[MENU] | |||||||||
[THOUGHTS] | [TECH RESOURCES] | [TRASH TALK] | |||||||
[DANK MEMES] | [FEATURED ARTISTS] | [W] |
It is a really easy challenge but enjoyable.
When we look the source code, this line seems weird:
- random = rand(); // random value!
Let's check the description of rand() function.
- int rand(void):
- returns a pseudo-random number in the range of 0 to RAND_MAX.
- RAND_MAX: is a constant whose default value may vary
- between implementations but it is granted to be at least 32767.
But we can see that, it declared without a seed.
- The srand() function sets its argument as the seed for a new sequence of pseudo-random integers to be returned by rand().
- These sequences are repeatable by calling srand() with the same seed value.
- If no seed value is provided, the rand() function is automatically seeded with a value of 1.
So, it is generating the same number all the time. Easy solution would be inserting a printf() call and run the binary on your machine.
- unsigned int random;
- random = rand(); // random value!
- printf("%d", random);
- gcc source.c -o random
- $ ./random
- 1804289383
It yields the generated number now.
- if( (key ^ random) == 0xdeadbeef ){
We can XOR the generated number with 0xdeadbeef to get key.
- >>> 1804289383 ^ 0xdeadbeef
- 3039230856
- >>>
The result is our key.
- random@pwnable:~$ ./random
- 3039230856
- Good!
- Mommy, I thought libc random is unpredictable...
- random@pwnable:~$
The other way, let's assume that we dont own the source code. So, we will use a debugger.
- 0x00000000000011dd <+84>: call 0x1070 <__isoc99_scanf@plt>
-
- 0x00000000000011e2 <+89>: mov eax,DWORD PTR [rbp-0x10]
- 0x00000000000011e5 <+92>: xor eax,DWORD PTR [rbp-0xc]
- 0x00000000000011e8 <+95>: cmp eax,0xdeadbeef
- 0x00000000000011ed <+100>: jne 0x1213 <main+138>
- 0x00000000000011ef <+102>: lea rdi,[rip+0xe15] # 0x200b
- 0x00000000000011f6 <+109>: call 0x1030
- 0x00000000000011fb <+114>: lea rdi,[rip+0xe0f] # 0x2011
- 0x0000000000001202 <+121>: mov eax,0x0
- 0x0000000000001207 <+126>: call 0x1050 <system@plt>
After scanf() the binary compares two value (11e8: cmp eax, 0xdeadbeef), they are located at [rbp-0x10] and [rbp-0xc] We can put a breakpoint there and check these.
- gef➤ print $rbp-0x10
- $1 = (void *) 0x7fffffffe820
- gef➤ print *0x7fffffffe820
- $2 = 0x0
- gef➤ print $rbp-0xc
- $3 = (void *) 0x7fffffffe824
- gef➤ print *0x7fffffffe824
- $4 = 0x6b8b4567
- gef➤ print/d *0x7fffffffe824
- $5 = 1804289383
- gef➤
We got the same value again but at this time we grabbed that from our memory.