
Defensive Office macro analyzer in Go: extracts VBA, deobfuscates it and emulates it in a fully simulated sandbox to recover commands, PowerShell, shellcode and dropped payloads without executing the sample.
MaldocTrace is a defensive analyzer for malicious Office documents, written in Go. It extracts VBA and Excel 4.0 (XLM) macros, rebuilds obfuscated strings, and emulates the macros in a fully simulated environment. The output reports what the document would do: the commands it would run, the payloads it would decode and the files it would drop. All of it is backed by evidence that points to the module, procedure and line (or sheet and cell) that produced it.
Documents with no macros at all are covered too. Remote template injection, DDE fields, linked and embedded OLE objects (including Equation Editor exploits in RTF), hyperlinked lure images and VBA stomping are reported as static findings.
.doc, .xls, .ppt), OOXML (.docx, .docm, .xlsx, .xlsm, .pptm), RTF and raw VBA text. Includes MS-OVBA decompression, UserForm control properties, and resource limits against zip bombs and malformed containers..xls (BIFF8 formulas decompiled from parsed tokens, using the MS-XLS function tables) and .xlsm, including hidden and very hidden sheets;Auto_Open (any name Excel would run). It follows GOTO, RUN, IF, WHILE/FOR/NEXT, ON.TIME and RETURN, and applies FORMULA/FORMULA.FILL/SET.VALUE/SET.NAME, so self-decoding macros rebuild their real code;EXEC, CALL, REGISTER and aliases (URLDownloadToFileA, ShellExecuteA, WinExec, CreateProcessA) and FOPEN/FWRITE. Anti-sandbox probes (GET.WORKSPACE, GET.WINDOW, GET.CELL) get plausible answers, flagged as simulated;attachedTemplate, RTF \*\template);ms-msdt (Follina) monikers;QUOTE-encoded ones) and Excel DDE formulas and links;\objdata, corrupted OLE1 headers), with Equation Editor exploit detection: the MTEF FONT overflow (CVE-2017-11882 / CVE-2018-0802) and the MATRIX overflow (CVE-2018-0798), plus extraction of the bytes that follow;Sheets("x").Range("A1"), Cells(r, c)), document properties (BuiltInDocumentProperties("Comments"), custom properties), document variables (ActiveDocument.Variables) and UserForm controls (TextBox.Text, Label.Caption) are all available to the emulated macro..docx. Droppers often hide their payload in the document body and read it back through ActiveDocument.Paragraphs(n).Range.Text.ByRef parameters, named arguments, conditional compilation, loops, arrays and the string built-ins.Chr/StrReverse/Replace/concatenation. Each value records how it was rebuilt (concatenation+Chr, StrReverse, ...).WScript.Shell, Shell, WMI Win32_Process.Create (both GetObject and CreateObject("winmgmts:..."))FileSystemObject, ADODB.Stream, XMLHTTP/WinHttpMSScriptControl.ScriptControlParagraphs, Range, Delete, SaveAs2Sheets, Worksheets, Range, Cells, Offset), shared with the XLM engine, and ExecuteExcel4Macro/Application.Run into macro sheetsVarPtr pointers-EncodedCommand decoding, with static folding of 'ht'+'tp' concatenations before URLs are extractedMultiByteToWideChar(CP_UTF7)certutil -decode, reproduced over a virtual file system built from what the macro wroteScriptControl.AddCode, reported as script payloads rather than command linesevent-3, command-1, payload-1) and source locations. Secondary views refer to an item by its ID instead of repeating large blobs.Prebuilt binaries for Windows, Linux and macOS (x64 and ARM64) are on the Releases page, along with SHA-256 checksums. Each release's notes come from CHANGELOG.md.
Requires Go 1.23+.
go build -o maldocTrace ./cmd/maldoctrace
On Windows:
go build -o maldocTrace.exe ./cmd/maldoctrace
maldocTrace inspect <file>
maldocTrace extract <file> --out <dir> [--force]
maldocTrace analyze <file> [--format json|text|jsonl] [--timeout 30s] [--max-steps N]
[--input-format vba] [--show-strings] [--dump-payloads DIR]
maldocTrace analyze <dir> --recursive [--format jsonl] [--workers N]
maldocTrace version
| Option | Description |
|---|---|
--format text | Human-readable report (default). |
--format json | Full, versioned JSON report (schema 1.3.0). It always includes indicators, diagnostics, decoded strings and full payload content. |
--format jsonl | One JSON report per line, for batch analysis with --recursive. |
--show-strings | Text format only. Lists the reconstructed strings, deduplicated, with every module/procedure/line occurrence and the reconstruction method. |
--dump-payloads DIR | Writes decoded payloads and files dropped by the macro to DIR/<input-sha256>/, with a manifest.json. Files get neutral extensions (.bin, .txt), so nothing can run on a double-click. Existing files are never overwritten. |
--input-format vba | Analyze a plain-text VBA file. |
--timeout, --max-steps | Per-file time budget and interpreter step budget. |
Exit codes: 0 success (even when the sample is malicious), 1 analysis or internal error, 2 usage error.
The four reports below come from real malicious documents and show the main recovery paths. Long blobs are shortened with …. The full values are in the JSON output.
MultiByteToWideChar → EnumUILanguages)The macro fills a byte array with UTF-7 text and copies it into RWX memory with MultiByteToWideChar(65000, …, VarPtr(buf(0)), …). It then runs the memory through an EnumUILanguages callback. MaldocTrace resolves VarPtr to the array, captures the buffer and decodes the UTF-7 statically. The result is x64 shellcode (90 55 48 89 e5 = nop; push rbp; mov rbp,rsp).
$ maldocTrace analyze 394c97cc9d567e556a357f129aea03f737cbd2a1761df32146ef69d93afc73dc.doc
MaldocTrace 0.1.0 (schema 1.2.0)
File: 394c97cc9d567e556a357f129aea03f737cbd2a1761df32146ef69d93afc73dc.doc (60418 bytes)
SHA-256: 394c97cc9d567e556a357f129aea03f737cbd2a1761df32146ef69d93afc73dc
Format: ooxml
Status: partial | Macros: present
Operational: completed | Semantic coverage: partial