Stomping On Microsoft Word
In 2018, security research was released on
how VBA code is stored in Microsoft Word and Excel macros
and how this may be abused.
In this section, we’ll investigate this topic
to find out how we can leverage the technique to reduce our detection rates.
To begin, we must inspect our existing shellcode runner more closely,
and this requires some custom tools.
The Microsoft Office file formats used in documents with .doc and .xls extensions
rely on the very old and partially-documented proprietary Compound File Binary Format,
which can combine multiple files into a single disk file.
On the other hand, more modern Microsoft Office file extensions, like
.docm and .xlsm,
describe an updated and more open file format
that is not dissimilar to a .zip file.
There are no official tools for unwrapping .doc files,
so we’ll turn to the third party FlexHEX application,
which is pre-installed on the Windows 10 development machine.
Let’s use this tool to inspect
our most recent revision of the VBA shellcode runner.
First, we’ll open FlexHEX,
and navigate to File
Open
OLE Compound File…
In the new file browser window, we’ll specify the file to open.
Notice the lower-left Navigation window.
If we expand the Macro and VBA folders,
we obtain a view showing all the embedded files
and folders included in the document.
Any content related to VBA macros are located in the Macros folder.
The first file worth inspecting is PROJECT,
which contains project information.
If we click this file in the Navigator window,
the content is displayed in the upper-left window.
The graphical VBA editor also determines which macros to show
based on the contents of this file.
The binary content contains the ASCII line “Module=NewMacros”,
which is what the GUI editor uses to link the displayed macros.
If we could remove this link in the editor, it could hide our macro
if our target opens the graphical Office VBA editor.
To remove this link in the graphical editor,
we can simply remove the line by replacing it with null bytes.
This is done by highlighting the ASCII string
and navigating to Edit
Insert Zero Block.
We can save the change by clicking OK.
With the null bytes saved,
we’ll close FlexHEX to recompress the file.
Now let’s open the document up in Word and observe the result.
The VBA editor no longer shows modules or macros.
We’ll submit this new file to antiscan.me
to find out if we have improved our evasion rate.
This helps prevent manual detection, but AntiScan.Me
reports that we have not reduced the detection rate
since the macro still exists and will still be executed.
However, if we could somehow remove the macro
yet still have it execute,
we may enjoy a significant reduction in our detection rate.
To understand how this unlikely scenario is possible,
we must dig deeper into the implementation of VBA code.
The key concept here is called PerformanceCache,
which is a structure present in both _VBA_PROJECT and NewMacros.
Inspecting the documentation reveals that this signifies a cached
and compiled version of the VBA textual code, known as P-code.
The P-code is a compiled version of the VBA textual code
for the specific version of Microsoft Office and VBA it was created on.
To explain it differently,
if a Microsoft Word document is opened on a different computer
that uses the same version and edition of Microsoft Word,
the cached pre-compiled P-code is executed,
avoiding the translation of the textual VBA code
by the VBA interpreter.
Using FlexHEX, we can view the P-code inside the NewMacros file.
In the right-side pane, we notice the Win32 API
names inside the compiled P-code,
while the rest of the code is in a pure binary format.
If the document is opened on a different version
or edition of Microsoft Word,
the P-code is ignored
and the textual version of the VBA is used instead.
This is also located within NewMacros in a variable called CompressedSourceCode.
Scrolling towards the bottom of NewMacros,
we find a partially-compressed version of the VBA source code.
Even partially compressed, we notice the Win32 API imports
following the statement
Attribute VB_Name = “New Macros”
Scrolling further down,
We find the remainder of the VBA code.
In regards to this cached P-Code,
we need to understand how Microsoft Word determines the version
and edition a specific document was created with.
A clue lies at the beginning of the _VBA_PROJECT file.
From these two sections,
we notice that the P-code in this document will be compiled for Office 16.
This indicates Microsoft Office 2016,
which uses VBE7.DLL
and is installed in the 32-bit version of the Program Files folder.
This matches our current environment.
As long as our document is opened
on a computer that uses the same version of Microsoft Word
installed in the default location,
the VBA source code is ignored and the P-code is executed instead.
This means that in some scenarios, the VBA source code can be removed,
which could certainly help us bypass detection.
As we will demonstrate,
only a few antivirus products actually inspect the P-code at all.
This concept of removing the VBA source code has been termed VBA Stomping.
Let’s perform this evasion technique with our encrypted shellcode runner
by locating the VBA source code inside NewMacros.
We need to mark the bytes that start with the ASCII characters
“Attribute VB_Name” and select all the remaining bytes.
The end of the p-code will be the very last byte.
With the VBA source code selected, we’ll navigate to Edit
Insert Zero Block,
and accept the size of modifications.
Once the VBA source code has been stomped, we’ll save the Microsoft Word document,
and close FlexHEX to allow it to be re-compressed.
If we open the Word document,
we’ll notice the “Enable Content” security warning,
but if we open the VBA editor,
we’ll find that the NewMacro container is completely empty.
Visually, the VBA macro seems to have been completely removed.
When we accept the security warning
and let the VBA macro execute, we notice two things.
First, we obtain a reverse Meterpreter shell,
which demonstrates that even with the VBA source code removed,
the P-code is executed and the attack still works.
Second, the VBA source code has reappeared inside the VBA editor.
Microsoft Word decompiled the P-code
and wrote it back into the editor while executing it.
Since the Microsoft Word document still yields us code execution,
the most pressing question is,
does this reduce antivirus detection rates?
AntiScan.Me reports an improved detection rate of only four flags,
down from seven in our last scan.
This is a decent detection rate,
especially considering that this is one of the most commonly used document types
used in phishing attacks
and we have embedded a very widely-used shellcode stager.
Abusing the Microsoft Office file format to obfuscate the shellcode
is a relatively new concept
and parts of the file format are still undocumented
so it is quite possible that other evasion techniques have so far gone undiscovered.
It is important that we target the
correct version of Office when we perform VBA stomping,
otherwise the VBA code will fail to execute entirely.
In this section, we have examined detection rates and
possible evasions while having the shellcode runner inside the VBA macro.
Next, we will further reduce our detection rates
by once again staging with PowerShell.