Toddler's Bottle #02 - collision (3 pt)

포너블 2번 문제인 collision 입니다.

Daddy told me about cool MD5 hash collision today.

I wanna do something like that too!

MD5 해시 충돌에 대해 이야기하고 있습니다.


MD5 Hash Collision 이란? 

(풀고 보니 큰 상관은 없는 내용입니다)

-> 본래 암호학적으로 안전한 해시함수란 역상 저항성, 제 2 역상 저항성, 충돌 저항성을 만족해야합니다.

어떤 해시함수 h가 있다고 합시다.

- 역상 저항성 : h(x) = y에서, y를 알더라도 x를 알아내기 어렵다.

- 제 2 역상 저항성 : h(x1) = y에서, h(x2) = y인 x2를 알아내기 어렵다.

- 충돌 저항성 : h(x1) = h(x2)인 (x1, x2) 쌍을 알아내기 어렵다.

-> MD5 라는 해시 함수에서 collision을 아주 쉽게 찾아낼 수 있는 취약점이 보고된 바 있습니다. (알고리즘 자체의 결함)


ssh col@pwnable.kr -p2222로 접속했습니다. (pw : guest)

ls -al로 살펴보니 지난 문제 fd와 같이 col에 setuid가 걸려있습니다. 

col의 취약점으로 상위 권한을 따서 flag를 볼 수 있는 것입니다.


cat col.c로 col의 소스코드를 살펴보겠습니다.

전역변수로 선언된 hashcode라는 변수에는 0x21DD09EC라는 값이 들어가 있습니다.

check_password 함수에서는 인자로 p를 입력받습니다.

그 후에 인자로 받은 p배열의 int 값(4바이트)을 인덱스를 이동하면서 5번 더해줍니다.  (4 bytes * 5 =20 bytes)

그 값을 res에 저장하고 res를 리턴합니다.

main 함수에서 인자로 받은 20바이트 값을 check_password에 전달한 후, 

check_password의 리턴값과 hashcode의 값이 같을 때 flag를 볼 수 있게 되어 있습니다.



즉 check_password에 전달할 때 4바이트씩 5번 더하기 때문에

0x21DD09EC 값을 다섯개로 나누어서 넣어주면 되겠습니다.

0x21DD09EC = 568134124 = 113626824 * 4 + 113626828 = 0x06C5CEC8 * 0x4 + 0x06C5CECC


값을 넣을 때 주의할 점!

반드시 리틀 엔디안(Little Endian) 방식으로 넣어주어야 합니다.


리틀 엔디안(Little Endian) 방식이란?

-> 컴퓨터 공간에 연속적인 데이터를 바이트단위로 저장하는 방식을 뜻합니다.

-> 리틀 엔디안, 빅 엔디안, 미들 엔디안 방식이 있습니다.

- 리틀 : 작은 단위의 바이트가 앞에 옵니다. ex) 0x12345678 --> 78 56 34 12

x86 아키텍처에서 이 방식을 사용하기 때문에 대부분의 컴퓨터는 리틀 엔디안 방식으로 저장합니다. --> 인텔 포맷

- 빅 : 사람이 쓰는 방법과 동일하게 큰 단위의 바이트가 앞에 옵니다. ex) 0x12345678 --> 12 34 56 78

네트워크에서는 주소를 빅 엔디안 방식으로 사용합니다.

- 미들 : 그 외의 방식들입니다.

출처 : https://ko.wikipedia.org/wiki/엔디언


인자로 16진수 전달하는 법

-> main함수의 인자를 받을 때는 보통 문자열 형태로 받습니다.

-> 따라서 아스키(ASCII)코드로 값이 들어가기 때문에 실제 값 자체를 넣어주기 위해서는 다른 방법이 필요합니다.

-> 그래서 쓰는 것이 바로 백틱(backtick, `)입니다. 백틱 사이에 넣는 모든 것들은 메인 함수 전에 쉘에 의해 실행됩니다.

-> 파이썬 문법이나 펄 문법이 문자열을 다루기 편하게 되어있기 때문에 python -c 나 perl -e를 붙여서 값을 전달해줍니다.

ex) 0x12341234를 리틀 엔디안 방식으로 전달하려 한다. --> ./program `python -c 'print "\x34\x12"*2'`


./col `python -c 'print "\xC8\xCE\xC5\x06"*4+"\xCC\xCE\xC5\x06"'` 

이렇게 넣어주면 check_password에서 리턴하는 값은 0x21DD09EC가 될 것입니다.

cat flag가 실행되어 flag를 볼 수 있습니다.


FLAG : daddy! I just managed to create a hash collision :)



1-02 fin.



+ Recent posts