[toddler's bottle] col

폭풍저그머성찡 ㅣ 2018. 11. 30. 18:19

#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;

}


① : 문자배열은 단위가 1바이트 정수배열은 단위가 4바이트이다. 따라서 이렇게 형변환을 하면 문자배열이 4자리씩 끊어서 들어가게 된다.


② : 아래에서 총 20문자를 받았으므로 이 함수는 문자 20바이트를 정수 4바이트 단위로 잘라서 총 값을 더해 결과를 반환하는 함수이다.


③ : 그렇게 해서 입력받은 값이 위의 hashcode변수와 같으면 플래그를 출력해준다.



여기까지만 보면 좀 복잡해보인다. 하지만 perl이 출동한다면 어떨까!


P!

E!

R!

L!


꿀잼



해공예를 보면 perl명령어를 사용하는 방법이 나와있다.


++ 해쉬코드는 unsigned로 선언되어있기 때문에 -hashcode = hashcode 크.. 이 정도면 ㄹㅇ 다 알려줌




우선 적당한 문자 하나를 4개 쓴다. 여기서 적당하게란 4개의 바이트에 0이 하나도 없는걸 말한다.


해쉬코드가 언사인드 변수이므로 121DD09EC, 221DD09EC . . 를  해쉬코드로 놓고 해도 같은 결과가 나온다. 


-> 8바이트짜리 unsigned 변수이므로 0xFFFFFFFF + 0x1 = 0x0임. 최댓값을 넘어가면 0으로 돌아오므로 9번째 비트부터는 의미가 없음


그냥 적당하게 121DD09EC를 놓고 했다. 


그리고 AAAA = 0x41414141이므로 4개를 입력하면 0x41414141 x 4 = 105050504이다.


121DD09EC - 105050504 = 1CD804E8 마지막 바이트에 저거만 입력해주면 끝난다.


따라서 payload는


./col $( perl -e 'print "AAAA" x 4 . "\xe8\x04\xd8\x1c"' ) 가 된다!





'write-up > pwnable.kr' 카테고리의 다른 글

[toddler's bottle] random  (0) 2018.11.30
[toddler's bottle] passcode  (0) 2018.11.30
[toddler's bottle] flag  (0) 2018.11.30
[toddler's bottle] bof  (0) 2018.11.30
[toddler's bottle] fd  (0) 2018.11.29