One look in this program and our whole understanding of how robots run has been shaken. Maybe you will have better luck than us.
Title: Override (300)
For this challenge we had to find a passphrase which was accepted by a 64-bit binary.
The challenge consists of a broken self-extracting bash script, if we look in the input we see that it contains some gzipped data which starts at file offset 803.
We extract as follows:
$ dd bs=1 skip=803 if=override | zcat > scrambled $ file scrambled scrambled: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped
Next step is to see what we can do with this binary, looking at the code in a disassembler shows it is heavily obfuscated, this will take some time to figure out. Let’s try a different approach.
Let’s try to solve this one old skool keygen style, like +orc and +fravia told is in the good old days:
– Break on getting the input. In the good old days on Windows this was some GetWindowText function, but here in Linux that’s just read/gets/fgets
– Step through to see where the input is used
We run through objdump and see what library functions are imported:
objdump -d scrambled | grep "plt.*>:" 0000000000400558 <printf@plt-0x10>: 0000000000400568 <printf@plt>: 0000000000400578 <puts@plt>: 0000000000400588 <__libc_start_main@plt>: 0000000000400598 <fgets@plt>: 00000000004005a8 <strlen@plt>: 00000000004005b8 <srand@plt>: 00000000004005c8 <rand@plt>:
So the input is retrieved using fgets, let’s try to attack from there..
gdb$ b 'fgets@plt' Breakpoint 1 at 0x400598 gdb$ r Please enter your password: ABCDEFG Breakpoint 1, 0x0000000000400598 in fgets@plt () Buffer address for fgets is $rdi gdb$ p/x $rdi $1 = 0x600dd8 gdb$ rwatch *0x600dd8 Hardware read watchpoint 2: *0x600dd8
The breakpoint triggers in strlen a few times, but then this is triggered:
=> 0x400805: mov eax,DWORD PTR [rbp-0x4] 0x400808: cdqe 0x40080a: add rax,QWORD PTR [rbp-0x20] 0x40080e: movzx eax,BYTE PTR [rax] 0x400811: push 0x40081b 0x400816: jmp 0x4006f0 0x40081b: je 0x40082a
Tracing through that for a few instructions, lands us at:
RAX: 0x0000000000000042 RBX: 0x0000000000000000 RCX: 0x0000003FA5F9B064 RDX: 0x0000000000000041 o d I t s z A P c RSI: 0x00007FFFFFFFE494 RDI: 0x0000000000600DD8 RBP: 0x00007FFFFFFFE4E0 RSP: 0x00007FFFFFFFE4C0 RIP: 0x0000000000400811 R8 : 0x0000003FA5F9B064 R9 : 0x0000003FA5F9B0E0 R10: 0x00007FFFFFFFE238 R11: 0x0000003FA5C36C40 R12: 0x0000003FA5F9B6A0 R13: 0x00007FFFFFFFE5D0 R14: 0x0000000000000000 R15: 0x0000000000000000 CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B ----------------------------------------------------------------------------------------------------------------------- => 0x400811: push 0x40081b 0x400816: jmp 0x4006f0 0x40081b: je 0x40082a
Hmmm $rdx 0x41 is the first letter of our input (A) and it is compared against $rax 0x42.
Let's hack together a quick gdb script which does the following:
- Log the value of $rax since that is the expected input
- Patch $rdx so it is equal and the comparison continues
b *0x400811 commands 1 silent printf "%c", $eax set $rdx=$rax c end
Running this script in gdb:
r Starting program: /root/scrambled Please enter your password: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Bg8Ph#xnr||l*YjV|9K#RRfh6XhnhK8*%f:h5AAUgg%t5K3%xRnR%Xh|iU#W6h3kU8A*KU|YR:l83g
Hmm so that looks like a nice password. Let's try inputting it:
Please enter your password: Bg8Ph#xnr||l*YjV|9K#RRfh6XhnhK8*%f:h5AAUgg%t5K3%xRnR%Xh|iU#W6h3kU8A*KU|YR:l83g INCORRECT PASSWORD. INITIATING DESTROY-THE-HUMAN SEQUENCE...
Hmmm, this looked to good to be wrong... What could be the problem? Maybe our tricks fooled the check a little bit too much and made the program accept a longer password than expected, let's try some substrings.
import os s = 'Bg8Ph#xnr||l*YjV|9K#RRfh6XhnhK8*%f:h5AAUgg%t5K3%xRnR%Xh|iU#W6h3kU8A*KU|YR:l83g' for x in range(len(s)): sub = s[:-x] os.system('echo "%s"; (echo "%s" | ./scrambled)' % (sub,sub))
$ python sub.py | grep -B1 Success Bg8Ph#xnr||l*YjV|9K#RRfh6XhnhK8*%f:h5AAUgg%t5K3%xRnR%Xh|iU#W6h3k Please enter your password: Success! You are now logged into the system.
Success! Again proof the gdbscripts are more useful than actual reverse engineering! 😀