[Pwnable.kr] collision 풀이문서

mj·2023년 1월 20일
0
post-thumbnail

collision 풀이문서

접속

아래 코드를 사용하여 문제에 접속한다.

$ ssh col@pwnable.kr -p2222
pw : (guest)

파일 확인

파일 목록 확인

col@pwnable:~$ ls -al
total 36
drwxr-x---   5 root    col     4096 Oct 23  2016 .
drwxr-xr-x 117 root    root    4096 Nov 10 02:06 ..
d---------   2 root    root    4096 Jun 12  2014 .bash_history
-r-sr-x---   1 col_pwn col     7341 Jun 11  2014 col
-rw-r--r--   1 root    root     555 Jun 12  2014 col.c
-r--r-----   1 col_pwn col_pwn   52 Jun 11  2014 flag
dr-xr-xr-x   2 root    root    4096 Aug 20  2014 .irssi
drwxr-xr-x   2 root    root    4096 Oct 23  2016 .pwntools-cache

col 파일 확인

col@pwnable:~$ file col
col: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=05a10e253161f02d8e6553d95018bc82c7b531fe, not stripped

col.c 파일 내용 확인

#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;
}
  • 프로그램에 넘겨지는 인자값이 2개 이상인지 확인하고 있다.
  • 첫번째 인자값의 길이가 20인지 확인하고 있다.
  • hashcode 와 check_password( argv[1] ) 의 값을 비교해서 값이 같으면 flag 를 출력한다.

파일 분석

아래 코드를 보면 hashcode 와 check_password( argv[1] ) 의 값을 비교하고 있다.

	if(hashcode == check_password( argv[1] )){
		system("/bin/cat flag");
		return 0;
	}

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 * 타입으로 강제 형 변환하고 있다.
두 포인터의 차이점은 특정 주소에서 읽어오는 바이트의 수이다.
char * 형 변수는 값을 읽어올 떄 1바이트씩 읽어오고
int * 형 변수는 값을 읽어올 때 4바이트씩 읽어온다.

int * 형으로 변환된 ip에서 5번 반복을 통해 읽어온 값을 res 에 저장하고 있다.

5번 반복을 하니까 총 20바이트를 읽어온다고 할 수 있다.
main 함수에서 첫번째 인자의 길이를 20바이트로 제한한 이유가 이 때문인 것 같다.

인자값의 각 4바이트 씩 더한 값이 hashcode 값인 0x21DD09EC가 되도록 하면 될 것 같다.

0x21DD09EC = 568134124 = 0x06C5CEC8‬ * 4 + 0x06C5CECC

exploit

col@pwnable:~$ ./col `python -c 'print "\xc8\xce\xc5\x06" * 4 + "\xcc\xce\xc5\x06"'`
daddy! I just managed to create a hash collision :)
  • flag : addy! I just managed to create a hash collision :)
profile
사는게 쉽지가 않네요

0개의 댓글