이번에 풀이할 문제는 pwnable.kr의 collision 문제다. 이 문제 역시 fd와 마찬가지로 putty에서 풀이했다.
서버에 접속한 후 ls 명령어를 사용해보니 col, col.c, flag가 존재하는 것을 알 수 있다. 이 문제 역시 col 프로그램을 풀면 flag를 읽어 출력해줄 것 같다.
일단 주어진 프로그램인 col을 실행해봤다. 여러 번 실행해봤을 때 이 프로그램은 인자가 필요하고, 이 인자는 20byte 크기의 passcode로 이 passcode가 일치해야지 flag을 읽어준다는 것을 추측할 수 있다.
#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++){ // 5번 반복하며 각 문자열의 정수 값을 res에 더함
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){ // 인자의 문자열 길이가 20이 아니라면
printf("passcode length should be 20 bytes\n");
return 0;
}
if(hashcode == check_password( argv[1] )){ // hashcode와 check_password 함수의 리턴 값이 일치할시
system("/bin/cat flag");
return 0;
}
else
printf("wrong passcode.\n");
return 0;
}
위는 col.c에 적혀있던 코드들이다. 입력 값을 정수형 배열로 변환한 후 5번 반복하며 각 인덱스의 값을 res에 더해준 후 그 값을 hashcode(0x21DD09EC)와 비교한다. 같을시 flag를 출력하고, 다를시 wrong passcode를 출력한다.
5번 반복해서 입력 값을 더해주기 때문에 hash 값인 0x21DD09EC를 5로 나눈 값을 5번 넣어주면 될 것 같다.
0x21DD09E8을 5로 나눈 값을 0x6C5CEC8이다. 이 값을 5번 넣으면 될 줄 알았지만 함정이 있었다.
0x6c5CEC8을 5번 곱해주면 0x21DD09E8보다 4 부족한 0x21DD09E8이 나온다. 따라서 0x6C5CEC8을 5개를 넣는게 아닌 0x6C5CEC8을 4개 + 0x6C5CECC(0x6C5CEC8+4)을 인자로 주면 된다.
0x6C5CEC8 * 4 + 0x6C5CECC을 파이썬을 이용해 리틀 엔디안으로 넣어주니 flag 값을 얻게 됐다.
'Wargame > Pwnable.kr' 카테고리의 다른 글
pwnable.kr [random] (0) | 2021.04.08 |
---|---|
pwnable.kr [leg] (0) | 2021.04.08 |
pwnable.kr [flag] (0) | 2021.04.08 |
pwnable.kr [bof] (0) | 2021.04.04 |
pwnable.kr [fd] (0) | 2021.04.01 |