< Home

Alright, first of all, this is the first I’ve solved with zero looking up on the internet. So I’m super ecstatic! For this challenge we needed to login again on the server and saw the following files.

random@pwnable:~$ ls -ls
total 20
 4 -r--r----- 1 random_pwn root     49 Jun 30  2014 flag
12 -r-sr-x--- 1 random_pwn random 8538 Jun 30  2014 random
 4 -rw-r--r-- 1 root       root    301 Jun 30  2014 random.c

Again I chose to completely ignore the random.c (and didn’t even peek later on) and just focused on the random file that would be able to read the flag file.

To also start learning how to use GDB I quickly opened Youtube and watched the Harvard ten minute intro into gdb. After that I downloaded a cheatsheet and I could start.

(gdb) disassemble main
Dump of assembler code for function main:
   0x00000000004005f4 <+0>:   push   rbp
   0x00000000004005f5 <+1>:   mov    rbp,rsp
   0x00000000004005f8 <+4>:   sub    rsp,0x10
   0x00000000004005fc <+8>:   mov    eax,0x0
   0x0000000000400601 <+13>:  call   0x400500 <rand@plt>
   0x0000000000400606 <+18>:  mov    DWORD PTR [rbp-0x4],eax
   0x0000000000400609 <+21>:  mov    DWORD PTR [rbp-0x8],0x0
   0x0000000000400610 <+28>:  mov    eax,0x400760
   0x0000000000400615 <+33>:  lea    rdx,[rbp-0x8]
   0x0000000000400619 <+37>:  mov    rsi,rdx
   0x000000000040061c <+40>:  mov    rdi,rax
   0x000000000040061f <+43>:  mov    eax,0x0
   0x0000000000400624 <+48>:  call   0x4004f0 <__isoc99_scanf@plt>
   0x0000000000400629 <+53>:  mov    eax,DWORD PTR [rbp-0x8]
   0x000000000040062c <+56>:  xor    eax,DWORD PTR [rbp-0x4]
   0x000000000040062f <+59>:  cmp    eax,0xdeadbeef
   0x0000000000400634 <+64>:  jne    0x400656 <main+98>
   0x0000000000400636 <+66>:  mov    edi,0x400763
   0x000000000040063b <+71>:  call   0x4004c0 <puts@plt>
   0x0000000000400640 <+76>:  mov    edi,0x400769
   0x0000000000400645 <+81>:  mov    eax,0x0
   0x000000000040064a <+86>:  call   0x4004d0 <system@plt>
   0x000000000040064f <+91>:  mov    eax,0x0
   0x0000000000400654 <+96>:  jmp    0x400665 <main+113>
   0x0000000000400656 <+98>:  mov    edi,0x400778
   0x000000000040065b <+103>: call   0x4004c0 <puts@plt>
   0x0000000000400660 <+108>: mov    eax,0x0
   0x0000000000400665 <+113>: leave
   0x0000000000400666 <+114>: ret

This is what GDB produced after I set the disassembler syntax to intel. It provides less information than Ghidra at first view but diagonally looking through assembly and getting a general idea of what the code does is starting to feel very normal. It seemed that at the start a random number would be generated, a bit later on it expects input from the user and after that it XOR’s it with the random number and is expected to be the value of 0xDEADBEEF!

First let us open up the documentation of rand. The important part is that rand isn’t really that random. Like many random applications the function actually can be made predicable, so companies try to generate randomness out of world events (Cloudflare for example creates a random seed out of a wall of lava lamps, Random.org uses radio signals from atmospheric events,…). The documentation of rand tells us that you should srand before rand to set a different seed. if the programmer doesn’t do this than rand will set its seed to 1. When looking at our function I noticed nowhere is srand called so rand has a seed of 1. Let us write a small program that outputs rand and showcase how bad rand actually is.

First random run One long minute later

This program generates 9 random numbers, I’ve ran it twice but because the seed is not set and defaults to one we get… not so random numbers! These numbers will also be the same on any machine that uses the default rand library. I’ve tested it by running it on Godbolt and some other C online compilers.

So now we know that 1804289383 XOR userinput should be equal to 0xDEADBEEF. XORing works both ways so when we XOR 1804289383 with 0xDEADBEEF we will get our answer!

Thanks Python

When scooping through GDB I also checked what scanf was expecting and the string stored in 0x400760 was “%d” so we don’t need to do any conversion as scanf will do it for us!

And that was it! Not so hard!

< Home