Skip to content

Lesson 3 of 9 · 22m

Sandboxes: Useful Liars

What a sandbox verdict really means, when uploading a sample is a leak, how to make samples actually detonate, and the evasion tricks that produce clean reports for dirty files.

A sandbox report is a witness statement, not a verdict. "No malicious activity" means nothing we recognized happened in the 120 seconds we watched, in this VM, with this configuration. I once signed off on a loader that came back clean from two sandboxes. It slept for ten minutes in a loop of short NtDelayExecution calls — too fragmented for the sandbox's sleep-skipping to collapse. EDR caught it on 40 hosts the next morning. Static had shown the VM checks; I trusted the green badge over my own notes.

Public vs private: uploading is publishing

Uploading to VirusTotal or a public sandbox shares the file with every subscriber who can download it — and actors monitor those services for their own hashes. Targeted samples routinely contain the victim's email address, internal hostnames, or even credentials in a phishing kit. The rule:

  1. Hash lookup first. Already public? You've lost nothing.
  2. Unknown and targeted? Private sandbox only (self-hosted CAPE, or a commercial sandbox in private mode).
  3. Public upload only with the IR lead's sign-off, after the client knows.

Getting it to actually run

Half of "clean" reports are samples that never really executed:

  • DLLs: DllMain often does nothing. List exports first, then call the one that matters.
  • Scripts: .js/.vbs run under wscript.exe; .hta under mshta.exe.
  • Documents: macros need Office installed and content enabled; the lure tells you which button the victim was asked to press.
  • Containers: ISO/IMG/ZIP deliveries hide an .lnk that launches the real payload — detonate the shortcut, not the container.
# CAPE: run a DLL's export with a longer timeout
python3 utils/submit.py --package dll --options "function=DllRegisterServer" --timeout 300 9e1c4f.dll
C:\> rundll32.exe C:\Users\Public\9e1c4f.dll,DllRegisterServer

The evasion checklist

What commodity loaders check before doing anything interesting:

if (GetTickCount64() < 10 * 60 * 1000) ExitProcess(0);  // uptime < 10 min: fresh sandbox VM
if (si.dwNumberOfProcessors < 2)       ExitProcess(0);  // 1 vCPU: cheap analysis VM
if (ms.ullTotalPhys < (4ULL << 30))    ExitProcess(0);  // < 4 GB RAM
if (mac_prefix_is(0x08, 0x00, 0x27))   ExitProcess(0);  // VirtualBox OUI
if (recent_docs_count() < 10)          ExitProcess(0);  // nobody actually uses this machine
if (keyboard_layout_is_cis())          ExitProcess(0);  // geofence: don't detonate at home

Countermeasures: realistic VMs (4+ vCPUs, 8 GB, a lived-in user profile with browser history and documents), changed MAC prefixes and hardware strings, human-interaction emulation, longer timeouts, and running the same sample under two or three configurations.

Reading the report in the right order

Process tree → dropped files → network (DNS names, HTTP paths) → memory dumps and extracted configs → then signatures. Signatures are heuristics: "queries computer name" fires on every installer ever built.

Field notes

  • Clean sandbox + suspicious static = inconclusive, never "benign". Write it that way.
  • Record the environment in your report — OS build, timeout, network mode. IR needs to know whether "no C2 seen" means "no C2" or "INetSim answered".
  • With INetSim, every DNS answer is your sinkhole IP. Domains in the report are real; resolved IPs are not. Never paste sandbox-resolved IPs into an IOC list.
  • If the sample checks for a debugger or VM, that's a behavior worth reporting by itself.