Sep
21

## Leet More 2010 SHAdow dROP writeup

Category: reverse

It installs a SEH handler with “bad guy” message,

pushes some binary trash on the stack,

opens “license.key“, and for each 5 bytes in reads from license, it calculates their SHA-1 and xors another 20 bytes on stack with hash binary.
After xoring all data in stack, just a ret follows – it jumps to the last pushed value xor first 4 bytes of first sha1 hash. Task name has reference to SHA and ROP, so we can suppose those pushed values are addresses of ROP gadgets xor’d with license.

Where are the ROP gadgets situated? Perhaps in this huge-ass random asm block in the middle of the app :)

The exe has image base of 13370000, so all the ROP addresses will be 1337xxxx. A good idea now is to dump the binary trash from stack. It’s done easily and here it is.

So now we have crypt text, partial plain text (\x37\x13 bytes) and key length (5 bytes). To clarify, let’s take first 20 bytes from binary trash:

CE37D44A1EDD38854EBBFC1769A11881855ED248

we know for sure that there might be a “3713” sequence in the plaintext on these positions:
****3713****3713****3713****3713****3713
of course not all the dwords will be 1337xxxx, because rop gadgets need parameters to be passed in the stack among rop addresses.
So let’s suppose we have 3713 on first (this we know for sure, it’s being ret to) and last dword:
****3713****************************3713
now we can xor our crypt text with that mask to get
****E359****************************E55B
And we need to get 5-byte sequence that’s sha-1 matches this mask.
sha1(“R0lGO”) == “3a21e3591edd38851aa0cb0442812f92dd45e55b

First 5 bytes of our license key is ‘R0lGO‘. Similarly, we can reconstruct the other (1340 / 20 * 5 – 5) = 330 bytes.
I used a modified version of John… ok, whom am i kidding? i had no idea whether this task is solvable till the first team has done it :)

The correct ROP sequence binary-patches the SEH handler to make it display this message instead of “license error”:

And the license file itself is a base64 string, which after unbase64ing gives us a GIF with the answer: