MD5 hash collision(해시 충돌)
해시 충돌이란 어떤 해시 함수가 서로 다른 두 입력에 대해 동일한 출력 값을 나타내는 경우를 말한다.
보통 해시 함수는 다수의 데이터가 있을 때 이들을 구별하고 특정 데이터의 검색을 빠르게 하기 위해 사용되는데, 이 때문에 해시 충돌이 많이 일어나는 해시 함수일수록 그 질이 낮다고 평가된다.
출처: https://medium.com/shell-tharsis/hash-collision-5891d7dde54f
문제의 flag를 보면 col_pwn만 접근할 수 있다.
col.c 파일을 보자
./col passcode
1. passcode는 20바이트(160비트) -> md5는 128비트(16바이트)인데? sha1이 160비트인데
2. 0x21DD09EC와 check_password 함수 결과값이 같으면 (해시 충돌) flag 확인가능하다.
check_password 함수
p 문자열의 주소값을 입력받아서 4바이트씩(int*) 5번 읽어 리턴한다 (20바이트 리턴)
p에 값을 입력해야하고, 이것을 4바이트씩 5번 읽어서 더한 값이 hashcode 값과 같으면 된다.
(실제 충돌되는 해시값을 구하는 것이 아닌 합만 만드는 문제, 그래서 16바이트가 아닌 20바이트, 해시함수 사용 안하는 이유)
0x21DD09EC을 5개로 쪼개기
값을 5로 나누어보면 0x6C5CEC8이 나온다. 그런데 이 값을 5번 곱해보면 0x21DD09E8이 나오므로 4만큼 마지막 숫자에 더해주면 된다.
즉, 0x06C5CEC8 4번, 0x06C5CECC 1번
쉘 스크립트 실행하는 방법 : $()
./col $() <- () 쉘 스크립트 만들기
command를 실행할때 python -c (-c는 command)를 많이 사용하는 것 같다.
./col $(python -c 'print "a"*4')
endian 확인
운영체제마다 환경마다 big endian, little endian이 다르다고 한다.
내 리눅스 환경에서는 little endian이다.(맥 터미널도 little endian)
big endian
메모리에 저장된 순서 그대로 읽을 수 있다.
little endian
평소 우리가 숫자를 사용하는 선형 방식과는 반대로 거꾸로 읽어야 한다.
출처: http://www.tcpschool.com/c/c_refer_endian
리틀 엔디안이므로 거꾸로 입력하자.
- 0x06C5CEC8 4번, 0x06C5CECC 1번
- 4바이트씩(int*) 5번 읽어 리턴
16진수는 수 하나당 4비트를 나타내므로 두 글자마다 1바이트이다. 숫자 두개씩 쪼개기
./col $(python -c 'print "\xc8\xce\xc5\x06"*4 + "\xcc\xce\xc5\x06"')
진짜 오래걸렸다..
질문
./col $(python -c 'print "\xc8\xce\xc5\x06"*4 + "\xcc\xce\xc5\x06"')
왜 한바이트씩 끊어서 print 하나요?
답변
컴퓨터는 데이터를 메모리에 저장할 때 바이트(byte) 단위로 나눠서 저장하기 때문입니다.
출처: http://www.tcpschool.com/c/c_refer_endian
'보안공부 > 시스템 해킹' 카테고리의 다른 글
pwnable 3번: bof (2) | 2023.01.30 |
---|---|
pwnable 1번 : fd (0) | 2023.01.30 |
MD5 hash collision(해시 충돌)
해시 충돌이란 어떤 해시 함수가 서로 다른 두 입력에 대해 동일한 출력 값을 나타내는 경우를 말한다.
보통 해시 함수는 다수의 데이터가 있을 때 이들을 구별하고 특정 데이터의 검색을 빠르게 하기 위해 사용되는데, 이 때문에 해시 충돌이 많이 일어나는 해시 함수일수록 그 질이 낮다고 평가된다.
출처: https://medium.com/shell-tharsis/hash-collision-5891d7dde54f
문제의 flag를 보면 col_pwn만 접근할 수 있다.
col.c 파일을 보자
./col passcode
1. passcode는 20바이트(160비트) -> md5는 128비트(16바이트)인데? sha1이 160비트인데
2. 0x21DD09EC와 check_password 함수 결과값이 같으면 (해시 충돌) flag 확인가능하다.
check_password 함수
p 문자열의 주소값을 입력받아서 4바이트씩(int*) 5번 읽어 리턴한다 (20바이트 리턴)
p에 값을 입력해야하고, 이것을 4바이트씩 5번 읽어서 더한 값이 hashcode 값과 같으면 된다.
(실제 충돌되는 해시값을 구하는 것이 아닌 합만 만드는 문제, 그래서 16바이트가 아닌 20바이트, 해시함수 사용 안하는 이유)
0x21DD09EC을 5개로 쪼개기
값을 5로 나누어보면 0x6C5CEC8이 나온다. 그런데 이 값을 5번 곱해보면 0x21DD09E8이 나오므로 4만큼 마지막 숫자에 더해주면 된다.
즉, 0x06C5CEC8 4번, 0x06C5CECC 1번
쉘 스크립트 실행하는 방법 : $()
./col $() <- () 쉘 스크립트 만들기
command를 실행할때 python -c (-c는 command)를 많이 사용하는 것 같다.
./col $(python -c 'print "a"*4')
endian 확인
운영체제마다 환경마다 big endian, little endian이 다르다고 한다.
내 리눅스 환경에서는 little endian이다.(맥 터미널도 little endian)
big endian
메모리에 저장된 순서 그대로 읽을 수 있다.
little endian
평소 우리가 숫자를 사용하는 선형 방식과는 반대로 거꾸로 읽어야 한다.
출처: http://www.tcpschool.com/c/c_refer_endian
리틀 엔디안이므로 거꾸로 입력하자.
- 0x06C5CEC8 4번, 0x06C5CECC 1번
- 4바이트씩(int*) 5번 읽어 리턴
16진수는 수 하나당 4비트를 나타내므로 두 글자마다 1바이트이다. 숫자 두개씩 쪼개기
./col $(python -c 'print "\xc8\xce\xc5\x06"*4 + "\xcc\xce\xc5\x06"')
진짜 오래걸렸다..
질문
./col $(python -c 'print "\xc8\xce\xc5\x06"*4 + "\xcc\xce\xc5\x06"')
왜 한바이트씩 끊어서 print 하나요?
답변
컴퓨터는 데이터를 메모리에 저장할 때 바이트(byte) 단위로 나눠서 저장하기 때문입니다.
출처: http://www.tcpschool.com/c/c_refer_endian
'보안공부 > 시스템 해킹' 카테고리의 다른 글
pwnable 3번: bof (2) | 2023.01.30 |
---|---|
pwnable 1번 : fd (0) | 2023.01.30 |