When to use / when not to use
- Use: the sample is a "downloader/dropper"—small size, dynamically fetches subsequent payloads, loads/stitches the final module in memory at runtime
- Use: layer-by-layer recovery of multi-layer payload chains (downloader → decompress → in-memory load → final RAT/ransomware/miner)
- Use: analysis of reflective loading / process hollowing / module stitching delivery techniques
- Don't use: the sample itself is a complete payload (all functionality is statically visible; go to [[re-triage]] / [[re-binary-core]])
- Don't use: doing only static string extraction (first do [[re-triage]] initial reconnaissance; when downloader characteristics are not obvious, do static analysis first)
- Note: dynamic analysis is a mandatory prerequisite ([[re-sandbox]], [[re-analyze/platform-tips]] highest principle)—a downloader must be run to observe the download chain; analyze under network isolation
Tool preparation
Verify all tools before use. This skill is primarily dynamic analysis—for the runtime environment and monitoring tools, directly reuse the following skills (installation methods are in each skill); this skill additionally adds two extraction tools.
Dynamic environment (reuse; runtime is a mandatory prerequisite)
- [[re-sandbox]]: VM snapshot + network isolation (INetSim is key for feeding the download chain—it simulates HTTP receiving download requests and can replay recorded responses; pitfall 1)
- [[re-tracing]]: strace / ltrace / ProcMon / APIMonitor—call-level tracing of downloads, decompression, and process operations
- [[re-behavior]]: procmon / sysdig / bpftrace—process tree, injection detection (process hollowing/APC/reflective loading)
- [[re-memdump]]: gcore default dump—in-memory payload extraction
- Verify: sandbox snapshot ready +
strace -V+gcore --helpavailable
python3 + pefile — in-memory module parsing/stitching validation (optional but commonly used)
- For python3 installation, see [[re-proto-rev]] tool preparation
pip install pefile- Verify:
python3 -c "import pefile; print(pefile.__version__)"
pe-sieve / hollows_hunter — Windows in-memory process scanning (optional)
- Source: GitHub hasherezade/pe-sieve releases and hasherezade/hollows_hunter releases, ready to use after extraction (Windows)
- Purpose: scan process memory, extract PE modules from reflective loading/process hollowing (automated helper for step 3)
- Verify:
pe-sieve.exe /?output usage
Payload unpacking (reuse)
- [[re-anti-analysis]] ([[re-packer-id]] / [[re-unpack-simple]] / [[re-unpack-advanced]]): payloads are often packed after landing; rerun the unpacked product in the sandbox to verify
Operating steps
Execute in order, recording evidence at each step (path + sha256, see [[re-triage]]); each layer's payload "source" (URL/path/memory offset) and sha256 are the core of the report ([[re-ioc]]).
-
Initial sample identification (downloader vs complete payload):
file loader.bin && sha256sum loader.bin ls -la loader.bin # 下载器通常小(几 KB~几百 KB) strings -n 6 loader.bin | grep -iE 'http|url|download|temp|\.exe|\.dll' | head -30- Downloader characteristics: small size, strings contain URLs/paths, import table has many network and decompression APIs (WinINet/WinHTTP/URLDownloadToFile, CryptAPI, RtlDecompressBuffer); a complete payload is the opposite (all functionality is in itself)
- Check hashes against VT/community first ([[re-ti]]) to confirm family and existing conclusions; don't start from scratch
- Judged as a downloader → Step 2; already a full payload → go to [[re-binary-core]] static or [[re-malware]] behavior
-
Download/decompression chain tracking:
# Linux 沙箱内 strace -ff -o out -e trace=network,file,process ./loader.bin grep -E 'connect|sendto|openat|execve' out.* | head -50 # Windows 沙箱内: ProcMon 过滤 网络操作/文件写入/进程创建 三个类别- Network: INetSim records the URL and parameters of the sample's requests (download target, User-Agent, chunk parameters); if offline, subsequent layers cannot be obtained → replay the recorded responses as feed (Pitfall 1)
- Decompression: Observe RtlDecompressBuffer / 7z / Expand-type calls and temporary file write paths (%TEMP% common); each layer's artifacts
sha256sumarchive - Chain does not trigger → anti-sandbox delay/interaction detection (Pitfall 3), go back to [[re-sandbox]] environment masquerading
-
In-memory loading analysis (reflective loading / process hollowing):
- Reflective loading: VirtualAlloc(RWX) + manual PE parsing + manual relocation (no LoadLibrary/NtMapViewOfSection calls, all manual); characteristics: large allocation + write + execute, no process creation
- Process hollowing: NtUnmapViewOfSection (erase target process image) → NtWriteVirtualMemory (write malicious image) → SetThreadContext + ResumeThread (switch execution from suspended process)
- Observation: [[re-behavior]] process tree/injection (sysdig
proc.name=loaderor ProcMon process operations + memory writes); [[re-memdump]] during the windowgcore -o out <pid>extraction (timing see Pitfall 2) - Windows automation: pe-sieve /hollows_hunter scans processes to extract in-memory PE (optional)
-
Module stitching (multi-file composition / multi-segment writes):
# 拼接后校验: 内存切片/下载片段重组出的模块 python3 - <<'EOF' import pefile pe = pefile.PE('mem_module.bin') # 解析重组产物 print(pe.FILE_HEADER.Machine, len(pe.sections), pe.OPTIONAL_HEADER.AddressOfEntryPoint) EOF- Multi-file composition: Record the order of chunk parameters (range/chunk URL) in the download log → stitch in order; when configuration and payload are stored separately, stitch configuration first then code
- In-memory module dumping: reassemble by memory layout and section alignment slices from the dump; if pefile validation fails → alignment/offset correction (RWX section mapping, relocation table repair)
- Stitching/repair complete → return to Step 1 initial triage (file/hash/entropy), continue to next layer
-
Extract final payload for analysis:
- file/hash/entropy ([[re-triage]]) confirm final payload type: still a loader → iterate back to Step 2; is RAT/ransomware/miner/spyware → go to [[re-malware]] (full behavior/C2/report workflow)
- Packed → [[re-anti-analysis]] unpack, run the unpacked artifact back in sandbox for verification ([[re-sandbox]]) before continuing
- Each layer's sha256 + source (URL/path/memory offset) organized into the report ([[re-ioc]] structure), forming a complete delivery chain
Cross-domain joint
- [[re-sandbox]] / [[re-behavior]]: dynamic environment (mandatory prerequisite, [[re-analyze/platform-tips]] highest principle) and injection/process tree detection—this skill is referenced by the [[re-malware]] gateway, and the sandbox is workflow Step 1
- [[re-tracing]]: download/decompression chain tracking (strace / ProcMon), Step 2
- [[re-memdump]]: in-memory payload extraction (dump first by default, [[re-analyze/platform-tips]] key experience: determine dump timing by plaintext/code materialization, OEP is not a universal criterion), Step 3
- [[re-anti-analysis]]: payload packing handling and anti-sandbox bypass ([[re-packer-id]] / [[re-unpack-*]]), Step 5
- [[re-protocol]]: download protocol/C2 interaction analysis (netcap / proto-rev / crypto-*)
- [[re-ioc]]: produce IOCs and reports for each layer's hash / URL / file path
- [[re-malware]]: final payload behavior analysis, ransomware scenarios go to [[re-ransomware]]
- [[re-analyze/platform-tips]] Related branches: default sandbox, static-first, direct read vs dump (dump timing determined by materialization), Linux/Windows platform branches (strace vs ProcMon)
Common pitfalls and traps
- Multi-layer network download (network disconnection prevents obtaining subsequent layers): Symptom - run the downloader under strict network isolation, only the layer 1 behavior is seen, subsequent payloads can never be obtained, and chain analysis is interrupted; Cause - the payloads are entirely remote, and download failure breaks the chain at layer 1; Countermeasure - two phases: first identify the download URL in a controlled environment (INetSim/fake DNS), then replay the recorded bytes as simulated responses to feed the process and obtain each layer; archive the response bytes and sha256 of each layer (step 2)
- Memory payload dump timing: Symptom -
gcoredumping too early (payload not yet decrypted/not yet mapped to an executable state) or too late (already finished executing and cleaned up), the extracted module is incomplete/all zeros; Cause - the memory payload exists intact only during the landing window; Countermeasure - locate the landing point based on the trace log (network receive -> write to memory -> create thread), and dump before the reflective entry/thread creation ([[re-analyze/platform-tips]] key experience: determine the dump point by plaintext/code materialization, OEP is not a universal criterion); pair with pausing the process with a breakpoint before dumping; dump multiple times and compare - Anti-sandbox delayed download: Symptom - after detecting sandbox characteristics the sample sleeps for tens of seconds to hours, or waits for mouse/keyboard interaction before triggering the download, and a short observation window only shows "no activity"; Cause - anti-sandbox delay and interaction detection (ATT&CK T1497.003 time evasion / T1497.002 user activity detection, see [[re-sandbox]] time/interaction detection pitfalls); Countermeasure - [[re-sandbox]] environment disguise (real clock, interaction simulation, sufficient resources) + [[re-behavior]] lengthen the observation window; if necessary patch the detection point ([[re-anti-analysis]] domain)
- Encrypted payload must be decrypted first: Symptom - the downloaded "payload" has entropy >7.0 and is all random bytes, static analysis has no starting point; Cause - encrypted during transmission/landing (XOR/custom), decrypted in memory only when the loader runs; Countermeasure - [[re-crypto-id]] / [[re-crypto-keys]] statically recover the algorithm and key from the loader, or directly [[re-memdump]] extract the decrypted form in memory (skipping the on-disk form), rather than stubbornly analyzing the ciphertext
- Self-extracting loader with disguised extension: Symptom - readelf reports an error and cannot parse; Cause - PHDR is deliberately filled with corruption (to interfere with parsing); Countermeasure - ignore the corrupted PHDR and only look at the valid LOAD segments; recognize the standard pattern: entry -> decompression function -> mmap(RW) -> decompress -> mprotect(RX) -> jump
- Bit-operation-intensive code decompiles poorly: Symptom - Hex-Rays output is unreadable; Cause - ARM64 is bit-operation intensive; Countermeasure - switch to the disassembly view and analyze manually (for bitstream reading/shifting/conditional branch scenarios the decompiler is worse than looking directly at assembly)
- Self-written decompressor bug (carry semantics): Symptom - the Python-rewritten decompressor outputs incorrectly; Cause - misjudgment of the refill path return value/carry semantics; Countermeasure - carefully check the carry semantics against the assembly, and compare with known plaintext plus assertions
- Entry offset uncertain: Symptom - the meaning of the payload entry field is unclear; Cause - the data table field is undocumented; Countermeasure - trace the loader's actual jump target (
br mmap_base + offset) to confirm the entry - Extension is untrustworthy: Symptom — selecting the toolchain by suffix goes wrong; Cause — the self-extracting sample disguises its extension; Countermeasure —
fileis always the first step; choose a fault-tolerant implementation for the parser (can handle corrupted headers) (Source: reverse-skill field-journal, MIT)