Debugme - HTB reversing challenge

Summary

Statically analyse the sample --> find main method --> run the program in x64dbg --> patch registers to bypass anti-debugging techniques --> flag

challenge page

This binary starts out with most of its code XORed and only unpacks it if we bypass several anti-debugging techniques.

Static analysis

I first wanted to see if I could grasp anything useful from throwing the program in cutter. Looks like all I got is the location of main in memory, as the initial code in main is pretty cryptic.

main function

Dynamic analysis

Opening up x64dbg and setting a breakpoint at 0x401620 yields.. a crash. That’s because before main even starts, in fact even before mainCRTstartup executes, the binary takes a sneaky jump to 0x408904! Here it does the following:

anti dbg view 1 anti dbg view 2

Let’s briefly go over what this all means. The program does 3 checks:

Check 1

This check goes over the Process Environment Block (PEB) flag called BeingDebugged. This flag is of BOOLEAN type and most debuggers tick this on because that’s the standard. It starts out by dereferencing the memory in the fs register plus an offset of 0x30 (everything in x64dbg is hex). This is where the PEB resides at runtime on a windows 32-bit program. On 64-bit the PEB address resides at gs:60h.

Check 2

This one does basically the same thing except it references the flag at offset 0x68 in the PEB, which is the NtGlobalFlag. This is not a BOOLEAN however, but will instead display 0x70 if in a debugger.

Check 3

This check is a little more advanced, relying on the fact that instructions under a debugger take significantly more time to execute than when they do natively. This is achieved using the rdtsc x86 instruction which counts ticks in the interval starting from when it is first called and ending when it is called again. In this interval the program executes useless instructions as they effectively cancel out (additions and subtractions of registers). This is done so the difference in time is clear.

Solution

The way to solve this now would be to manually step through each instruction and modify EAX to 0 at every cmp instruction. However theres a simpler way to do this: In x32/x64dbg, navigate to Debug -> Advanced -> Hide debugger (PEB) This will automatically patch the PEB BeingDebugged and NtGlobalFlag to not give us away.

Now all that is left to do is to bypass the tick count from rdtsc. To do this, set a breakpoint at the cmp instruction right after the second rdtsc:

hitting the cmp at rdtsc

Next just double click the value of EAX and set it to 0, or anything under 3E8. After doing so and continuing we reach this snippet of code:

program unpacking itself

Here the code XORs a large chunk of data and then jumps back to the beginning. Main has now changed, that was the reason for all the nops. The nops we’re replaced by a sequence of encodings and pushing of data to the stack. This is the encrypted flag:

new unpacked code

We then encounter a loop which decrypts the flag and places it on the stack:

flag