[pwnable.kr] collision

이동화·2025년 7월 17일

풀이

#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] )){
                setregid(getegid(), getegid());
                system("/bin/cat flag");
                return 0;
        }
        else
                printf("wrong passcode.\n");
        return 0;
}

소스 코드를 보면, argv로 길이 20짜리 인자를 받고, 해당 인자를 check_password 함수에 넣어 hashcode와 값이 같은지 비교 후, fd 문제처럼 권한 상승을 통해 flag를 읽고 출력한다.
그런데 hashcode라는게 md5나 sha를 쓰는 것이 아닌 단순하게 for문을 통해 입력값들을 더하고만 앉아있다.

이런 경우는 해시 충돌을 발생시키기 더욱 쉬운 구조로, for문의 정확한 구조는 길이 20짜리 문자열을 5개로 나누어 int값으로 변환 후 전부 다 더한 값이다. 해당 값이 0x21dd09ec와 같으면 되기 때문에 조건을 만족하는 값이어야 한다.
그러나, argv[1]을 strlen속에 넣기 때문에 \x00이 포함되는 순간 strlen은 그 이후 바이트를 읽지 못하기 때문에 argv[1]로 \x00이 포함되지 않도록 구성해야 한다.

위 코드를 write 권한이 있는 tmp 디렉토리에서 생성하고
이를 col 디렉토리에서 실행해주면 flag를 볼 수 있다. (col 디렉토리의 flag를 읽고 싶기 때문)

flag : Two_hash_collision_Nicely

profile
notion이 나은듯

0개의 댓글