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!