Let’s start another challenge from pwnable.kr called collision, which is next one in Toddler’s Bottle category.

Daddy told me about cool MD5 hash collision today.
I wanna do something like that too!

Once again we have to connect via ssh in order to view challenge files.

[email protected] ~ % ssh [email protected] -p2222
[email protected] password:
 ____  __    __  ____    ____  ____   _        ___      __  _  ____  
|    \|  |__|  ||    \  /    ||    \ | |      /  _]    |  |/ ]|    \
|  o  )  |  |  ||  _  ||  o  ||  o  )| |     /  [_     |  ' / |  D  )
|   _/|  |  |  ||  |  ||     ||     || |___ |    _]    |    \ |    /
|  |  |  `  '  ||  |  ||  _  ||  O  ||     ||   [_  __ |     \|    \
|  |   \      / |  |  ||  |  ||     ||     ||     ||  ||  .  ||  .  \
|__|    \_/\_/  |__|__||__|__||_____||_____||_____||__||__|\_||__|\_|

- Site admin : [email protected]
- IRC : irc.netgarage.org:6667 / #pwnable.kr
- Simply type "irssi" command to join IRC now
- files under /tmp can be erased anytime. make your directory under /tmp
- to use peda, issue `source /usr/share/peda/peda.py` in gdb terminal
Last login: Fri Nov 24 12:21:39 2017 from 24.16.85.95
[email protected]:~$ ls -la
total 36
drwxr-x---  5 root    col     4096 Oct 23  2016 .
drwxr-xr-x 80 root    root    4096 Jan 11  2017 ..
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

And without hesitation, let’s jump straight into the code.

#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;
}

Firstly int* ip = (int*)p; will cast the char, passed as the parameter into the check_password function. In addition we know that the passcode has to be 20 bytes. After doing simple mathematics, our input will have to consist of 5 integers, as the size of int is 4 bytes. What next?

Function will return the sum of these 5 integers, which is calculated by the loop. Back in the main function, this sum is checked for length, then compared with hash and if the answer is correct, it will view the flag for us.

Let’s convert hash into the decimal number.

>>> 0x21DD09EC
568134124

Great, now we can divide it into 5 pieces. But as the number is not divisible by 5, we’ll have to use floor division which will truncate numbers after decimal point.

>>> 0x21DD09EC // 5
113626824
>>> hex(113626824)
'0x6c5cec8'

Now let’s use these 4 pieces. We will substract them from the original hash, which will result in our fifth piece.

>>> 0x21DD09EC - 454507296
113626828
>>> hex(113626828)
'0x6c5cecc'

Will it be true? We can check it with simple comparision operation.

>>> 4 * 0x6c5cec8 + 0x6c5cecc == 0x21DD09EC
True

Great, our math worked out! Now we will only have to convert these hex values into little endian, as that’s how C stores integers. After that we’re ready to exploit this application.

[email protected]:~$ ./col $(python2 -c 'print "\xc8\xce\xc5\x06" * 4 + "\xcc\xce\xc5\x06";')
daddy! I just managed to create a hash collision :)