Flare-On 7 2020 Challenge #2: garbage

Eviatar Gerzi
4 min readOct 29, 2020

--

Tools to use:

  • x64dbg
  • HxD
  • pestudio
  • upx-3.96-win64
  • IDA
  • Python

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:

Sections are with UPX name

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 WriteFile and ShellExecuteA:

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.

The Data

Let’s see what we have so far.

String A:

KglPFOsQDxBPXmclOpmsdLDEPMRWbMDzwhDGOyqAkVMRvnBeIkpZIhFznwVylfjrkqprBPAdPuaiVoVugQAlyOQQtxBNsTdPZgDH

String B:

nPTnaGLkIqdcQwvieFQKGcTGOTbfMjDNmvibfBDdFBhoPaBbtfQuuGWYomtqTFqvBSKdUMmciqKSGZaosWCSoZlcIlyQpOwkcAgw

Some key:

[ebp+var_58], 2C332323h
[ebp+var_54], 49643F0Eh
[ebp+var_50], 40A1E0Ah
[ebp+var_4C], 1A021623h
[ebp+var_48], 24086644h
[ebp+var_44], 2C741132h
[ebp+var_40], 0F422D2Ah
[ebp+var_3C], 0D64503Eh
[ebp+var_38], 171B045Dh
[ebp+var_34], 5033616h
[ebp+var_30], 8092034h
[ebp+var_2C], 0E242163h
[ebp+var_28], 58341415h
[ebp+var_24], 3A79291Ah
[ebp+var_20], 58560000h
[ebp+var_1C], 54h
[ebp+var_18], 3B020E38h
[ebp+var_14], 341B3B19h
[ebp+var_10], 3E230C1Bh
[ebp+var_C], 42110833h
[ebp+var_8], 731E1239h
Cleaner 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
54
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)
print(result)

Decoding the encoded string for the CreateFile

The key, 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:

KglPFOsQDxBPXmclOpmsdLDEPMRWbMDzwhDGOyqAkVMRvnBeIkpZIhFznwVylfjrk

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)
sink_the_tanker.vbs

We see that it creates a VBS file named sink_the_tanker.vbs.

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:

flag: C0rruptGarbag3@flare-on.com

--

--

Eviatar Gerzi
Eviatar Gerzi

Written by Eviatar Gerzi

Security researcher interested in reversing, solving CTFs, malware analysis, penetration testing and DevOps security (docker and Kubernetes)