Untrusted Sample Handling
A malware sample is not a file to be understood; it is a live adversary you have
agreed to bring into contact with your systems. Every handling decision is a security
decision, and two cardinal errors account for most of the damage analysts do to
themselves and to the truth:
- Executing it where it can reach something real — a host with credentials, a
mounted share, real network egress, a corporate identity. Detonation is not
observation; it is running the attacker's code with your privileges. A "quick look"
on your workstation is how the analysis becomes the second incident.
- Confusing capability with intent — writing "ransomware that targets hospitals"
from the presence of an AES routine and a hardcoded string. What a sample can do is
read off its imports and strings and is nearly always broad; what it was aimed at
lives in its config, its target list, its C2, and its trigger conditions, and is a
separate, evidentiary claim.
The through-line with the rest of the library: capability is not intent, absence in
a sandbox is not benignity, and shared code is not a shared author. Each is a place
where a hostile artifact is designed to mislead exactly the analyst who relaxes.
Composes with the library:
- reverse-engineering — the mechanics of static/dynamic understanding; this skill governs doing it safely and reporting it honestly
- honest-degradation — packing, encryption, anti-analysis → partial understanding is a WARN that names what it could not reach, never a confident full verdict
- finding-custody / tamper-evident-audit-chain — hash the sample first, record provenance, never alter the original; extracted IOCs carry their chain
- threat-attribution-restraint — code reuse, a shared packer, a reused C2 are leads; they do not name an actor
- dual-use-behavior-adjudication — a sample using legitimate tools (LOLBins) is judged on context, not on the tool
- detection-engineering — IOCs and behaviors feed rule-writing there; extraction is not detection
Step 0 — Isolation invariant, decided before you touch it
State the containment before the first double-click, not after. The invariant: the
sample must never, at any stage, hold a privilege or reach a resource whose abuse you
are not prepared to treat as compromised.
- No detonation on a host with anything real — no domain-joined machine, no saved
credentials, no mounted shares, no VPN, no production network. A disposable,
snapshotted VM with controlled (recorded, filtered, or faked) network, treated as
burned after use.
- Assume the sample knows it is caged. Modern samples fingerprint sandboxes (VM
artifacts, low uptime, no user activity, known analysis tooling) and behave benignly
to fool you. Absence of malicious behavior in the sandbox is not evidence of
benignity — it is, at best, evidence you could not provoke it here. This is the
single most misread result in the discipline; treat "sandbox showed nothing" as
WARN/inconclusive, never PASS.
- Static-first. Everything reachable without running it — hash, type, strings,
imports, entropy, embedded resources, certificates, macro/script source — comes
first and carries no execution risk. Detonate only to confirm a hypothesis static
analysis raised, never to form the first one.
Step 1 — Custody before curiosity
The moment the sample exists in your hands, before analysis:
- Hash it (SHA-256) and record provenance — where it came from, when, how, who
handed it over. This is the anchor everything else references.
- Never modify the original. Work on copies; the pristine sample is evidence
(
finding-custody). Renaming, unpacking in place, or letting a tool "clean" it
destroys the artifact you may need to prove something about later.
- Label live vs inert from the start. The live sample (for analysis) and any
defanged/disarmed copy (for sharing, screenshots, tickets) are different objects and
must never be confused — a "sample" pasted into a chat that is actually live is how
the artifact escapes containment through the report.
Step 2 — Build the capability inventory (static), kept separate from intent
From static analysis, produce an inventory of what the sample is equipped to do —
and label it explicitly as capability, so no reader mistakes it for behavior:
- Imports/syscalls (crypto, network, process injection, file enumeration,
persistence APIs), strings, embedded config, packing/obfuscation (high entropy →
packed → your static view is partial, a WARN), signing status, compiler/toolchain.
Capability is broad by construction and therefore weak evidence of purpose on its own.
"Has an AES routine" is consistent with ransomware, with a secure updater, and with a
config decryptor. Do not let the scariest capability write the verdict. Keep this
column strictly apart from Step 3.
Step 3 — Intent requires the config, the target, the trigger — or you abstain
Intent is not inferred from capability; it is read from the choices the author encoded:
- Target selection — a hardcoded victim list, a domain/geo/language check, an
environment guard ("only run if domain == X"). This is where "aimed at" actually
lives.
- C2 and tasking — the real command set, the exfil destination, the operator
interface. A network capability is not exfiltration until you can show where it sends
and what.
- Trigger conditions — time bombs, kill switches, sandbox checks, activation logic.
If the sample is packed/encrypted/anti-analysis and you cannot reach the config, then
you cannot state intent — and the honest output is a scoped, degraded finding:
"capability inventory X; intent not established; blocked by packing/anti-analysis;
would require Y to reach." That is a stronger deliverable than a confident story
extrapolated from an import table. ABSTAIN on intent is a valid, defensible verdict.
Step 4 — Grade the IOCs; do not ship noise as intelligence
Extracted indicators are not equal, and a list padded with library artifacts poisons
everyone downstream who blocks on them:
- Rank by specificity — a hardcoded C2 domain/IP or a unique cryptographic key
(high) vs a common Windows API string, a standard library path, or a public-CA
certificate (noise). Ask the base-rate question: how many benign programs also
contain this? (The link to
dual-use-behavior-adjudication and to detection
false-positive budgets.)
- Flag sandbox-only artifacts — a domain the sample only contacts because it
detected the sandbox is an anti-analysis tell, not an IOC to block.
- Defang before sharing —
hxxp, [.], neutered paths — so the intelligence does
not itself become a delivery mechanism when pasted into a browser or clicked in a
ticket.
- Carry provenance — each IOC references the sample hash and how it was extracted,
so a consumer can judge and re-derive it (
claim-provenance-discipline).
Step 5 — Report with the plane of certainty marked
The write-up separates, visibly, what was observed from what was inferred, and marks
where analysis was blocked:
- Observed (static facts, sandbox behavior with the caveat that the sandbox may
have been evaded) vs inferred (purpose, targeting, attribution).
- Coverage honesty — "unpacked layer 1 of 3; layers 2–3 not reached" is stated, not
smoothed over. A partial analysis presented as complete is the reverse of the
overclaim in attribution and just as damaging.
- No actor names from code overlap — hand shared code, packers, or reused
infrastructure to
threat-attribution-restraint; they are clustering leads, not an
author.
- Capability and intent stay in separate sections — so a reader can never quote the
capability inventory as if it were established intent.
The one-line test
If your verdict required running the sample and you cannot prove the cage held and
that the sample did not simply choose to behave for you, you have a hypothesis, not a
verdict — and possibly a second incident. And if you wrote what it "targets" without
pointing at its config, its list, or its C2, you reported the capability and called it
intent.
1---2name: untrusted-sample-handling3description: Untrusted Sample Handling4---56# Untrusted Sample Handling78A malware sample is not a file to be understood; it is a live adversary you have9agreed to bring into contact with your systems. Every handling decision is a security10decision, and two cardinal errors account for most of the damage analysts do to11themselves and to the truth:1213- **Executing it where it can reach something real** — a host with credentials, a14 mounted share, real network egress, a corporate identity. Detonation is not15 observation; it is *running the attacker's code with your privileges*. A "quick look"16 on your workstation is how the analysis becomes the second incident.17- **Confusing capability with intent** — writing "ransomware that targets hospitals"18 from the presence of an AES routine and a hardcoded string. What a sample *can* do is19 read off its imports and strings and is nearly always broad; what it *was aimed at*20 lives in its config, its target list, its C2, and its trigger conditions, and is a21 separate, evidentiary claim.2223The through-line with the rest of the library: **capability is not intent, absence in24a sandbox is not benignity, and shared code is not a shared author.** Each is a place25where a hostile artifact is designed to mislead exactly the analyst who relaxes.2627Composes with the library:2829- **reverse-engineering** — the mechanics of static/dynamic understanding; this skill governs doing it *safely* and reporting it *honestly*30- **honest-degradation** — packing, encryption, anti-analysis → partial understanding is a WARN that names what it could not reach, never a confident full verdict31- **finding-custody / tamper-evident-audit-chain** — hash the sample first, record provenance, never alter the original; extracted IOCs carry their chain32- **threat-attribution-restraint** — code reuse, a shared packer, a reused C2 are leads; they do not name an actor33- **dual-use-behavior-adjudication** — a sample using legitimate tools (LOLBins) is judged on context, not on the tool34- **detection-engineering** — IOCs and behaviors feed rule-writing there; extraction is not detection3536---3738## Step 0 — Isolation invariant, decided before you touch it3940State the containment *before* the first double-click, not after. The invariant: the41sample must never, at any stage, hold a privilege or reach a resource whose abuse you42are not prepared to treat as compromised.4344- **No detonation on a host with anything real** — no domain-joined machine, no saved45 credentials, no mounted shares, no VPN, no production network. A disposable,46 snapshotted VM with controlled (recorded, filtered, or faked) network, treated as47 burned after use.48- **Assume the sample knows it is caged.** Modern samples fingerprint sandboxes (VM49 artifacts, low uptime, no user activity, known analysis tooling) and behave benignly50 to fool you. **Absence of malicious behavior in the sandbox is not evidence of51 benignity** — it is, at best, evidence you could not provoke it here. This is the52 single most misread result in the discipline; treat "sandbox showed nothing" as53 WARN/inconclusive, never PASS.54- **Static-first.** Everything reachable without running it — hash, type, strings,55 imports, entropy, embedded resources, certificates, macro/script source — comes56 first and carries no execution risk. Detonate only to *confirm* a hypothesis static57 analysis raised, never to form the first one.5859---6061## Step 1 — Custody before curiosity6263The moment the sample exists in your hands, before analysis:6465- **Hash it (SHA-256) and record provenance** — where it came from, when, how, who66 handed it over. This is the anchor everything else references.67- **Never modify the original.** Work on copies; the pristine sample is evidence68 (`finding-custody`). Renaming, unpacking in place, or letting a tool "clean" it69 destroys the artifact you may need to prove something about later.70- **Label live vs inert from the start.** The live sample (for analysis) and any71 defanged/disarmed copy (for sharing, screenshots, tickets) are different objects and72 must never be confused — a "sample" pasted into a chat that is actually live is how73 the artifact escapes containment through the report.7475---7677## Step 2 — Build the capability inventory (static), kept separate from intent7879From static analysis, produce an inventory of what the sample is *equipped* to do —80and label it explicitly as capability, so no reader mistakes it for behavior:8182- Imports/syscalls (crypto, network, process injection, file enumeration,83 persistence APIs), strings, embedded config, packing/obfuscation (high entropy →84 packed → your static view is partial, a WARN), signing status, compiler/toolchain.8586Capability is broad by construction and therefore weak evidence of purpose on its own.87"Has an AES routine" is consistent with ransomware, with a secure updater, and with a88config decryptor. Do not let the scariest capability write the verdict. Keep this89column strictly apart from Step 3.9091---9293## Step 3 — Intent requires the config, the target, the trigger — or you abstain9495Intent is not inferred from capability; it is read from the choices the author encoded:9697- **Target selection** — a hardcoded victim list, a domain/geo/language check, an98 environment guard ("only run if domain == X"). This is where "aimed at" actually99 lives.100- **C2 and tasking** — the real command set, the exfil destination, the operator101 interface. A network capability is not exfiltration until you can show where it sends102 and what.103- **Trigger conditions** — time bombs, kill switches, sandbox checks, activation logic.104105If the sample is packed/encrypted/anti-analysis and you cannot reach the config, then106you cannot state intent — and the honest output is a **scoped, degraded** finding:107"capability inventory X; intent not established; blocked by packing/anti-analysis;108would require Y to reach." That is a stronger deliverable than a confident story109extrapolated from an import table. `ABSTAIN` on intent is a valid, defensible verdict.110111---112113## Step 4 — Grade the IOCs; do not ship noise as intelligence114115Extracted indicators are not equal, and a list padded with library artifacts poisons116everyone downstream who blocks on them:117118- **Rank by specificity** — a hardcoded C2 domain/IP or a unique cryptographic key119 (high) vs a common Windows API string, a standard library path, or a public-CA120 certificate (noise). Ask the base-rate question: *how many benign programs also121 contain this?* (The link to `dual-use-behavior-adjudication` and to detection122 false-positive budgets.)123- **Flag sandbox-only artifacts** — a domain the sample only contacts because it124 detected the sandbox is an anti-analysis tell, not an IOC to block.125- **Defang before sharing** — `hxxp`, `[.]`, neutered paths — so the intelligence does126 not itself become a delivery mechanism when pasted into a browser or clicked in a127 ticket.128- **Carry provenance** — each IOC references the sample hash and how it was extracted,129 so a consumer can judge and re-derive it (`claim-provenance-discipline`).130131---132133## Step 5 — Report with the plane of certainty marked134135The write-up separates, visibly, what was observed from what was inferred, and marks136where analysis was blocked:137138- **Observed** (static facts, sandbox behavior *with the caveat that the sandbox may139 have been evaded*) vs **inferred** (purpose, targeting, attribution).140- **Coverage honesty** — "unpacked layer 1 of 3; layers 2–3 not reached" is stated, not141 smoothed over. A partial analysis presented as complete is the reverse of the142 overclaim in attribution and just as damaging.143- **No actor names from code overlap** — hand shared code, packers, or reused144 infrastructure to `threat-attribution-restraint`; they are clustering leads, not an145 author.146- **Capability and intent stay in separate sections** — so a reader can never quote the147 capability inventory as if it were established intent.148149---150151## The one-line test152153If your verdict required running the sample and you cannot prove the cage held *and*154that the sample did not simply choose to behave for you, you have a hypothesis, not a155verdict — and possibly a second incident. And if you wrote what it "targets" without156pointing at its config, its list, or its C2, you reported the capability and called it157intent.