Obfuscating VBA
So far, we have found
that the detections on our VBA macro are mainly from signatures
since we have string content that is very easy to match,
and switching the process creation technique
did not change the detection rate.
In this section, we are going to perform some obfuscation
to hide the content of any text strings from the antivirus scanner.
The current VBA macro has three of these:
the PowerShell download cradle,
the WMI connection string, and the WMI class name.
We will make two attempts at obfuscating the strings.
The first will be a relatively simple technique,
while the second will be more complex.
VBA contains a function called StrReverse that,
given an input string,
returns a string in which the character order is reversed.
Our first obfuscation technique is going to rely on reversing all strings
to hopefully break the signature detections.
We could reverse our content strings in a number of ways,
but in this case we’ll use the Code Beautify online resource.
We can now add our updated code after reversing the strings
and inserting the StrReverse functions to restore them.
Our code will run properly but we may have replaced one red flag with another.
Since StrReverse is notoriously used in malware, we should minimize its use.
To reduce the amount of times the function name appears,
we’ll create a new function that simply calls it.
This will reduce the number of times StrReverse appears in our code.
This function uses benign names for the function and argument names.
Saving the macro in a Microsoft Word document,
and uploading it to AntiScan.Me,
reduces our detection rate from seven products to only four.
The rather simple obfuscation technique yields a massive drop in detection.
However, we have introduced a new potential flag with StrReverse
and our code may still be flagged by advanced detection engines
that reverse or otherwise permutate strings in search of signatures.
To reduce the detection rate even further, we can perform a more complex obfuscation
by converting the ASCII string to its decimal representation
and then performing a Caesar cipher encryption on the result.
To better understand the encryption and decryption technique in detail,
we’ll start by creating an encryption script in PowerShell.
We’ll create an input variable called payload
containing the string to be encrypted,
along with the output variable, which will contain the encrypted string.
We’ll convert the entire string into a character array
through the ToCharArray method,
and then run that output through a Foreach loop, with the “%” shorthand.
Inside the loop, the byte value of each character is increased by 17,
which is the Caesar cipher key selected in this example.
We’ll use if and else conditions to pad the character’s decimal representation
to three digits.
Finally, each decimal value is appended to the output string,
and piped into the clipboard through clip.
Running the PowerShell script,
copies the output to the clipboard
We can now use a similar
process for the other two content strings in the VBA macro.
Next, lets add a simple VBA decrypting routine.
This routine consists of four functions.
Notice that we are reducing the potential signature count in this decryption routine
by using benign function names related to food.
The main Nuts function performs a while loop
through the entire encrypted string
where the Oatmilk variable is used to accumulate the decrypted string.
For each iteration of the loop, the entire encrypted string is sent to Strawberries.
The function uses Left
to fetch the first three characters of the string and returns that value.
Next, the Pears function is called with the three-character string as input.
It treats the three character string as a number,
subtracts the Caesar cipher value of 17, and then converts it to a character,
that is added to the accumulator in Oatmilk.
Once a character is returned, the Almonds function is called,
inside the loop where the Right function will exclude
the first three characters that we just decrypted.
With the decryption routine implemented,
we can use it to decrypt and execute the PowerShell download cradle.
Recall that previously,
we invoked the Create method with the second and third arguments set to “Null”.
In order to replicate this, we instead use undefined variables in the VBA code above,
which by default contains the value “Null”.
Once we execute the encrypted VBA macro,
we obtain a Meterpreter reverse shell,
proving that the rather convoluted technique actually works.
We anxiously test the document against AntiScan.Me,
and discover that only two products flags our code.
Nice!
This custom encryption routine reduced our detection rate,
but we can push it even further.
Although we have fully encrypted the VBA code,
we are likely running into heuristics detection.
There are a number of ways to bypass
heuristics in VBA that do not involve the use of Win32 APIs.
One simple technique is to check the document name when the macro runs.
When most antivirus products emulate the execution of a document, they rename it.
During execution, we check the name of the document
and if we find that it is not the same as the one we originally provided,
we can assume the execution has been emulated and we can exit the code.
For example, let’s assume we named the document runner.doc.
If we check the Name property of the ActiveDocument
and find it to be anything but runner.doc, we’ll exit to avoid heuristics detection.
To further the obfuscation, we’ll even encrypt this static document name.
Putting all this together, we add our simple heuristic detection code.
Running the updated document,
we find that it generates a Meterpreter reverse shell
as long as our file is named runner.doc.
As a result, AntiScan.Me reports that our code
is only flagged by one antivirus product!
Excellent!
We have once again achieved a very low detection rate.