Flare-On 8 Challenge 7 - spel

Upon running the binary, it shows an error. Upon closing the window, nothing appears to happen. However, the application continues to run in the background.

After some trial and error, I managed to find out where the error window was created and shown. After which, there is a huge mov operation to load shellcode into memory.

mov operation

Nearing the end, there are calls to VirtualAllocExNumA and memmove to load the shellcode into memory.

API calls

Upon spending some time tracing the execution of the shellcode, calls to VirtualAlloc were noticed.

VirtualAlloc

Continue following the trace and there would soon be data written to the memory location returned at rax after the VirtualAlloc call. Find the source, and dump out the binary to get the first DLL. (Note: the binary should have 2 DOS headers)

From the first DLL, we can see it loading something from itself, and calling it.

dll 1 DllMain

A look into unk_1800168f0 reveals a MZ DOS header.

dll 1 embed

From this, we call tell that a second DLL is embedded inside of this DLL. It is being loaded by this DLL, and executed.

We can now extracted the 2nd DLL to find out what is going on.

Looking at the exports of the 2nd DLL, we can see start.

dll 2 exports

That would be a good place to start as that was what the 1st DLL tried to execute.

Within start only a single call to a subroutine is found. Following the subroutine results in the following.

dll 2 start

The function decrypts the names of DLLs needed at runtime. After that, it proceeds to resolve some WinAPIs via a hashing function. Some anti-debugging was found when analysing the DLL. sub_7ff9b8e11a40 is called twice, once with 1 as the second argument, another with the value at offset 9 of the memory allocated via VirtualAlloc. Let’s dig deeper.

When the second argument of the function is 1, it appears to be setting stuff up.

setup

When the second argument is 8, the process exits.
Notice how when the second argument is 8, it proceeds to decrypt flare-on.com.

flareon decrypt

Looking down further, we can see registry operations and some AES decryption going on.

AES

A look into the function reveals a ton of BCrypt operations. Of which, BCryptGenerateSymmetricKey being used to generate a session key for BCryptDecrypt.

BCrypt

At this point, I decided to debug this application in IDA, to reach the BCryptDecrypt by running sub_7ff9b8e11a40 with 1 as the second argument first.
Upon the next call to sub_7ff9b8e11a40, i manually changed the argument to 2.

However, to do so, I would have to first defeat the anti-debug.

anti-debug

The binary checks that its own name is SPELL.EXE before it can allow the decryption function to run.
I bypassed this check by renaming rundll32.exe to SPELL.EXE.

There is also another function to contact a non-existent domain. Failure to reach the domain will result in the termination of the program.

pattern

Notice how the resource loaded at the start is copied to the same offset as the buffer passed into the decryption function. It fetches offset 25 of the PNG resource in original exe to decrypt using hash of ’ ’ as key

To proceed, I used resource hacker to copy all resources from spel.exe to rundll32.exe (renamed as SPELL.EXE).
This allowed me to decrypt the contents successfully.

To bypass the network check, I simply stepped over the function and set the return value to 1.

The decryption revealed l3rlcps_7r_vb33eehskc3, which looks an awful lot like a flag.

There is 1 last function that is executed before the program ends.

cfg

The function executes a ton of XORs based on a huge switch-case table. The garbled flag is XOR-ed with some static bytes to become garbage. By zero-ing out the static bytes are they are initialized, and before the XOR happens, we can have the flag, in its correct order.

[email protected]