Flare-On 7 2020 Challenge #2: garbage
Tools to use:
When I tried to load the file to x64dbg I received a message that this is an invalid PE file:
I opened it with HxD and noticed that the headers looks fine but when I scrolled down to the end of the file I noticed that it doesn’t look right:
It seems that the end of the file is not finished. My first idea was to build a simple program and complete it accordingly.
Before doing it, I also noticed that file is packed with UPX:
We can see the differences:
I copied the missing part to the garbage.exe file.
Notice that some of the data is imported functions and you can fix it but we will see that you don’t need to.
Loading the file
After the copy I succeeded to load the file to x32dbg, but it still doesn’t run because there is a problem with the imported functions. At this point I could try to fix the imports but I decided to check it statically before fixing it.
Static Analysis to the unpacked file
I unpacked the file with UPX:
I loaded it to IDA and I found an interesting function
sub_40106B in the main function. It had two long constant strings that caught my eyes:
Some unclear constants, maybe a key:
And after that it called to
CreateFileA followed by
Notice to the another interesting function
sub_401000 that was called before each writing operation. The assumption that maybe this is some encrypted data that is being decrypted before each call.
Let’s see what we have so far.
[ebp+var_8], 731E1239hCleaner version:
2C 33 23 23
49 64 3F 0E
40 A1 E0 0A
1A 02 16 23
24 08 66 44
2C 74 11 32
0F 42 2D 2A
0D 64 50 3E
17 1B 04 5D
50 33 61 06
80 92 03 04
0E 24 21 63
58 34 14 15
3A 79 29 1A
58 56 00 00
3B 02 0E 38
34 1B 3B 19
3E 23 0C 1B
42 11 08 33
73 1E 12 39
Analyzing the Decryption Function (sub_401000)
The decompiled version:
To understand what are the roles of each input argument, we checked the calls to this function from the disassembly and figure it out.
Creating the function in Python
The first call looks like that:
It call 5 arguments and based on their value we can make an educational guess to their roles:
// (result , key, length, encoded_string, ecx)
sub_401000(lpFileName, var_18, 0x14, eax, ecx)
We can create the Python script to match it:
def sub_401000(key, length, encoded_string):
modulo = 102
result = ''
for v5 in range(length):
r = ord(key[v5%modulo]) ^ ord(encoded_string[v5])
result += chr(r)
Decoding the encoded string for the CreateFile
var_18, start with
0x3B020E38 and the length is
0x14 (20) so it should be:
3B 02 0E 38 34 1B 3B 19 3E 23 0C 1B 42 11 08 33 73 1E 12 39
The encoded string is the last one:
We will run it with Python:
encoded_string1 = 'KglPFOsQDxBPXmclOpmsdLDEPMRWbMDzwhDGOyqAkVMRvnBeIkpZIhFznwVylfjrkqprBPAdPuaiVoVugQAlyOQQtxBNsTdPZgDH'key1 = '\x38\x0E\x02\x3B\x19\x3B\x1B\x34\x1B\x0C\x23\x3E\x33\x08\x11\x42\x39\x12\x1E\x73'>>> sub_401000(key1, ,0x14, encoded_string1)
We see that it creates a VBS file named
Decoding the encoded string for the WriteFile
Like before, we searched for the encoded string based on
var_58 and the length
0x3d, extracted it and run in Python:
encoded_string2 = 'nPTnaGLkIqdcQwvieFQKGcTGOTbfMjDNmvibfBDdFBhoPaBbtfQuuGWYomtqTFqvBSKdUMmciqKSGZaosWCSoZlcIlyQpOwkcAgw'
key2= '\x23\x23\x33\x2C\x0E\x3F\x64\x49\x0A\x1E\x0A\x04\x23\x16\x02\x1A\x44\x66\x08\x24\x32\x11\x74\x2C\x2A\x2D\x42\x0F\x3E\x50\x64\x0D\x5D\x04\x1B\x17\x16\x36\x03\x05\x34\x20\x09\x08\x63\x21\x24\x0E\x15\x14\x34\x58\x1A\x29\x79\x3A\x00\x00\x56\x58\x54\x00\x00\x00\x38\x0E\x02\x3B\x19\x3B\x1B\x34\x1B\x0C\x23\x3E\x33\x08\x11\x42\x39\x12\x1E\x73\x81\x2C\x11\x35\xF0\xFC\xB5\x00\x94\x84\x80\x77\x00\xE0\x9B\x00\x70\x84\x80\x77\x5D\xD0\xA4\x35\x38\xFD\xB5\x00'>>> sub_401000(key2, 0x3d, encoded_string2)
MsgBox("Congrats! Your key is: C0rruptGarbag3@flare-on.com")
We received the flag: