Pwnable.kr collision
Mar 26, 2016 · Wargame
col@ubuntu:~$ ls
col col.c flag
col@ubuntu:~$ cat col.c
#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의 값을 비교하는데, 사용자가 입력한 char배열의 값이 check_password에 들어가 검사를 하게 된다.
char배열이 들어갔지만, int*로 캐스팅하여 사용한다. 이때 리틀엔디안
을 신경써서 넣어야 한다.
값이 0x01020304
라 하여도, 실제로 메모리에 들어간 정보를 보면 0x04
0x03
0x02
0x01
순서로 들어가게 된다.
그러므로 값을 넣을 때에도 순서를 반대로 해 주어야 한다. int형 이기 때문에 4byte씩 묶여서 더하기가 된다. 그러므로 4byte씩 잘라서 넣어주어야 한다.
하지만 NULL
문자는 처리를 하지 못하므로 최소 1의 값을 넣어주어야 한다. 0x01010101을 4번 넣고 원하는 값을 넣어주면 총 20byte의 값이 된다.
원하는 값은 0x21DD09EC - 0x0404040 (0x01010101을 4번 넣었기 때문)을 해준 값으로, 0x1DD905E8을 넣어주면 된다. 하지만 리틀엔디안 형식이므로 값을 거꾸로 넣어 0xE805D91D
를 넣어 주면 된다.
col@ubuntu:~$ ./col `python -c 'print "\x01" * 16 + "\xE8\x05\xD9\x1D"'`
daddy! I just managed to create a hash collision :)