Challenge
The challenge is a XLS (Excel) file named report.xls
.
Readme shows this message: Nobody likes analysing infected documents, but it pays the bills. Reverse this macro thrill-ride to discover how to get it to show you the key.
Solution
Seems that we have a malicious document :D
I haven’t done anything about malicious code embedded inside documents, this challenge was a surprise to me! Let’s open the document:
In the screenshot I already enabled the macros; in your case, you just need to click Enable content in the yellow panel on top of the blue image. We notice an error: Invalid procedure call or argument. What is this? The title of the window is Microsoft Visual Basic for Application, so it seems that something went wrong on the execution of a VBA Macro. What is a VBA Macro?
Office suit allow devs to define code that executes when particular events are triggered. This functionality is offered from Microsoft for automating many document tasks, such as re-ordering, calculating values on specific columns etc…
Turns up that VBA Macros are commonly seen inside malicious documents :)
If we click Ok from the error window, it brings inside the code of the macro, that is written in Visual Basic.
We also have a form inside the project with two suspicious strings:
the blank textarea is named T
, the other L
.
We can get the same code using oledump
python script, but for me was more comfortable doing this way.
Ok, my eyes start to burn as soon as I see Visual Basic:
So I open Visual Studio, start a new VB project, adjust and format the code and now we’re ready to analyze it. Let’s do a quick schema of what happens inside the code:
First, the VBA is executed when two events are triggered:
Auto_Open()
WorkBook_Open()
From a stackoverflow post:
Like
Auto_Open
,WorkBook_Open
runs when the workbook is opened, however its mechanics are much more transparent, and work exactly like every other event-handling procedure: Workbook is the interface, Open is the event/member.
foldero1()
is the startup function that is called from the two events. The first big string obtained by looking at the F.L
property of the form is splitted by .
in several strings and put into the onzo
array. This array data is used many times in the code and its content of each array cell wrapped in a function called rigmarole()
that does the obfuscation. Inside the VS Debugger, we inspect all the onzo
elements (12 strings total) getting the following strings:
[0] -> "AppData
[1] -> "\Microsoft\stomp.mp3"
[2] -> "play "
[3] -> "FLARE-ON"
[4] -> "Sorry, this machine is not supported."
[5] -> "FLARE-ON"
[6] -> "Error"
[7] -> "winmgmts:\\.\root\CIMV2"
[8] -> "SELECT Name FROM Win32_Process"
[9] -> "vbox"
[10] -> "WScript.Network"
[11] -> "\Microsoft\v.png"
After getting the connection state, it employs COM objects and WMI queries (GetObject("winmgmts:\\.\root\CIMV2"))
, ExecQuery("SELECT Name FROM Win32_Process")
to search for process starting with vmw
, vm
. Typically, virtual machine like VBox or VMWare run some processes into the task manager. Malware can easily detect in a trivial VM configuration if it’s running inside a VM by looking at the list of the process. In this case, if it finds some starting with those keywords it’ll exit. This is a typical anti-VM trick used by malware authors to avoid their malicious piece of code being analyzed.
Then, code sets up a key (xerts
) and using the xoring function canoodle
creates a buffer from F.T
data xor’ed with xerts
. The buffer is an MP3 file (we can check the ID3
header) and it is saved under the name stomp.mp3
inside %Appdata%/Microsoft
directory. Finally, a string is sent over the network with the content: play <path of mp3 file>/stomp.mp3
.
Okay great! And now? We open the mp3 and we listen to our flag…
… which is not true, because it’s just an audio with many stomp sounds and it’s metadata show a sad hint:
Reversing/analyzing hex of the MP3 is useless, no clue there. What the f*** I’m supposed to do?
I was blocked until I found an hint mentioning p-code. P-code
is mentioned also in the author section of the MP3. And the MP3 is called stomp.mp3
. Oh, jeez…
The line Suspicious: VBA Stomping
of olevba
output triggered me. So there is some strange technique used in this excel… what’s p-code
?
P-code is the actual code to run. It’s like a compiled cache kept inside by Microsoft. From a theoretical point, it should be equal to the source code, no?
Here’s the trick: if I compile a VBA with a malicious source code, and then I stomp (i.e., overwrite) the source inside with a benign one, many VBA analyzer tools will get you the benign code. What’s actually executed is the malicious code (i.e., p-code
). Nice trick!
So… I have to find a way to dump also the compiled p-code
… how to do that?
Just use olevba
with --show-pcode
option, and you’ll get also the p-code.
The compiled code looks worst than visual basic. I care about my eyes, so I used some p-code to vb code dumper (like pcode2code.py
). We notice that the first part of the obtained source is the same as the one above; but here the code continues after the mp3 file.
The first part tries to get the NetBIOS domain name. It checks if it’s called "FLARE-ON"
, and if not, exits. onzo
de-obfuscated values are translated in the comments for your convenience.
Dim groke As Object
groke = CreateObject(rigmarole(onzo(10))) ' CreateObject("WScript.Network")
Dim firkin = groke.UserDomain ' NetBIOS domain name
If firkin <> rigmarole(onzo(3)) Then ' NETBios domain name != FLARE-ON
MsgBox(rigmarole(onzo(4)), vbCritical, rigmarole(onzo(6))) ' MsgBox("Error", "Sorry, this machine is not supported.")
End
End If
Then, it reverses the FLARE-ON
string, and uses the resulted string as a key for canoodle
, applied for the same F.T
property.
Dim n = Len(firkin) - 1
Dim buff(n)
For i = 1 To n
buff(n - i) = Asc(Mid$(firkin, i, 1))
Next
wabbit = canoodle_old(T, 2, 285729, buff)
mf = Environ(rigmarole(onzo(0))) & rigmarole(onzo(11))
The new buffer is saved as a file called v.png
into the same %appdata%/Microsoft
dir and it is showed as a picture inside the document.
Open mf For Binary Lock Read Write As #fn
Ld fn
Sharp
LitDefault
Ld wabbit
PutRec
Close #fn
Dim panuding = Sheet1.Shapes.AddPicture(mf, False, True, 12, 22, 600, 310)
I just ran the code in Visual Studio so I didn’t step into the detailed de-obfuscation
logic of rigmarole
and canoodle
.
Btw here’s the image… we finally got the flag!
See you in the next research!