This is the write-up for the Third level of NoNameCon CTF Quals 2013.
In a nutshell, a Linux reversing challenge where the goal is to get the secret key:
$ file ./level.elf
./level.elf: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xb589d432799bf15343387fea63d4bdc00faa177c, not stripped
Running the executable, we are challenged to type a “password.”
$ ./level.elf
| > Type to win, only what I want to read…
| >
Clicking any key, will end the program with an error message.
$ ./level.elf
| > Type to win, only what I want to read…
| >
|
| -> I DON’T THINK SO
The related executable code starts at 0x4010f3 with the getch() call.
** 0x00000000004010f3 <+212>: call 0x400fef **
0x00000000004010f8 <+217>: movsx eax,al
0x00000000004010fb <+220>: mov DWORD PTR [rbp-0x4],eax
0x00000000004010fe <+223>: mov eax,DWORD PTR [rbp-0x8]
0x0000000000401101 <+226>: cdqe
0x0000000000401103 <+228>: mov eax,DWORD PTR [rax*4+0x6033a0]
** 0x000000000040110a <+235>: cmp eax,DWORD PTR [rbp-0x4]**
Breaking at the following “cmp” instruction:
(gdb) break *0x40110a
Breakpoint 1 at 0x40110a
(gdb) run
Starting program: /home/kroosec/Downloads/level.elf| > Type to win, only what I want to read…
| >
Breakpoint 1, 0x000000000040110a in main ()
(gdb) p *((int *) ($rbp - 0x4))
$1 = 65
(gdb) p $rax
$2 = 32
Obviously, the cmp will be false as the char we typed A is not equal to the space (32 decimal in ASCII.)
To fix that:
(gdb) set *((int *) ($rbp - 0x4)) = 32
Then we continue, again we come back
(gdb) c
Continuing.
*
Breakpoint 1, 0x000000000040110a in main ()
(gdb) p $rax
$3 = 83
Again, we return to the same place, (getch() call followed by cmp.)
This time the character is ‘S’, and to fix our erroneous guess:
(gdb) set *((int *) ($rbp - 0x4)) = 83
This is the main routine of the program. A loop that reads stdin character by character and compares them to the password’s. In a normal situation, where the password is a some long string, we would have needed a brute-forcing program, but in this case, the string is pretty short and obvious (my 2nd guess, after finding the 2nd R ;))
$ echo ’ SURPRISE!’ | ./level.elf
| > Type to win, only what I want to read…
| > **********
|
| -> Congratulations! The key is:
| 9e0d399e83e7c50c615361506a294eca22dc49bfddd90eb7a831e90e9e1bf2fb