Last Updated: 2019-12-09 00:08:01 UTC
by Didier Stevens (Version: 1)
I received another malicious Word document: with VBA macros and string obfuscation, launching a PowerShell downloader. As classic as they come.
The VBA code is not too long, and the obfuscation is not that hard. It makes a good example for static analysis.
I start the analysis with my tool oledump.py, this will give me an overview of the streams (including VBA macro streams) contained in the document:
Stream 8 has an M indicator: this stream contains VBA macros. Using option -s 8 to select stream 8, and option --vbadecompressskipattributes to decompress the VBA macros without showing the hidden attributes (usually I just use option -v, since I don't mind seeing the hidden attributes), I get to see the VBA code:
There's a Document_Open subroutine: this will be executed once the document is opened and the user has accepted the warning(s). It assigns a different number to three variables, and then calls function besb repeatedly with a number as argument.
These numbers are mostly different. Function besb takes the argument (a number), divides it by 23 and multiplies it with 1. Then it converts the obtained number to a character (chr function), and concatenates it into variable ahiv.
Finally, subroutine Document_Open executes (run) string ahiv.
With this information, I know that the numbers represent a command and that I can obtain that command by dividing each number by 23 and then converting it to a character. Typically, one would write a small custom script to do this, but as I often have to do such conversions, I made my own tool to help with this: numbers-to-string.py.
Numbers-to-string.py takes text as input, extracts the numbers it finds on each line (provided there are at least 3 numbers per line), transforms the numbers according to a given formula, and then converts them to a string.
I will use this to decode the command. First I select all VBA source code lines with function besb using grep. Since identifiers in VBA are not case-sensitive, I use option -i, just in case the malware author was not consistent in his case use for function name besb.
Next, I use numbers-to-string.py to process each number. Since by default, my tool expects 3 numbers per line, and here I have only one number per line, I use option -n 1 to have my tool process each line with 1 number or more.
Each number has to divided by 23: I use expression "n / 23" to achieve this. Here is the complete command:
When I read the characters from top to bottom, I see a command forming: powershell iex …
My final step is to use option -j to join all lines together:
Like I said: a classic example.
Yet, there is something unusual about this document. To be continued ...