Identify + hash
sha256sum sample ; ssdeep -b sample # exact + fuzzy hash
file sample ; exiftool sample
diec sample.exe # Detect It Easy: packer/compiler
diec -e sample.exe # -e section entropy (>7 = packed)
# imphash for family clustering
python3 -c "import pefile;print(pefile.PE('x.exe').get_imphash())"
ssdeep -m known.txt suspect.exe # match vs known set
Strings + capabilities
# FLOSS = strings + decoded/stack/tight (deobfuscated)
floss sample.exe
floss --only stack tight -- sample.exe # '--' before path
floss -j sample.exe > strings.json
# capa (v9.x) → MITRE ATT&CK / MBC capabilities
capa sample.exe
capa -vv sample.exe # show which features matched
capa -j sample.exe > caps.json
pecheck.py -y all sample.exe # PE summary + YARA
PE structure & disasm
rabin2 -I sample.exe # info: arch, bits, signed
rabin2 -i / -E / -S sample.exe # imports / exports / sections
objdump -x sample.exe | less
# deep dive: Ghidra / IDA / Binary Ninja
# red flags
- RWX section · very high entropy · tiny import table
- VirtualAlloc/WriteProcessMemory/CreateRemoteThread (injection)
- WinHttp/InternetOpenUrl/WSASocket (C2)
Unpacking
upx -l packed.exe # is it UPX?
upx -d packed.exe -o unpacked.exe
# custom packer → dump OEP in a debugger:
- bp on VirtualAlloc / tail-jump to a fresh RWX region
- run to OEP, dump the image, rebuild the IAT (Scylla)
- unpac.me for automated cloud unpacking (see §08)
# then diff: strings/imports/entropy before vs after,
# carve embedded config or a 2nd stage from resources/overlay
Sandbox + baseline
# CAPEv2 — auto config/payload extraction (Cuckoo successor)
python3 utils/submit.py sample.exe
python3 utils/submit.py --package dll --options function=Foo sample.dll
python3 utils/process.py -r <task_id> # re-run config extraction
# any.run = interactive cloud sandbox (web)
# Local baseline BEFORE detonating:
Regshot: shot1 → detonate → shot2 → Compare # reg+file diff
Observe (4 channels)
proc Process Explorer / System Informer · ProcDOT graph
fs+reg Procmon /Quiet /BackingFile cap.pml → CSV
api API Monitor (Crypto/Registry/Internet groups)
net dumpcap -i eth0 -w cap.pcapng ; TCPView
tshark -r cap.pcapng --export-objects http,./out
linux strace / ltrace / tcpdump / inotifywait
Fake the network
# cut real internet so C2 reveals itself locally
sudo inetsim # fake HTTP/S,DNS,SMTP,FTP...
fakenet # FakeNet-NG (Admin/root)
fakenet -c custom.ini -l fakenet.log
# point the VM gateway/DNS at the fake service
Memory pivots
vol -f mem.raw windows.malfind # injected RWX code
vol -f mem.raw windows.netscan # C2 sockets
vol -f mem.raw windows.cmdline
# full memory workflow → volatility3 cheat sheet
Automated
# 1) identify the family (capa rules) →
# 2) let the sandbox/extractor pull the config:
python3 utils/process.py -r <task_id> # CAPE 'cape_config' key
# frameworks CAPE uses: RATDecoders, DC3-MWCP, malduck, MaCo
# standalone family parsers (malwareconfig.com):
pip install git+https://github.com/kevthehermit/RATDecoders
python DarkComet.py sample.bin config.json
Manual blob decode
# config often = a high-entropy resource/overlay, XOR/RC4'd
- find the key: nearby string, imphash-known routine, or brute 1-byte
- XOR: xorsearch / translate.py ; RC4: look for 0x100 sbox loop
- then record the recovered indicators:
beacon URI · User-Agent · sleep/jitter · C2 host(s)
campaign/watermark · mutex · pubkey
Emulate
scdbg /f sc.bin # libemu: logs Win32 API calls
scdbg /f sc.bin /findsc # find likely entry points
scdbg /f sc.bin /s -1 # unlimited steps (packed/looping)
speakeasy -t sc.bin -r -a x64 -o report.json
# -r/--raw shellcode, -a arch; --raw-offset skips a decoder stub
Run under a debugger
# BlobRunner: maps blob, prints base, pauses → attach x64dbg
BlobRunner.exe sc.bin # BlobRunner64.exe for x64
# Cutter/Rizin ESIL (single-step without native run):
aei ; aeim ; aeip # init VM, stack/mem, set IP
aes / aeso # step / step-over ; aer = regs
Decompile
# diec/file says .NET / managed →
ilspycmd sample.dll # CLI decompile to stdout
ilspycmd -p -o ./out sample.dll # -p export compilable project
# GUI: dnSpyEx (maintained fork) — read + debug + IL patch
# JetBrains dotPeek — strong on generics/obfuscation
Deobfuscate
# use the de4dotEx / de4dot-cex forks (orig is 2015-stale)
de4dot sample.exe # → sample-cleaned.exe
de4dot -r C:/in -ro C:/out # recurse dir → output dir
de4dot --strtyp delegate --strtok 0x06000123 sample.exe
# strings still encrypted? dnSpyEx: bp the decrypt method, dump
Spot it statically (prefer static)
# Packing signal:
- section entropy >7.0 (diec -e / pefile get_entropy)
- tiny import table / near-empty imphash
- weird section names: UPX0, .themida, .aspack, .netreactor
# Anti-debug imports to flag:
IsDebuggerPresent · CheckRemoteDebuggerPresent · NtQueryInformationProcess
# PEB.BeingDebugged = fs:[0x30]+2 (x86) / gs:[0x60]+2 (x64)
Anti-VM & early exec
# Anti-VM (static grep of strings/disasm):
cpuid · rdtsc · "VMware" "VBOX" "VBoxGuest" "qemu" · hypervisor bit
# capa has rules that surface anti-debug/anti-VM automatically
# TLS callbacks run BEFORE the entry point — common unpack/anti stub
pe.DIRECTORY_ENTRY_TLS.struct.AddressOfCallBacks
Author signatures
# capa → ATT&CK/MBC (already ran in triage)
# YARA: strings + condition. Modifiers:
yara -r -s rules.yar /samples # -s show match offsets, -m meta
# xor / xor(0x01-0xff), base64 / base64wide, wide, nocase, fullword
# (nocase can't combine with base64 or xor)
# rank noisy strings by ML relevance:
flarestrings mal.exe | rank_strings -l 100 -s
Cluster & services
imphash # exact import-layout family match
ssdeep -d ./samples/* # byte-similarity across variants
# services:
unpac.me # automated unpacker (API: 'Authorization: Key ..')
VirusTotal # vt file <hash> ; vt file behaviours <hash>
FLARE-VM # Mandiant analysis distro (FLOSS/capa/stringsifter)
Instrumented VM only
Snapshot before detonation; be ready to revert.
Strings mislead
Decoys, dead strings, and encrypted blobs are the norm — corroborate.
Prefer static on anti-tamper
A debugger can corrupt data silently. Static + dynamic + memory must reinforce each other.