Code Challenge – Pwnable.kr Collision

This code challenge can be found on Pwnable.kr Collision. If you are interested in security and programming head over and check out there webpage
This is a write up of the solution to Collision

Find out where you are

logging onto the server we do a quick ls -l to see what we are working with.

col@ubuntu:~$ ls -l
total 16
-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

This shows us now  a few things. 1st  user col can read and execute col but can not write to it. col can read col.c but not edit it. 2nd col can not read write or execute flag.  3rd col.c is run as root and can read flag.

So lets see what we can see. vim col.c returns:

col.c

Code breakdown

As you can see from the highlighted code, the password length needs to be 20 bytes. How can we represent a single number as 20 bytes though. Well the program gives you a hint in the functioncheck_password. It is looking for 5 int’s. This is explained with some basic computer math we know one int is 4 bytes (check size of int) therefore we know we need 5 integers then the numbers are added to together and passed the logic that outputs flag. The hash we are looking for is 0x21DD09EC To obtain the flag we need to input a this value into the program. Let’s find 5 integers that are in total equal to 0x21DD09EC:

Python 2.7.10
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 0x21DD09EC
568134124
>>> 568134124 / 5
113626824
>>> 568134124 - 4 * 113626824
113626828
>>> 4 * 113626824 + 113626828
568134124

Hey hey he what did we just do there. ok lets take it step by step.

First we opened python and converted 0x21DD09EC to an in 568134124

Next we devided 568134124 by 5 giving us 113626824

So why did we not stop there were have 5 values. Well that is not intirely true, we have a truncated value. 568134124 /5 is actually 113626824.8 so wee need our last value.

568134124 – 4*113626824  giving us 113626828

Checking our results

Let’s check  4 * 113626824 + 113626828 equals 0x21DD09EC.
Next step is to convert the integers to bytes.  It is not that easy as typing it in python.  It is good to note that C integers are stored in little-endian format (meaning byte order is reversed).

I needed a little google foo to find out how to convert I use struct.pack to convert integers to the little-endian. The first argument of struct.pack(the format of the conversion) consists of two parts: < means that the bytes need to be in little-endian order, and i means that it needs to be converted to the size of an int.

>>> import struct
>>> 4 * struct.pack('<i', 113626824) + struct.pack('<i', 113626828)
'\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xcc\xce\xc5\x06'

lets input our result and see if we are right:

col@ubuntu:~$ ./col '\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xcc\xce\xc5\x06'
passcode length should be 20 bytes

Hum ok what is wrong. The next step really gave me a hard time. Since we have hex values they are not translating correctly into the program

take a look at how we can pass a value correctly to strlen(argv[1]) != 20 and identify how we can pass argv as a string and still be 20 bytes. Doing some more google foo we need to pass the string as its binary representation to col so we can use echo -e acording to the documentation -e will enturprate \xHH to the Hexadecimal value HH

col@ubuntu:~$ ./col `echo -e "\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xc8\xce\xc5\x06\xcc\xce\xc5\x06"` 
daddy! I just managed to create a hash collision 🙂

And we did it. Congratulations.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.