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.
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!
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!