이번엔 collision이라는 문제를 풀 것입니다.
우분투 터미널에
ssh col@pwnable.kr -p2222
를 입력하고
패스워드는 guest
풀이
당연히 cat flag는 안되고
col.c를 보면
이렇게 되어있습니다.
아무래도
MD5 해시 충돌에 대한 문제라고 하는데
MD5는 해시 충돌로 인해 취약한 해싱함수이고
해시함수는 충돌이 없어야하는데~~ 대충 이런 개념을 이용해서
원래 값과 같은 값으로 충돌을 일으키는 문제인듯 합니다.
소스코드를 해석해보면.
main함수에서 인자를 받고. 인자의 사이즈(문자열의 길이)는 20byte여야 합니다.
그리고 hashcode라는 값과 check_password라는 함수에 인자를 넣은 결과가 같으면 플래그를 출력해주네요.
hashcode는
0x21dd09ec라는 값이고
check_password에서는 약간의 포인터 지식이 필요한데.
예를들어 문자열 "ABCD"를 입력할 때,
argv는 char *argv[]이므로 argv[1]에는 "ABCD"를 가리키는 포인터가 들어있고
그걸 인자 p로 전달합니다.
ip라는 포인터는 p를 int형으로 읽어들이려고 만든 포인터이고.
ip[i]를 넣는다는건 ip를 4byte 단위로 읽어들인 값을 res에 더하겠다는 뜻이고 그 더한 값들을 출력한다는 것입니다.
여기서 주의할 점은 little endian으로 메모리에 들어가있어서
"ABCD"가 있으면 (A = 0x41)
메모리에는 0x44434241로 거꾸로 들어가게 됩니다.
근데 4byte로 읽어들이면 0x44434241이라는 숫자로 받아들이는 것 .
결론적으로 우린,
더해서 0x21dd09ec가 되도록 하여 20byte문자열을 넣어야 합니다.
그럼 5번의 기회가 주어지죠 4byte씩 쪼갰으니까.
처음에는 0x21dd09ec를 5로 나눈 몫을 4번 넣고 나머지를 1번 넣으려고 했는데.
\x00 (null)이 있는 순간 strlen에 의해서 문자열 사이즈가 작은 것이 되므로
그냥 1번의 기회(4byte)를 0x11111110으로 확보해두고 4로 나누었습니다.
0x21dd09ec에서 0x11111110을 빼면 4로 나누어떨어지기 때문
윈도우에서 프로그래머용 계산기 써서
이렇게 하고
그러면 exploit 할 때에는
문자열이 거꾸로 들어가야 한다는 점에 유의해서
이렇게 하면 됩니다.
짜잔.