Skip to content

Cheat sheet — File Triage & Identification

Companion to Module 02 — File Triage & Identification · CC BY 4.0 — print it, pin it, share it.

Last reviewed: 2026-07

Only handle live malware in an isolated, disposable analysis VM with no bridged network.

True type — magic bytes, not the extension

file mystery.bin                 # the fast answer — reads magic bytes, not the extension
file -k mystery.bin              # keep going: report every match, not just the first
xxd mystery.bin | head           # eyeball the first bytes yourself
First bytes (hex) ASCII Type
4D 5A MZ Windows PE (.exe/.dll)
7F 45 4C 46 .ELF Linux executable
25 50 44 46 %PDF PDF
50 4B 03 04 PK ZIP / DOCX / XLSX / JAR
D0 CF 11 E0 OLE2 (.doc/.xls, maldoc)

Per-section entropy — the packing signal

# pefile in Python — section names + Shannon entropy per section
python3 - <<'PY'
import pefile
pe = pefile.PE("sample.exe")
for s in pe.sections:
    name = s.Name.rstrip(b"\x00").decode(errors="replace")
    print(f"{name:8} entropy={s.get_entropy():.2f} vsize={s.Misc_VirtualSize}")
PY
  • Entropy runs 0–8 bits/byte. Legible code (.text) sits ~5–6; >7.0 is the "something hidden here" heuristic — compression, encryption, or shellcode.
  • .upx0 / .upx1 (or any odd section name) + high entropy = almost certainly packed → route to Module 09.
  • > 7.0 is a lead, not a verdict. Installers, .rsrc with a compressed asset, and legit crypto are high-entropy too.

Compiler / packer fingerprint — Detect It Easy

diec sample.exe                  # die-cli: compiler, packer, linker, architecture
diec -e sample.exe               # include entropy report / scan output
diec -j sample.exe               # JSON output — feed the classifier
  • DIE parses internal structure, so it beats file for routing: it names MSVC vs. GCC vs. Delphi, spots UPX / MPRESS / Themida, and reports the arch (an ARM binary can't detonate in an x86 sandbox).

Triage-as-routing — the three questions per file

file sample.* ; diec sample.*                 # (1) true type + compiler/packer
python3 classify.py sample.*                   # (2) packed? per-section entropy
# (3) route:  MZ+high-entropy → Module 09 unpack
#             OLE/PDF/PK       → Module 11 doc/macro
#             MZ+low-entropy   → Module 03 static strings/PE

Gotchas worth remembering

  • The extension is a lie, or at best a polite suggestion. An "image" whose first bytes are MZ is a Windows executable — magic bytes beat the extension every time.
  • "Packed = malicious" is false, and so is a single fixed entropy threshold. High entropy is suspicious relative to the section type; treat 7.0 as "investigate," not a label.
  • Triage is routing, not analysis. Doing string extraction on a packed PE is wasted effort — note it packed, flag for unpacking/dynamic, and move to the next file. An Emotet wave is hundreds of files.
  • Magic bytes name only the outer container. A PE nested inside a ZIP inside a .doc needs each layer peeled — file on the top level won't reveal the payload.
  • Even static triage runs in the isolated VM: a double-clicked "PDF" that is really a PE is one misclick from detonation.

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).