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 형으로 형변환을 한다.


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형에서 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'


In [3]: hex(0x21DD09EC-0x21dd09e8) Out[3]: '0x4'


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'



위 연산으로 hashcode를 생성 하면 된다.  0x21DD09EC를 5로 나눈 몫 0x6c5cec8을 4번 곱하고 0x6c5cecc 더하면 hashcode 값이 나온다. 


col@ubuntu:~$ ./col `python -c 'print "\xc8\xce\xc5\06"*4+"\xcc\xce\xc5\x06"'`

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



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

random  (0) 2016.11.27
passcode  (0) 2016.11.27
flag  (0) 2016.11.27
bof  (0) 2016.11.15
fd  (0) 2016.11.09

+ Recent posts