Phase 02 — Offensive Tooling Development (Analysis, Formats & IOC Hygiene)
Operation Cedar Lattice, Phase 02. Phase 01 produced the emulation plan — which actor FIN-LATTICE is, which techniques they use, in which order. Before executing the plan, a consultant must understand the tools that implement those techniques: their binary formats (so you can triage them), the Indicators of Compromise (IOCs) they leave behind (so you can tell the client what to look for), and the OPSEC hygiene that separates a noisy tool from an engagement-grade one.
This phase is a static-analysis and triage phase, not a build phase. The labs are a PE/ELF format parser (parsing binary headers from bytes, classifying tooling type, extracting imphash and export table) and a tooling IOC / OPSEC linter (checking a tooling inventory against an OPSEC checklist and flagging noise indicators). They work on synthetic binary metadata — no live malware, no shellcode, no deployable offensive artifact.
Safety (non-negotiable). Authorized security-education only. The labs in this phase are static analyzers and OPSEC linters over synthetic binary metadata dicts. There is no weaponized payload, no shellcode, no working implant, no PE injection, and no deployable offensive artifact in this repo. Understanding binary formats is how defenders triage tooling in a DFIR case. OPSEC hygiene is how red teams leave fewer traces for blue teams to detect — the reverse is equally true. Same boundary as all other phases.
Why this phase exists
Every technique in the emulation plan is implemented by a tool — a binary, a script, or a LOLBin. Understanding what that tool looks like from the inside (its PE/ELF structure, its import table, its strings, its imphash) is the common language between the red team consultant and the incident responder who found the tool in a DFIR case. The JD explicitly requires "experience with offensive tooling development" across C#, C/C++, Python, Nim, and Go — understanding the binary formats those languages produce is the prerequisite to using or triaging that tooling.
OPSEC hygiene — the practice of configuring tools to minimize the traces they leave — is part of what distinguishes an engagement-grade tool from a noisy one. A tool that ships its default compilation artifacts, default C2 strings, and a well-known imphash is easily blocklisted and detected within minutes. Knowing which indicators a tool creates, which logging plane sees them, and which ones the analyst uses to build detections is both the red team's concern (minimize noise) and the blue team's concern (maximize detection surface). Both perspectives are trained here.
Learning Objectives
By the end of this phase you can, without notes:
- Describe the PE (Portable Executable) format: DOS MZ header, NT headers (
IMAGE_NT_HEADERS), optional header (AddressOfEntryPoint,SizeOfImage,Subsystem), section table (.text,.data,.rdata,.rsrc), Import Directory Table (IDT) and Import Address Table (IAT), Export Directory Table. - Describe the ELF format parallel: ELF header (
e_type,e_machine,e_entry,e_phoff), program headers (segments), section headers (.text,.data,.rodata,.dynamic), dynamic symbol table,.rel.plt/.rela.plt. - Compute and explain imphash (the MD5 of the normalized import table name list) and explain why it is used for classification and attribution — and why it fails at the bottom of the Pyramid of Pain.
- Name the OPSEC indicators a tool can leave: compilation artifacts (default PDB path, linker version, compile time stamp), behavioral indicators (default named pipes, default beacon URIs, default user-agent strings, well-known imphash families), and log-plane indicators (Sysmon EID 7 image load, ETW image-load callbacks, process-creation command lines).
- Explain the tooling IOC taxonomy used in engagement reporting: host-based IOCs (file hash, imphash, PDB path, strings), network-based IOCs (JA3/JA4, URI pattern, user-agent), and behavioral IOCs (API call sequence, named-pipe name, parent-child relationship).
- Apply the Pyramid of Pain to tooling IOCs: hash/imphash at the bottom (trivial to change), behavioral TTPs at the top (costly to change), and explain which detection is worth engineering.
- Apply an OPSEC linter checklist to a tool inventory and rank the highest-noise items.
The binary format model
PE (Windows) ELF (Linux)
─────────────────────────────────────────────────────────────────────────
DOS header (MZ magic 4D5A) ELF header (magic 7F454C46)
PE signature ("PE\0\0") e_type (ET_EXEC / ET_DYN)
IMAGE_FILE_HEADER e_machine (EM_X86_64)
Machine (0x8664 = x86-64) e_entry (virtual entry point)
NumberOfSections e_phoff → program headers
TimeDateStamp (compilation time)
IMAGE_OPTIONAL_HEADER Program headers (segments)
Magic (PE32+ = 0x20B) .text (rx) / .data (rw) / .bss
AddressOfEntryPoint .dynamic → dynamic linker info
SizeOfImage
Subsystem (2=GUI, 3=CUI, 14=EFI) Section headers
DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] .text / .data / .rodata / .dynamic
.dynsym (dynamic symbol table)
Section table (.text, .data, .rdata, .rel.plt / .rela.plt
.rsrc, .reloc, ...)
Import Directory Table (IDT) Dynamic linking (equivalent)
DLL name → IAT entries → function .dynamic / .dynsym / PLT → GOT
names + ordinals
imphash = MD5(sorted normalized list)
Export Directory Table
function name → VA
Why the import table matters for detection. A Windows binary's IDT is the list of DLLs and
functions it calls. Forensic tools (imphash, pe-sieve, capa) use the import table to classify
tool families. A Cobalt Strike beacon has a distinctive import table; so does mimikatz; so does
a legitimate system binary. The imphash provides a fingerprint at medium cost (recompiling changes
it; adding a dummy import changes it). Detection at the TTP level — "this process called
NtAllocateVirtualMemory → NtWriteVirtualMemory → NtProtectVirtualMemory via ETW-TI" —
survives the recompile.
Concepts
| Concept | What it is | Why it matters to the engagement |
|---|---|---|
| PE DOS/MZ header | First 64 bytes; 0x3C → offset to PE signature | Identifies a Windows executable; missing or malformed = packed/obfuscated |
| NT headers | IMAGE_FILE_HEADER + IMAGE_OPTIONAL_HEADER | Machine type, subsystem, entry point, section layout |
| Import table / IDT | DLL + function name list; basis of imphash | Classification, attribution, detection at imphash layer |
| imphash | MD5 of sorted normalized dll.function list | Family fingerprint; bottom of Pyramid of Pain |
| Export table | List of exported function names + VAs | DLL/reflective-loader identification |
| ELF header | Magic \x7fELF, type, machine, entry | Identifies Linux executable; ET_DYN = shared obj or PIE |
.dynamic section | Tells the dynamic linker what to load | Equivalent to PE import table for ELF tooling |
| Compilation artifact | PDB path, debug directory, linker version | IOC for attribution; default paths are loud |
| Named pipe | IPC mechanism; default C2 pipes are well-known | Sysmon EID 17/18; blocked by name at detection layer |
| imphash family | Tools with identical import tables (same compile, same version) | Detection database classification |
| OPSEC indicator | Any artifact that tips off a defender | Host/network/identity plane classification |
| Pyramid of Pain | IOC taxonomy by adversary cost to change | Tells you whether a detection is durable |
| JA3/JA4 fingerprint | TLS client hello hash — network-layer fingerprint | C2 beacon identification at network layer |
Labs
| Lab | Builds | Lesson |
|---|---|---|
| Lab 01 — PE/ELF Format Analyzer | parse a synthetic binary metadata dict (DOS header, NT headers, sections, imports, exports); compute imphash; classify tooling type; extract OPSEC indicators from the header fields | binary format is how triage works — the import table and header fields are the first classification layer |
| Lab 02 — Tooling IOC / OPSEC Linter | check a tooling inventory dict against an OPSEC checklist (default named pipes, default URIs, known-bad imphash, default PDB paths, default user-agent strings); compute a noise score; return ranked findings with detection descriptions | OPSEC hygiene is measurable — every default indicator has a detection that fires on it |
Each lab follows LAB-STANDARD.md: lab.py (TODOs), solution.py (reference),
adversarial test_lab.py, README.md, requirements.txt — pure Python stdlib + pytest, offline,
deterministic.
cd lab-01-pe-format-analyzer
LAB_MODULE=solution python3 -m pytest -q # reference passes (14 tests)
cd ../lab-02-tooling-ioc-opsec-linter
LAB_MODULE=solution python3 -m pytest -q # reference passes (15 tests)
Deliverables
- A PE/ELF format analyzer that classifies synthetic binary metadata (tooling type, imphash, OPSEC-relevant header fields) and maps each finding to its detection layer and Pyramid-of-Pain level.
- A tooling IOC / OPSEC linter that scores a tooling inventory against a noise checklist and returns a ranked list of OPSEC findings with detection descriptions.
- The Operation Cedar Lattice Phase 02 artifact: the FIN-LATTICE tooling inventory triage — which tools are in-scope for the engagement, their binary-format fingerprints, their OPSEC noise score, and the detections that would catch each one at each layer (imphash, behavioral, network). Over synthetic metadata; no real malware.
- Fluency to explain PE/ELF structure, the import table, imphash, the IOC taxonomy, the Pyramid of Pain applied to tooling, and OPSEC hygiene — in an interview.
Readings (primary sources)
- Microsoft PE/COFF specification —
learn.microsoft.com/windows/win32/debug/pe-format— the authoritative reference for every field in the PE header and data directories. - ELF specification (Tool Interface Standard) —
refspecs.linuxbase.org/elf/elf.pdf. - MITRE ATT&CK: T1027 (Obfuscated Files/Information), T1055 (Process Injection), T1071 (Application Layer Protocol), T1090 (Proxy / redirectors).
- mandiant/capa — open-source tool that matches PE capabilities against ATT&CK techniques; read the rule format to understand what behavioral features are extractable from static analysis.
- imphash — Mandiant blog post "Tracking Malware with Import Hashing" (2014, Carhart). The original definition and motivation.
- David Bianco — The Pyramid of Pain. Applied to tooling IOCs, not just indicators generically.
- Sigma specification — detection rule format used to express tooling detections; a
logsource: category: image_loadrule detects specific DLL loads (Sysmon EID 7). - The Art of Memory Forensics (Ligh et al.) — chapters on PE structure and import/export analysis for forensic triage.
Common Mistakes
- Treating imphash as a durable detection. Imphash changes with a recompile or a single dummy import added. It is useful for family classification but sits at the bottom of the Pyramid of Pain. Engineer the behavioral detection in addition to logging the hash.
- Ignoring the compilation timestamp. The
TimeDateStampfield inIMAGE_FILE_HEADERis a default-on IOC that dates a compiled binary (and can be spoofed, but by default is not). A tool compiled today with a 2019 timestamp is a default artifact; one compiled in 2015 is either old or timestamp-stripped. - Confusing subsystem values. Subsystem
2(Windows GUI) is unusual for a command-line tool and may indicate a GUI wrapper or a PE that hides its console. Subsystem3(Windows CUI) is expected for typical red-team tooling. Misreading subsystem leads to wrong classification. - Missing the export table for DLL/reflective-loader detection. A DLL loaded reflectively has
an export table even when it has no disk representation. The export table name list (
ReflectiveDll,DllMain) is one of the first classifiers in a DFIR case. - OPSEC hygiene as a binary on/off. It is a ranked, contextual property: some indicators matter more in certain environments (a known-bad imphash matters more if the client has imphash-based blocking; a default named pipe matters if they have Sysmon EID 17/18 configured). The linter ranks by impact, not by presence.
- Confusing a format analyzer with a malware scanner. The lab analyzes structural metadata — it does not execute the binary, sandbox it, or detect malicious behavior through dynamic analysis. Static analysis is the first pass; it is fast but misses packed/obfuscated content.
Interview Questions
- Walk me through the PE format from the DOS header to the import table. What fields matter most for triage?
- What is imphash, how is it computed, and where does it sit on the Pyramid of Pain? When is it useful and when is it not?
- Explain the difference between the Import Directory Table and the Import Address Table in a PE. Why does the IAT matter for detecting process injection?
- What OPSEC indicators does a compiled tool leave by default? Name three and their detection.
- How does the ELF
.dynamicsection compare to the PE import table for tooling classification? - You find a binary with no import table entries. What are the likely explanations, and how do you triage further?
- A tool has a known-bad imphash. The attacker recompiles it with one dummy import. Does your detection survive? What would you build instead?
- Walk me through how you would produce the tooling triage artifact for a real engagement — what you would analyze, what output you would give the client, and what detections you would recommend.
(Full answers are in WARMUP.md.)
Portfolio artifact
FIN-LATTICE tooling triage for Operation Cedar Lattice — the per-tool analysis (PE/ELF structure
summary, imphash, OPSEC noise score) for the two synthetic tool samples in the engagement inventory;
the ranked OPSEC findings for each tool; and the detection-layer map (host hash, imphash family,
named-pipe name, network JA3, behavioral TTP) that tells Meridian where to invest detection. All over
synthetic metadata, no real malware. Part of 02-tooling/ in the
capstone portfolio.
Guides
- WARMUP.md — the from-zero deep dive: PE/ELF binary formats (field by field), imphash, export table, IOC taxonomy (host/network/behavioral), the Pyramid of Pain applied to tooling, and OPSEC hygiene — every indicator paired with its detection layer.
- HITCHHIKERS-GUIDE.md — on an owned range: use
objdump/dumpbinon allowed system binaries to observe PE/ELF structure live; feed the output as synthetic dicts into the lab analyzers; interpret the OPSEC linter output and write a Sigma rule for the highest-noise finding.