SHX5 : rev400-again

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:

  1. Disassembling the program, understanding the code and writing a keygen
  2. Patching anti-debug protections and dumping the flag from memory
  3. 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 :)