WAR GAME/pwnable.kr

[pwnable.kr] collision 문제풀이

jir4vvit 2020. 3. 5. 16:05

사용 툴: cygwin

 

1) 문제

collision 문제

아빠가 오늘 나에게 멋진 MD5 해시 충돌에 대해서 알려줬어

나도 해보고 싶어!

 

 

2) 문제풀이

먼저 ssh col@pwnable.kr -p2222 로 접속한다.

비밀번호는 guest이다.

col@pwnable:~$ ls -al
total 36
drwxr-x---   5 root    col     4096 Oct 23  2016 .
drwxr-xr-x 116 root    root    4096 Nov 12 21:34 ..
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:~$ 

flag는 권한이 없어서 보지 못한다.

col.c는 실행파일 col의 코드일 것 같아서 col.c를 열어보았다.

 

col@pwnable:~$ 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;
}
col@pwnable:~$

코드..

 

main문을 먼저 살펴보면 세번째 if문에서 hashcode와 check_password(argv[1])이 같으면 flag를 내놓는 듯하다.

그리고 두번째 if문에 나타나있다시피 argv[1]은 20바이트가 되어야 한다.

 

check_password 함수를 살펴보겠다.

파라미터는 내가 입력한 문자열이다.

unsigned long check_password(const char* p){  //파라미터 p는 내가 입력한 문자열 20바이트
        int* ip = (int*)p;  //내가 입력한 문자열 p의 타입을 int로 바꿈
        int i;
        int res=0;
        for(i=0; i<5; i++){  //20바이트 문자열을 4바이트씩 나누어서 5번 끊어서 res에 저장함
                res += ip[i];
        }
        return res; //res를 반환
}

포인터변수는 4바이트기 때문에 

res = ip[0] + ip[1] + ip[2] + ip[3] + ip[4]

ip[i]는 4바이트씩 떨어져 있다. (그래서 res가 20바이트가 될 수 있다)

 

정리해보면 우리는 0x21DD09EC를 5번에 나누어서 입력값에 넣어야한다.

0x21DD09EC / 5 = 0x6C5CEC8

 

하지만

0x6C5CEC8 * 5 = 0x21DD09E8 로 hashcode와 0x4가 차이난다.

 

결론은...

0x6C5CEC8 * 4 + 0x6C5CECC‬ 이렇게 프로그램에 입력값으로 넣어줘야 한다.

 

마지막으로 고려해야할 것이 우리는 little endian을 따르고 있음으로 little endian으로 16진수 값으로 전달해야한다.

 

col@pwnable:~$  ./col `python -c 'print "\xC8\xCE\xC5\x06"*4+"\xcc\xce\xc5\x06"'`
daddy! I just managed to create a hash collision :)
col@pwnable:~$

FLAG : daddy! I just managed to create a hash collision :)

'WAR GAME > pwnable.kr' 카테고리의 다른 글

[pwnable.kr] fd 문제풀이  (0) 2020.03.03