Skip to content

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/CreateObject is 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 + /OpenAction together is the most reliable malicious-PDF signal — benign PDFs rarely need both. pdfid only counts; use pdf-parser (or peepdf) 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. FromBase64String is 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.
  • pdfid counts; it does not extract or run. Seeing /JS tells you it's there — you still need pdf-parser/peepdf to read the JavaScript.
  • Peel nested encodings one layer at a time (base64 of gzip of base64…), running file/xxd between 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).