AtBlackHat Asia we released Evil Clippy, a tool which assists red teamers and security testers in creating malicious MS Office documents. Amongst others, Evil Clippy can hide VBA macros, stomp VBA code (via p-code) and confuse popular macro analysis tools. It runs on Linux, OSX and Windows.
At the time of writing, this tool is capable of getting malicious macros to bypass all major antivirus products and most maldoc analysis tools. It achieves this by manipulating MS Office files on a file format level.
The following screenshot shows detection rates of a default Cobalt Strike VBA macro before Evil Clippy is applied. This is a basic process injection macro which is obviously malicious and is detected by practically all major antivirus vendors.
Note that Evil Clippy only focuses on evasion of static analysis. A combination which can be particularly effective for initial compromise during red teaming operations is to deliver malicious documents generated with Evil Clippy via HTML smuggling (which helps you bypass perimeter defenses). If you need to evade dynamic analysis of macros, then read our blog on bypassing AMSI for VBA.
In order to understand how Evil Clippy works, we need to dive into the Compound File Binary Format (CFBF). This file format is used abundantly in MS Office. Evil Clippy supports the following two MS Office file types:
Note that some streams contain compressed data (most notably the dir and module streams), using a custom compression algorithm. Evil Clippy reuses code from Kavod.VBA.Compression to implement the compression algorithm.
For more information on this file format, watch our TROOPERS19 presentation titled MS Office File Format Sorcery. If you dive deeper into the MS-OVBA specifications, you will soon note the following issues:
In summary: if we know the version of MS Office of a target system (e.g. Office 2016, 32 bit), we can replace our malicious VBA source code with fake code, while the malicious code will still get executed via p-code. In the meantime, any tool analyzing the VBA source code (such as antivirus) is completely fooled.
For example, in order to replace the VBA source code in your malicious document with fake code and to have the malicious p-code run on 32 bit installs of Office 2016, run Evil Clippy with the following command line:
So in order to make this attack work, we need to know the MS Office version of our target. Achieving this is not as difficult as it sounds. A common trick is to send the victim an email that contains a tracking pixel. If the pixel is retrieved by MS Outlook (which is usually part of the same MS Office install), the headers of this HTTP request will disclose the MS Office version number and whether it is a 32 or 64 bit install.
Note that after running a macro using p-code in MS Office, the VBA engine will reconstruct the VBA source code from p-code and display it in the VBA editor GUI when opened. Hence, we need an additional trick to hide our malicious code from prying eyes.
Another trick to make macro code unaccessible is to mark the project as locked and unviewable. This feature has been added to Evil Clippy by Carrie Robberts from Walmart and can be used with the -u flag. Carrie has written a detailed blog on this topic.
Although the -g and -u flags can hide our malicious code from human eyes, they do not protect against security tools which analyse our file on a file format level. For example, pcodedmp can be used by an analyst to extract p-code from a document. However, we can use the ambiguity and complexity of the MS-OVBA specification to confuse various analysis tools, including pcodedmp.
How does it achieve this? With the -r flag Evil Clippy sets random ASCII module names in the Dir stream. Most analyst tools use the module names specified here, while MS Office parses module names from the undocumented _VBA_PROJECT stream. By setting a random ASCII module name most P-code and VBA analysis tools crash, while the actual P-code and VBA still runs fine in Word and Excel. More information about the root cause of this issue can be read in this Twitter thread by Vesselin Bontchev, the author of pcodedmp.
Evil Clippy only scratches the surface of issues resulting from the gap between official Microsoft specifications on VBA macros (MS-OVBA) and its actual implementation in MS Office. Since malicious macros are one of the most common methods for initial compromise by threat actors, proper defense against such macros is crucial. We believe that the lack of adequate specifications of how macros actually work in MS Office severely hinders the work of antivirus vendors and security analysts. This blog post serves as a call to Microsoft to change this for the better.
After its initial release, the project has received significant code contributions from the security team at Walmart, especially from Carrie Robberts (@OrOneEqualsOne). If you want to contribute to Evil Clippy, we are happy to receive your pull request.
python-oletools is a package of python tools to analyze Microsoft OLE2 files (also called Structured Storage, Compound File Binary Format or Compound Document File Format), such as Microsoft Office documents or Outlook messages, mainly for malware analysis, forensics and debugging. It is based on my olefile parser.
oletools are used by a number of projects and online malware analysis services, including Viper, REMnux, Hybrid-analysis.com, Joe Sandbox, Deepviz, Laika BOSS, Cuckoo Sandbox, Anlyz.io, ViperMonkey, pcodedmp,
dridex.malwareconfig.com, and probably VirusTotal. (Please contact me if you have or know a project using oletools)
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
MS Office documents with embedded VBA content store source code inside of module streams. Each module stream has a PerformanceCache that stores a separate compiled version of the VBA source code known as p-code. The p-code is executed when the MS Office version specified in the _VBA_PROJECT stream (which contains the version-dependent description of the VBA project) matches the version of the host MS Office application.[2][3]
If the document is opened with a Graphical User Interface (GUI) the malicious p-code is decompiled and may be viewed. However, if the PROJECT stream, which specifies the project properties, is modified in a specific way the decompiled VBA code will not be displayed. For example, adding a module name that is undefined to the PROJECT stream will inhibit attempts of reading the VBA source code through the GUI.[1]
Detection efforts should be placed finding differences between VBA source code and p-code.[4] VBA code can be extracted from p-code before execution with tools such as the pcodedmp disassembler. The oletools toolkit leverages the pcodedmp disassembler to detect VBA stomping by comparing keywords present in the VBA source code and p-code.[5][7]
> ... script to parse OLE and OpenXML files such as MS Office documents (e.g. Word, Excel), to detect VBA Macros, extract their source code in clear text, and detect security-related patterns such as auto-executable macros, suspicious VBA keywords used by malware, anti-sandboxing and anti-virtualization techniques, and potential IOCs (IP addresses, URLs, executable filenames, etc). It also detects and decodes several common obfuscation methods including Hex encoding, StrReverse, Base64, Dridex, VBA expressions, and extracts IOCs from decoded strings.
> ... To be able to analyze such "stomped" documents, Dr. Bontchev (@VessOnSecurity) released pcodedmp, a tool printing out the VBA bytecode of a document in a readable manner. However, the output might be still hardly readable and analyzable (please check out macaroni in tests folder). As such, pcode2code decompiles, based on pcodedmp's output, the VBA code.
TL;DR Macro code in Office documents can be digitally signed, and Office can be configured to restrict macro execution to digitally signed documents. We found a method to alter digitally signed VBA projects to execute our own, arbitrary code under the right conditions, without invalidating the digital signature.
When we recommend clients to harden their corporate environment, we often have to address macro code execution within Microsoft Office applications.
A possible recommendation is to configure Microsoft Office to restrict macro code execution to VBA projects with a digital signature: VBA code without a signature, or with an invalid signature, can not execute.
3a8082e126