Extracting & Analyzing VBA Macros (olevba, oledump)

30 minIn Progress

Extracting & Analyzing VBA Macros (olevba, oledump)

oletools -- The Essential Toolkit

The oletools Python package by Philippe Lagadec is the industry-standard toolkit for analyzing malicious Office documents. It provides a comprehensive set of utilities:

ToolPurposeWhen to Use
olevbaExtract and analyze VBA macrosFirst-pass macro analysis
oledump.pyAnalyze OLE2 streams (Didier Stevens)Deep stream-level inspection
oleidQuick risk indicator checkInitial triage
rtfobjExtract embedded objects from RTFRTF file analysis
oleobjExtract embedded OLE objectsEmbedded payload extraction
msoddeDetect DDE linksDDE-based attacks
mraptorDetect auto-executing macrosQuick auto-exec detection
# Install oletools
pip install oletools

# Verify installation
olevba --help
oledump.py --help

olevba -- VBA Macro Extraction and Analysis

Basic Usage

# Extract and display all VBA macro source code
olevba suspicious.doc

# Quick detection only (no extraction)
olevba --detect suspicious.doc

# Decode obfuscated strings and show analysis
olevba --decode suspicious.doc

# Reveal all VBA code including hidden attributes
olevba --reveal suspicious.doc

# Analyze an OOXML file (works the same way)
olevba suspicious.docm

Understanding olevba Output Structure

olevba output has three sections:

Section 1: OLE/VBA Information

olevba 0.60.2 - https://decalage.info/oletools
FILE: suspicious.doc
Type: OLE
-------------------------------------------------------------------------------
VBA MACRO ThisDocument.cls
in file: suspicious.doc - OLE stream: 'Macros/VBA/ThisDocument'

Section 2: VBA Source Code (the actual macro code is printed here)

Section 3: Keyword Analysis Summary

+----------+--------------------+---------------------------------------------+
|Type      |Keyword             |Description                                  |
+----------+--------------------+---------------------------------------------+
|AutoExec  |AutoOpen            |Runs when the Word document is opened        |
|AutoExec  |Document_Open       |Runs when the Word document is opened        |
|Suspicious|Shell               |May run an executable file or a system cmd   |
|Suspicious|WScript.Shell       |May run an executable file or a system cmd   |
|Suspicious|powershell          |May run PowerShell commands                  |
|Suspicious|CreateObject        |May create an OLE object                     |
|Suspicious|Environ             |May read system environment variables        |
|Suspicious|Hidden              |May hide the application                     |
|IOC       |http://cdn.evil[.]c |URL (potential C2 or payload source)         |
|Hex String|48656C6C6F          |Hex-encoded string                           |
|Base64    |cG93ZXJzaGVsbA==    |Base64 encoded string (decoded: powershell)  |
+----------+--------------------+---------------------------------------------+

olevba Keyword Categories Explained

CategoryMeaningAnalyst Action
AutoExecMacro runs automatically on open/closeIdentify the trigger mechanism
SuspiciousDangerous VBA keywords detectedTrace how these are used in the code
IOCURLs, IPs, file paths foundAdd to IOC list immediately
Hex StringsHex-encoded data in the macroDecode and analyze the content
Base64 StringsBase64-encoded payloadsDecode and check for commands/PE files
DridexDridex-style obfuscation patternsApply Dridex-specific deobfuscation
VBA StompingP-code differs from VBA sourceExtract P-code with pcodedmp for truth

oledump.py -- Stream-Level Analysis

Didier Stevens' oledump.py provides granular control over OLE2 stream inspection. While olevba gives you the big picture, oledump lets you examine individual streams at the byte level.

Listing All Streams

# List streams with the -i (info) parameter for details
oledump.py suspicious.doc -i

