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.
Binary Analysis
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.
Nearing the end, there are calls to VirtualAllocExNumA
and memmove
to load the shellcode into memory.
Upon spending some time tracing the execution of the shellcode, calls to VirtualAlloc
were noticed.
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)
DLL 1
From the first DLL, we can see it loading something from itself, and calling it.
A look into unk_1800168f0
reveals a MZ DOS header.
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.
DLL 2
Looking at the exports of the 2nd DLL, we can see start
.
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.
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.
sub_7ff9b8e11a40 Analysis
When the second argument of the function is 1, it appears to be setting stuff up.
When the second argument is 8, the process exits.
Notice how when the second argument is 8, it proceeds to decrypt flare-on.com
.
Looking down further, we can see registry operations and some AES decryption going on.
A look into the function reveals a ton of BCrypt operations. Of which, BCryptGenerateSymmetricKey
being used to generate a session key for BCryptDecrypt
.
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.
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.
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.
Flag Scrambling Function
There is 1 last function that is executed before the program ends.
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.