When we run the exe, we see that all the buttons are disabled. There is no button to click. So we close the dialog and start our analysis.
When we first disassemble the
spel.exe, we see a huge function in the beginning of the file. We can put a breakpoint at the end of this function and so we can save that file and check the contents. When we check the file, we see that it is a DLL file. It doesn’t end in here. If we check this DLL file, we see that it has another DLL embedded. We can easily dump this DLL and can easily disassemble this file. It has only one exported function called
DLL doesn’t use a standard import table, instead, it uses hash-based imports. It gets the address of the function by checking the export table of the DLL and calculate the hash of this function. If the hash matches, it returns the address of the function.
This challenge has a lot of booby traps, if you don’t see them, it “takes a break” by calling “Sleep” or “SleepEx” functions.
It gets the name of the file and compares it to Spell.EXE. So change the name of the file to Spell.EXE
There is a
SleepEx call just after the name comparison. Patch that call.
It tries to connect “inactive.flare-on.com” We can easily pass that by creating a fake server and change the
hosts file to point to our server. Exe first sends ’@’ to the server. If you send “exe” back, it sends ”#” and runs the code that is coming back. We can’t guess that so it is a trap.
If you send “run” back when it asks ’@’ then it sends ”&” and again runs the code that is coming from the server. It is another trap.
However, if you send, “flare-on.com” it continues.
It then tries to decrypt the resource with AES and set two keys under
HKCU\Software\Microsoft. This is where I got stuck. Because I didn’t see what was happening.
There was a huge switch statement. In each case, it was XORing the result of the AES operation with two big keys.
loc_1800027B3: cmp edx, 16h ja def_1800027D0 movsxd rax, edx mov ecx, ds:(jpt_1800027D0 - 180000000h)[rcx+rax*4] lea rax, cs:180000000h add rcx, rax jmp rcx
It seems, xor keys at
xmmword_180015160 was hiding the flag. You either note each byte in every switch statement or, you could zero out xmm0 and xmm1 registers after the below line. So it will show the correct flag.
movdqa xmm0, cs:xmmword_180015180 mov rbx, rcx movdqa xmm1, cs:xmmword_180015160
Flare-On 2021 Write-ups