# Example output:
#  1:       114 '\x01CompObj'
#  2:      4096 '\x05DocumentSummaryInformation'
#  3:      4096 '\x05SummaryInformation'
#  4:      7427 '1Table'
#  5:       489 'Macros/PROJECT'
#  6:        65 'Macros/PROJECTwm'
#  7: M    6947 'Macros/VBA/NewMacros'
#  8: m     985 'Macros/VBA/ThisDocument'
#  9:      7117 'Macros/VBA/_VBA_PROJECT'
# 10:       574 'Macros/VBA/dir'

Stream Markers

MarkerMeaning
MStream contains VBA macro source code
mStream references VBA macro code (attribute stream)
EStream contains an executable or PE file
OStream contains an OLE embedded object
(none)Stream has no special markers

Extracting Macro Code

# Extract a specific VBA macro stream (decompressed)
oledump.py -s 7 -v suspicious.doc

# Extract ALL macro streams at once
oledump.py -s a -v suspicious.doc

# Extract and pipe through grep to remove comments
oledump.py -s 7 -v suspicious.doc | grep -v "^Attribute "

# Dump raw bytes from a stream (for binary analysis)
oledump.py -s 7 -d suspicious.doc > stream7.bin

Using oledump Plugins

oledump supports plugins for advanced analysis:

# Use the VBA decompression plugin
oledump.py -p plugin_vba_dco.py suspicious.doc

# Use the strings plugin on a specific stream
oledump.py -s 7 -S suspicious.doc

Analyzing Obfuscated Macros

Real-world maldocs almost always use obfuscation to evade detection and slow analysis. Understanding common patterns is essential.

Obfuscation Technique 1: String Concatenation

' Instead of "powershell", build the string dynamically
Dim cmd As String
cmd = "pow" & "ersh" & "ell" & " -w hi" & "dden -ep by" & "pass"

Obfuscation Technique 2: Chr() Encoding

' Each character encoded as its ASCII value
Dim s As String
s = Chr(112) & Chr(111) & Chr(119) & Chr(101) & Chr(114) & _
    Chr(115) & Chr(104) & Chr(101) & Chr(108) & Chr(108)
' Resolves to: "powershell"

Deobfuscation helper -- Use numbers-to-string.py (Didier Stevens):

echo "112 111 119 101 114 115 104 101 108 108" | numbers-to-string.py
# Output: powershell

Obfuscation Technique 3: Array-Based URL Assembly

' URLs split across an array, reassembled at runtime
Dim urls(2) As String
urls(0) = "hXXp://cdn" & ".update" & "-srv[.]com/payload"
urls(1) = "hXXp://backup" & ".api-check[.]net/dl"
urls(2) = "hXXp://static" & ".res-cdn[.]org/get"

Deobfuscation approach -- Pipe olevba output through helper tools:

olevba suspicious.doc | grep -i "http" | re-search.py -n "https?://[^\"'\s]+"

Obfuscation Technique 4: UserForm Hidden Data

Attackers hide payloads in UserForm control properties (text boxes, labels, captions) that are not visible in the VBA editor code listing:

# olevba extracts UserForm strings automatically
olevba suspicious.doc | grep -A2 "UserForm"

# Check for Base64 strings hidden in form controls
olevba --decode suspicious.doc

Obfuscation Technique 5: Environment Variable Abuse

' Build paths from environment variables
Dim comspec As String
comspec = Environ("COMSPEC")   ' Resolves to C:\Windows\system32\cmd.exe
Shell comspec & " /c " & payload, vbHide

Obfuscation Technique 6: ChrW and Multi-Byte Encoding

' Unicode-aware character encoding
Dim s As String
s = ChrW(104) & ChrW(116) & ChrW(116) & ChrW(112)
' Resolves to: "http"

Deobfuscation with numbers-to-string.py:

# Extract ChrW values and decode
olevba suspicious.doc | grep "ChrW" | numbers-to-string.py

Step-by-Step De-obfuscation Workflow

Step 1: EXTRACT macro code
   olevba suspicious.doc > macro_code.txt

Step 2: IDENTIFY obfuscation patterns
   - Search for Chr(), ChrW(), StrReverse(), Replace()
   - Look for eval-like constructs: Shell, Exec, Run
   - Check for Base64 strings and hex-encoded data

