문제의 소스코드는 다음과 같다.

#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

hashcode = 0x21DD09EC 이다.

if문을 통해 hashcode 와 check_password 함수에 결과값을 통해 비교하여 같으면 플래그를 획득할 수 있다.

먼저 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 형으로 변환 시키는 것을 볼 수 있으며 4byte(정수 바이트) 씩 나누어 5번 res에 더해주는 것을 확인할 수 있다.

그럼 단순하게 Hashcode 를 5번 나누어 계산을 하면 되지 않을까 싶어서 나누기 5를 하고 다시 곱해보니 hash 코드 값과 같지 않았다. ( 소수 점으로 내려간다.. )

나온 결과값 21DD09E8 과 hash 코드 값에 차는 다음과 같이 나온다.

0x4 만큼 차이가 나오는 것을 확인할 수 있다.

그렇다면 같은 hash code가 나오게 하려면

0x6C5CEC8 * 4 + 0x6C5CECC  같이 연산을 하면 될 것이다.

// 0x6C5CECC 는 0x5CEC8 + 0x4 값과 같다.

이를 통하여 pwntools 을 활용하여 exploit 코드를 짜봤다.

from pwn import *

p = ssh ('col', 'pwnable.kr',2222, 'guest')
# --> SSH 접속

path = './col'
#--> 경로 파일

argv = p32(0x06C5CEC8) * 4 + p32(0x6c5cecc)#0x06C5CEC8 * 4 + 0x06C5CECC# --> Little Endian 방식

payload = [path, argv]

s = p.run(payload)
# --> 프로그램 실행

s.interactive()

이를 통해 exploit을 실행하면 flag을 얻을 수 있다.