Can you reverse it and find the flag?
Format: shellter{flag_here}
*Download the binary at shellterlabs.com
Solution
This is a classic keygen challenge, but I will solve it in 3 ways:
- Disassembling the program, understanding the code and writing a keygen
- Patching anti-debug protections and dumping the flag from memory
- Bruteforcing w/ nozzlr
1. Writing a keygen
Disassembling the main
, we can see a call to a function sub.strlen_7c5
before the last test
that prints the flag or the error message.
Dumping the registers to retrieve the flag is not possible because this function do some maths w/ our input and return the result. If you try to skip this function it will return something like this shellter{yourinput}
.
Well, disassembling sub.strlen_7c5
the first thing we note is this 21 byte
stacked:
..and just below, a strlen
function retrieving the length of our array = 0x14(20)
following by a loop XOR'ing 0x14(20)
times the first byte 0xd1
w/ every byte of the array!
It's clearly our flag.. let's code this..
Patching anti-debug protections
So, we just have our flag, but let's try to understand a little bit more about the program..
Strlen reveals the length of the flag 0x14(20)
and start a 20x loop..
..after the XOR, we can see a cmp
testing if the resulting byte is the same loaded into the rbp-local_25h
If je
is True
it loops back to test the next byte.. if not, kicks me out and print the message [!] Peem! Get out of here!!
If we send any 20len
flag AAAAAAAAAAAAAAAAAAAA
and set a breakpoint at this cmp
and dump rbp-local_25h
content, we will retrieve every byte of our flag.
But its not possible because we have some anti-debug protections.. the first one is found at init
function
Which do some test detecting any debugger, preventing the program from entering the main
while debugging.
No problem, we can simple patch the je
to jne
and skip this test
..and now the program enters the main
function
..but theres one more protection after the XOR.. a time based protection
..lets skip this too by pathing jg
to jle
Now we can run the program and dump the next cmp
0x42(B)
is our flag first byte stored at 0x7ffebdb0b187
.
To dump all characters at once we will also patch the next je
to jne
..this will avoid exit the program when the next inputed character is invalid.
And now u can easily dump the whole flag :)
Bruteforcing w/ nozzlr
Now with the patched program, it became easy to launch a bruteforce and read all bytes of the flag independent of the debugger software.
Nozzlr is a bruteforce framework which I developed to perform bruteforces in absolutely any protocol/situation.. In this case i've used my ARGV bruteforce sample and wrote this nozzlr template
Running nozzlr bruteforce..
$ nozzlr argv_bruteforce.py alphanumdigs.txt 1 --repeats=11 --offset=0
I'm not showing the rest of the flag.. do it by your own :)