Step 3: RESOLVE simple substitutions
   - Chr()/ChrW() -> use numbers-to-string.py
   - String concatenation -> manually join strings
   - StrReverse() -> reverse the string
   - Replace() -> apply the replacement

Step 4: CHECK UserForms for hidden payloads
   - olevba --decode automatically extracts form data
   - Look for long Base64 strings in form controls

Step 5: TRACE execution flow
   - Start at AutoOpen/Document_Open
   - Follow function calls to identify the payload
   - Map the full execution chain

Step 6: EXTRACT final IOCs
   - URLs, IPs, domains
   - File paths (dropped files, persistence)
   - Registry keys
   - Process names and command lines

ViperMonkey -- VBA Emulation Engine

For heavily obfuscated macros that resist static analysis, ViperMonkey can emulate VBA execution:

# Install ViperMonkey
pip install vipermonkey

# Emulate macro execution
vmonkey suspicious.doc

# Output shows:
# - Which functions were called
# - String values after deobfuscation
# - Shell commands that would be executed
# - Files that would be written

Pro Tip: ViperMonkey is not perfect -- it may fail on complex obfuscation. Use it as one tool in your arsenal alongside manual analysis.


Password-Protected VBA Projects

Some maldocs protect the VBA project with a password to prevent inspection:

# Method 1: Use olevba (ignores VBA password)
olevba protected.doc
# olevba can extract macros even from password-protected projects

# Method 2: Use evilclippy to remove protection
evilclippy -uu protected.doc
# Creates a new file with VBA project password removed

# Method 3: Hex-edit approach
# Find "DPB=" in the binary and change to "DPx="
# This corrupts the password hash, Office ignores it

Cobalt Strike Shellcode Detection in Macros

When macros contain shellcode (often Base64-encoded), use specialized tools to identify Cobalt Strike beacons:

# Extract Base64 payload from macro
olevba suspicious.doc | base64dump.py -s 1 -d > shellcode.bin

# Analyze with scdbg (shellcode emulator)
scdbg /f shellcode.bin

# Check for Cobalt Strike signatures
python 1768.py shellcode.bin
# Output: Cobalt Strike beacon config if detected

# Use YARA rules for Cobalt Strike detection
yara-rules/cobalt_strike.yar shellcode.bin

Deliverable Checklist

After analyzing a malicious document, your report should include:

  • File hash (MD5, SHA256) and file type
  • Macro trigger mechanism (AutoOpen, Document_Open, etc.)
  • Full deobfuscated macro code with annotations
  • Extracted payload description (downloader, dropper, etc.)
  • Complete IOC list (URLs, IPs, file paths, registry keys)
  • ATT&CK technique mapping
  • Recommended detection signatures (YARA, Sigma)

ATT&CK Mapping

TechniqueIDRelevance
Phishing: Spearphishing AttachmentT1566.001Delivery mechanism
User Execution: Malicious FileT1204.002Victim enables macros
Command and Scripting: VBAT1059.005Macro execution
Obfuscated Files or InformationT1027Macro obfuscation
Deobfuscate/Decode FilesT1140Runtime string assembly
Ingress Tool TransferT1105Payload download
Try it in the shell
Practise this lesson's tooling on its sample in an emulated analyst shell. Output is pre-recorded — nothing executes.

Suggested triage steps

  1. 1

    Extract and decode

    Full macro extraction, decoded — the core tool this lesson is built around.

  2. 2

    Spot the obfuscation call

    Chr() calls are exactly the obfuscation olevba's decoding pass exists to undo.

  3. 3

    Confirm the resulting behaviour

    Check that the macro's ultimate effect matches what you decoded by hand.

analyst@lab:~emulated · nothing executes

MAA analyst shell — emulated. Nothing executes.

Type 'help', or click a step on the left.

$
Extracting & Analyzing VBA Macros (olevba, oledump) | Malware Analysis Academy