Daddy told me about cool MD5 hash collision today.
I wanna do something like that too!
ssh [email protected] -p2222 (pw:guest)
소스코드
#include <stdio.h> #include <string.h> unsigned long hashcode = 0x21DD09EC; unsigned long check_password(const char* p){ int* ip = (int*)p; int i; int res=0; for(i=0; i<5; i++){ res += ip[i]; } return res; } int main(int argc, char* argv[]){ if(argc<2){ printf("usage : %s [passcode]\n", argv[0]); return 0; } if(strlen(argv[1]) != 20){ printf("passcode length should be 20 bytes\n"); return 0; } if(hashcode == check_password( argv[1] )){ system("/bin/cat flag"); return 0; } else printf("wrong passcode.\n"); return 0; }
hashcode 변수에 0x21DD09EC 값이 들어있고,
check_password 함수에는 p 문자열을 가져와 int 형으로 강제 형변환시킨다.
int 형식의 크기는 4바이트이기에, 4바이트씩 5번 읽어들여 res에 더하고 반환한다.
그리고 메인 함수에는 인자가 없으면 usage를 출력하고,
1번째 인자길이가 20이 아니면 “passcode length should be 20 bytes” 메시지를 출력한다.
hashcode가 check_password(argv[1])의 리턴값과 서로 같으면 flag를 출력하고,
아니면 “wrong passcode.”를 출력한다.
풀이
5번 읽어들여 res에 더한 값들이 0x21DD09EC 값이 되어야 한다.
0x21DD09EC 값을 십진수로 변환하면 568134124이다.
568134124을 5번 나누면, 몫은 113626824이 되고 나머지는 4가 된다.
113626824를 16진수로 변환하면 0x6C5CEC8이 되고,
따라서 0x6C5CEC8를 4번 더하고, 나머지 4를 더한 0x6C5CECC를 1번 더하면 0x21DD09EC이 된다.
from pwn import * s = ssh('col', 'pwnable.kr', 2222, 'guest') argvs = ["./col", (p32(0x6c5cec8)*4 + p32(0x6c5cecc))] p = s.process(executable="./col", argv=argvs) data = p.recvall() print(data) p.close() s.close()
ubuntu@docker:~/CTF/pwnable.kr/collision$ python3 collision.py [+] Connecting to pwnable.kr on port 2222: Done [*] [email protected]: Distro Ubuntu 16.04 OS: linux Arch: amd64 Version: 4.4.179 ASLR: Enabled [+] Starting remote process bytearray(b'./col') on pwnable.kr: pid 104973 [+] Receiving all data: Done (52B) [*] Stopped remote process 'col' on pwnable.kr (pid 104973) b'daddy! I just managed to create a hash collision :)\n'