Pwnable.kr - random

Writeup for random in pwnable.kr.

0x00 Puzzle

Daddy, teach me how to use random value in programming!

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

0x01 Explore

ssh into the ubuntu and here we get:

$ ssh random@pwnable.kr 2222
random@ubuntu:~$ ls -l  
total 20  
-r--r----- 1 random_pwn root     49 Jun 30  2014 flag
-r-sr-x--- 1 random_pwn random 8538 Jun 30  2014 random
-rw-r--r-- 1 root       root    301 Jun 30  2014 random.c

Obviously, we need to pwn the random to cat the flag file.

Take a glance at the random.c:

#include <stdio.h>

int main(){  
    unsigned int random;
    random = rand();    // random value!

    unsigned int key=0;
    scanf("%d", &key);

    if( (key ^ random) == 0xdeadbeef ){
        printf("Good!\n");
        system("/bin/cat flag");
        return 0;
    }

    printf("Wrong, maybe you should try 2^32 cases.\n");
    return 0;
}

Basiclly we need to input an int key so that key ^ rand() == 0xdeadbeef.

I firstly considered using r2 to set breakpoint and looking at the value of random, let's do it.

$ r2 -d random
[0x7f13a99adcc0]> aaa
[0x7f13a99adcc0]> s main
[0x004005f4]> pdf

Here is the disassembling code of main function:

We can see that

  • @0x00400601 it calls the rand() and the random return value is stored in $eax.

  • @0x00400606 it move $eax to local variable random.

So we can set the breakpoint @0x00400606, then just look at the value of $eax.

[0x004005f4]> db 0x00400606
[0x004005f4]> dc
hit breakpoint at: 400606  
= attach 45875 1
[0x004005f4]> dr eax
0x6b8b4567  

We got that, which means if we input 0x6b8b4567 ^ 0xdeadbeef = 3039230856, it should work.

Let's try.

[0x004005f4]> dc
3039230856  
Good!  
/bin/cat: flag: Permission denied

Seems we got it worked but since it's running by gdb and the gdb is under our random user's priviledge which is not in root group.

So we have to run the binary in the home directory, but how can we know the rand() value without debugging it?

Then I run it many times in both gdb and r2 and I found that the value of rand() never changed.

That reminded me that this program do not even set seed before calling rand(), which means every time someone run the program, it always use the same seed, I guess it's 0, no wonder it's predictable.

0x02 Solution and things learned

Now that we know the thory, just run the random binary and input 3039230856:

random@ubuntu:~$ ./random  
3039230856  
Good!  
Mommy, I thought libc random is unpredictable...  

Got it.

This is pretty straightforward. It warns us do not just use rand() in critical secured project because it's predictable.
At least, set a changable seed value, like system time, before calling rand().