Cheat sheet — Document & Script Malware¶
Companion to Module 11 — Document & Script Malware · CC BY 4.0 — print it, pin it, share it.
Last reviewed: 2026-07
Only handle live samples in an isolated, disposable analysis VM with no bridged network. The whole maldoc chain triages without executing the file — never open the document in Office/Adobe, and never browse to an extracted URL.
oletools — Office macro triage¶
oleid sample.doc # quick risk overview: VBA, Flash, encryption, indicators
olevba sample.doc # extract + decompress VBA source, apply heuristic scoring
olevba --decode sample.doc # also decode the obfuscated strings olevba recognises
olevba --json sample.doc # machine-readable — feed the IOC report
olevba -a sample.doc # analysis only (skip the source dump)
oledump.py sample.doc # list OLE streams; -s N -v dumps a stream's VBA
- olevba flags the high-risk bits: auto-execute handlers (
AutoOpen,Document_Open), shell invocation (Shell,CreateObject("WScript.Shell")), string obfuscation, and network access. Auto-exec +Shell/CreateObjectis the highest-risk pattern. - Office formats: OLE2 for
.doc/.xls(macros in the OLE stream); Open XML zip for.docx/.xlsx.
pdfid / pdf-parser — PDF triage¶
pdfid.py sample.pdf # count high-risk object types
pdfid.py -e sample.pdf # extra: also report /ObjStm, dates, etc.
pdf-parser.py sample.pdf # enumerate every object
pdf-parser.py --search JavaScript sample.pdf # locate the JS objects
pdf-parser.py -o 12 -f sample.pdf # dump object 12, apply filters (decompress)
| pdfid flag | Meaning |
|---|---|
/JS /JavaScript |
embedded JavaScript |
/OpenAction /AA |
automatic execution trigger |
/EmbeddedFile |
embedded object (maybe a PE) |
/Launch /URI |
external command / URL action |
/JS+/OpenActiontogether is the most reliable malicious-PDF signal — benign PDFs rarely need both.pdfidonly counts; usepdf-parser(orpeepdf) to extract the JavaScript.
base64 PowerShell — decode the payload¶
# The idiom to grep for in the macro/script:
# [System.Convert]::FromBase64String(...) → decode
# [System.Text.Encoding]::Unicode.GetString(...) → UTF-16LE
grep -aoiE 'frombase64string|-enc(odedcommand)?' script.ps1
# PowerShell -EncodedCommand is base64 of UTF-16LE — decode with iconv:
echo '<b64blob>' | base64 -d | iconv -f UTF-16LE -t UTF-8
# quick pure-Python decode of an -EncodedCommand blob:
python3 -c 'import base64,sys; print(base64.b64decode(sys.argv[1]).decode("utf-16-le"))' '<b64blob>'
- Base64 is encoding, not encryption — no key, so a maldoc's PowerShell always decodes statically.
FromBase64Stringis your entry point; the decoded string is your next IOC (URL / filename).
Full triage workflow → IOC + ATT&CK¶
hash → oleid/olevba (or pdfid) to find the surface → extract the script
→ decode base64/obfuscated strings → pull URL/filename IOCs → tag ATT&CK
Tags: T1566.001 (spearphishing attachment) T1059.001 (PowerShell) T1027.010 (obfuscated macro)
Gotchas worth remembering¶
- An olevba score is triage priority, not a verdict. Above the warning threshold means "look more carefully," not "malicious" — benign docs with legitimate macros score too. The verdict comes from reading what the macro does, not the heuristic total.
- Triage never requires executing the document — the delivery is legitimate (Outlook opens the
.docx, Adobe the PDF, PowerShell the script), which is exactly why you decode statically instead of detonating. pdfidcounts; it does not extract or run. Seeing/JStells you it's there — you still needpdf-parser/peepdfto read the JavaScript.- Peel nested encodings one layer at a time (base64 of gzip of base64…), running
file/xxdbetween steps so you know what you have before guessing the next. - An AI-extracted URL is a lead, not a confirmed indicator — verify via VirusTotal, and never browse to it from the analysis host.
Comments
Sign in with GitHub to comment. Choose the type: Feedback (errors or suggestions on this page) · Hints (help for fellow learners — no spoilers) · General (anything else).