Squid Game
Disclaimer
I am nowhere near a professional malware analyst, I am doing this for fun. There are for sure better methods, but this is how I did it. Also remember that this is just a walk through to answer the questions from the challenge and not a full malware analysis.
I tried to create this walk through in a way that still needs some interaction and thinking from the reader. Not all answers a provided in a Question?:Answer scheme :)
Thanks THM for this room!
Attacker 1
Hashes
Sha256: 2979b5fbb454e2f13d89e58177f8c1f881bd3f0a0bebb1d27da9e189ba9d284e
MD5: 4443840f2870c2cd55062bdcab07e5fd
Analysis
For maldocs I can highly recommend the tools from Didier Stevens which can be found here. The documentation is in the file itself. (oledump.py). Along with oledump I use this from decalage2.
They are already on the THM machine though!
oledump.py attacker1.doc
Lets check out the stream which contains the macro (indicated by "M"):
oledump.py attacker1.doc -s <stream> -S -v
Flag | Purpose |
---|---|
-s | indicating the stream we want to dump |
-S | dumps the strings |
-v | decompress the VBA macro sourcecode |
The dump shows a lot of string and character manipulation, but there is one specific block that stands out:
This is an attempt to use the 'Shell' function to execute a command. There also seems to be a replacement of characters taking place.
Timestamps can be checked with oletimes.
Now lets dump the other streams"
oledump.py attacker1.doc -s <stream> -S
The subject can be found in stream 3 as well as in stream 4 together with the phone number.
Stream 4 also contains something very interesting:
Followed by what looks like a base 64 string with some "[", which we saw earlier are replacing "A". So lets throw this into cyberchef with this recipe
This is where the IP, C2, folder, executable and COM object can be found.
The $path variable contains the folder, but it is not the correct name. Google will tell you. Do not forget the "%" before answering.
The COM object is identified by a GUID.
Attacker 2
Hashes
SHA256: 22fe1b36efa9cb3a8f1e71c1d6730d360977fad6923dcf9cb8a313a975b8aac7
MD5: e599a656599a2680c9392c7329d9d519
Analysis
First lets see what is going on with attacker2.doc:
oledump.py attacker2.doc
When entering the numbers, add a whitespace behind the comma. This made me nearly question my whole life xD
To find the bytes of the compiled code we can use the -i flag:
oledump.py -i attacker2.doc
oledump.py documentation: "the size of the compiled code (left of the + sign) and the size of de source code (right of the + sign)"
The total bytes can be found in the 3rd column.
For the next questions, we will use olevba.
olevba attacker2.doc | grep fun
This returns the command from the fun field, but you have to reverse it. If you use python, remember to escape the backslashes.
Then run the command again. At the bottom of the output you will see a summary, but for a better overview I recommend scrolling up to the output from stream 9:
This part of the olevba output should answer the remaining questions.
Attacker 3
Hashes
SHA256: b156c9ad046d0d4b174f7308bd3b965f4425b1dfa38e7dc19e6e1eb54b0b49a1
MD5: 30511605bee5a35ff80fde0de0105bd4
Analysis
oledump.py attacker3.doc
Going straight to olevba, we can see that this one is very small.
The most interesting things happen in VBA/T and VBA/d.
In VBA/T we can see an obfuscated string that gets passed into some kind of function, probably a custom deobfuscator. The output is then saved in a variable. Also a new WshShell object being created which does two things:
- It copies an executable from the System32 folder to the ProgramData folder under a different name
- It executes the contents from the previously deobfuscated string
In VBA/d the custom deobfuscation function is declared. We only need to split the character codes at the "%" and XOR them with 111. Good ole Shakespeare had a python script to share that helps:
obfu = input("Good morrow to thee, kind sir. Pray, might I entreat thee to bestow upon me the boon of thy counsel?\n")
out = ''
obfu = obfu.split("%")
for i in obfu:
out += str(chr(int(i)^111))
print("Parting is such sweet sorrow, that I shall say good night till it be morrow.\n")
print(out)
Deobfuscating this string reveals a command that:
- a file is downloaded and saved under a different name
- the downloaded file is registered as a DLL with regsvr32 (look)
- the downloaded file is than executed with the previously copied file from System32
This should allow you to answer all the questions
Attacker 4
Hashes
SHA256: d61aa6195a2da022d16af3694050b51e29bc7ef7a6f3ad735c3a20f81891b601
MD5: 41c4dd8ed6597723155aae653ad6a1e8
Analysis
oledump.py attacker4.doc
This does not look to bad, does it?
olevba attacker4.doc
Well...two snippets:
BUT! There is a nifty tool to analyze obfuscated maldocs:
Which is also installed on the box from THM.
vmonkey attacker4.doc
The -s flag can also be used for speedup, you can read about it in the docs. I did not use it for this analysis.
To decode the strings from the maldoc you can:
olevba | grep -i xori
The parameters of the XORI functions are as follows:
XORI(<value>, <key>)
You can use this cyberchef recipe to decode the values.
From the "Recorded Actions" output of vmonkey, the remaining questions can be answered.
Attacker 5
Hashes
SHA256: 55c9ff8f829bf0d5bbec83127570ad149bd18bc0351c59933090af917b4451db
MD5: 4ac3d0835c1650e2ec73c8607d55ed1d
Analysis
oledump.py attacker5.doc
olevba attacker.doc
The line following "AutoOpen()" runs powershell with the "-hidden" and "-encoded" flags. The latter
means that the string which gets concatenated (& operator) probably is a base64 encoded string.
Since there was nothing interesting in the output of olevba, we'll switch to oledump and go through the streams.
oledump.py attacker5.doc -S -s <stream>
In stream 6 we find the caption and in stream 7 the base64 string.
Decoding the first string in cyberchef, there is another base64 string. It is always important to further read what happens next with that string. In this case the string is base64 decoded and then gzip decompressed, before it is passed into the invoke expression function:
For this string we need base64 decoding and "gunzip". This results in another powershell script:
Another base64 string, this one is decoded and saved to a byte array, which is then bitwise-xored byte by byte. Further down in the script, memory is being allocated and the xored bytes are copied into the allocated memory, which can indicate a shellcode injection.
Lets create a python script that does exactly the same.Decode, XOR and write the bytes into a binary, as well as printing the the decoded bytes for some quick views.
import base64
bstring = "<b64 string here>"
decoded_bytes = base64.b64decode(bstring)
xor_bytes = bytearray(b ^ 35 for b in decoded_bytes)
with open('shcode.bin', 'wb') as f:
f.write(xor_bytes)
out = xor_bytes.decode('utf-8', errors='replace')
print(out)
With some research about the windows api, the next command can answer the remaining questions.
speakeasy -t shcode.bin -r -a x86
Flag | Purpose |
---|---|
-t | target |
-r | display a report upon completion |
-a x86 | specifies the architecture to emulate |
For a more clear and structured output, you can use scdbg:
scdbg -f shcode.bin -s -1
Flag | Purpose |
---|---|
-f | the file to use |
-s | the steps to go through, -1 for infinite |
scdbg needs some startup time on the THM box. On the interface tick the "unlimited steps" box
This should leave you with all the questions answered :)