1
| One of our team members developed a Flare-On challenge but accidentally deleted it. We recovered it using extreme digital forensic techniques but it seems to be corrupted. We would fix it but we are too busy solving today's most important information security threats affecting our global economy. You should be able to get it working again, reverse engineer it, and acquire the flag.
|
1
2
| $ file garbage.exe
garbage.exe: PE32 executable (console) Intel 80386, for MS Windows, UPX compressed
|
Introduction#
Looks like this is a UPX packed binary, but trying to unpack it using
results in
1
2
3
4
5
6
7
8
9
| Ultimate Packer for eXecutables
Copyright (C) 1996 - 2020
UPX git-d7ba31+ Markus Oberhumer, Laszlo Molnar & John Reiser Jan 23rd 2020
File size Ratio Format Name
-------------------- ------ ----------- -----------
upx: garbage.exe: OverlayException: invalid overlay size; file is possibly corrupt
Unpacked 1 file: 0 ok, 1 error.
|
That is a strange error there, we have to dig deeper.
Trying things out, I got something interesting from Ghidra
when trying to import the exe
file.
1
2
| Error importing file: garbage-cc.exe
java.lang.IndexOutOfBoundsException: Specified length extends beyond file bytes length
|
Note: IDA
imports it fine btw.
Maybe this file is corrupted by shrinking the size of the file, and that does not match the size specified in the PE header?
I tried to test this theory so I appended a number of NULL
(\x00
) bytes at the end of the file. Doing so actually fixed it and I managed to unpack it,
but there is no imports in the file, or at least they are not resolved.
Even without imports, I tried looking into the strings to find anything and found:
1
2
3
| "nPTnaGLkIqdcQwvieFQKGcTGOTbfMjDN...", # trimmed
"KglPFOsQDxBPXmclOpmsdLDEPMRWbMDz...", # trimmed
"covid19-sucks",
|
The first and second one are used in sub_40106B
, which seems an interesting function,
Also looking in the entry
we find that this function seems to be main
. So lets look
into it.
The third string is not being used anywhere.
Solution#
In the function FUN_0040106b
, we find that it decrypts the above strings using XOR
in
FUN_00401000
together with integer array. The results are used in functions that are not resolved due to not having import table.
Something like:
1
2
| FUN_00401000(&local_13c,(int)&local_1c,0x14,(int)local_c4);
iVar2 = (*(code *)(undefined *)0x12418)(local_13c,0x40000000,2,0,2,0x80,0);
|
The function in 0x12418
seems like CreateFile
. (Yes looks like, the decrypted first parameter is a file name, see below).
The flag pair is:
1
2
3
| encrypted_string = b'nPTnaGLkIqdcQwvieFQKGcTGOTbfMjDNmvibfBDdFBhoPaBbtfQuuGWYomtqTFqvBSKdUMmciqKSGZaosWCSoZlcIlyQpOwkcAgw'
key = [0x2C332323, 0x49643F0E, 0x40A1E0A, 0x1A021623, 0x24086644, 0x2C741132, 0x0F422D2A, 0x0D64503E, 0x171B045D, 0x5033616, 0x8092034, 0x0E242163, 0x58341415, 0x3A79291A, 0x58560000, 0x54]
|
We can decrypt them with:
1
2
3
4
5
6
7
8
| import struct
def decrypt(string, key):
# convert the little-endian ints into bytes and concat them together
ready_key = b''.join([struct.pack('i', x) for x in key])
return bytes([x[0] ^ x[1] for x in zip(string, ready_key)])
print(decrypt(encrypted_string, key))
|
And we got the flag
1
| MsgBox("Congrats! Your key is: C0rruptGarbag3@flare-on.com")\x00Fqv
|
Note: the other one decrypted is “sink_the_tanker.vbs
”, which is the filename.