Source
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #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; } | cs |
col 프로그램 조건은 인자로 전달되는 argv[1] 문자열 길이 20바이트 조건이 충족되야 한다.
check_password() 함수에 전달되는 인자는 char형이지만 함수내에서 int 형으로 형변환을 한다.
char형에서 int형으로 형변환이 되어 루프문에서 4byte씩 증가하게된다.
인자로 전달받은 값이 5번의 반복문이 끝난 값이 0x21DD09EC이면 system()함수가 실행 된다.
이 문제 접근방법은 check_password() 함수 인자값으로 0x21DD09EC / 5 값을 전달하여 루프문에서 누적 시키면 된다.
그러나 0x21DD09EC / 5 결과값을 5회 누적시키면 hashcode 보다 작은 값이 나온다.
In [1]: hex(0x21DD09EC/5) Out[1]: '0x6c5cec8' In [2]: hex(0x6c5cec8*5) Out[2]: '0x21dd09e8'
0x21DD09EC/5 연산 시 나머지 값이 0x4가 남게 되어 발생되는 문제로 생각 된다.
In [10]: hex(0x6c5cec8*4)
Out[10]: '0x1b173b20'
In [11]: hex(0x21DD09EC-0x1b173b20)
Out[11]: '0x6c5cecc'
In [12]: hex(0x6c5cec8*4+0x6c5cecc)
Out[12]: '0x21dd09ec'
col@ubuntu:~$ ./col `python -c 'print "\xc8\xce\xc5\06"*4+"\xcc\xce\xc5\x06"'`
daddy! I just managed to create a hash collision :)