아래 코드를 사용하여 문제에 접속한다.
$ ssh col@pwnable.kr -p2222
pw : (guest)
col@pwnable:~$ ls -al
total 36
drwxr-x--- 5 root col 4096 Oct 23 2016 .
drwxr-xr-x 117 root root 4096 Nov 10 02:06 ..
d--------- 2 root root 4096 Jun 12 2014 .bash_history
-r-sr-x--- 1 col_pwn col 7341 Jun 11 2014 col
-rw-r--r-- 1 root root 555 Jun 12 2014 col.c
-r--r----- 1 col_pwn col_pwn 52 Jun 11 2014 flag
dr-xr-xr-x 2 root root 4096 Aug 20 2014 .irssi
drwxr-xr-x 2 root root 4096 Oct 23 2016 .pwntools-cache
col@pwnable:~$ file col
col: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=05a10e253161f02d8e6553d95018bc82c7b531fe, not stripped
#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;
}
check_password( argv[1] )
의 값을 비교해서 값이 같으면 flag 를 출력한다.아래 코드를 보면 hashcode 와 check_password( argv[1] )
의 값을 비교하고 있다.
if(hashcode == check_password( argv[1] )){
system("/bin/cat flag");
return 0;
}
check_password 함수를 분석해보자
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;
}
첫번째 줄에서 char *
타입의 p 를 int *
타입으로 강제 형 변환하고 있다.
두 포인터의 차이점은 특정 주소에서 읽어오는 바이트의 수이다.
char *
형 변수는 값을 읽어올 떄 1바이트씩 읽어오고
int *
형 변수는 값을 읽어올 때 4바이트씩 읽어온다.
int *
형으로 변환된 ip에서 5번 반복을 통해 읽어온 값을 res 에 저장하고 있다.
5번 반복을 하니까 총 20바이트를 읽어온다고 할 수 있다.
main 함수에서 첫번째 인자의 길이를 20바이트로 제한한 이유가 이 때문인 것 같다.
인자값의 각 4바이트 씩 더한 값이 hashcode 값인 0x21DD09EC가 되도록 하면 될 것 같다.
0x21DD09EC = 568134124 = 0x06C5CEC8 * 4 + 0x06C5CECC
col@pwnable:~$ ./col `python -c 'print "\xc8\xce\xc5\x06" * 4 + "\xcc\xce\xc5\x06"'`
daddy! I just managed to create a hash collision :)