Malware Triage: Static Analysis, VirusTotal, and Sandboxed Dynamic Analysis
- Malware Triage: Static Analysis, VirusTotal, and Sandboxed Dynamic Analysis
Overview
Malware triage is the process of quickly assessing an unknown file to determine whether it is malicious, what family it belongs to, and what behaviors it exhibits. The goal is not a complete reverse-engineering effort — it is to gather enough signal to make decisions: quarantine, escalate, write a detection rule, or close out a false positive.
A standard triage workflow moves through three escalating levels of effort:
- Basic static analysis — examine the file without executing it
- VirusTotal / multi-engine scanning — leverage community intelligence
- Dynamic analysis in a sandbox — observe actual runtime behavior
Each level yields different evidence and carries different risks. You should start cheap (static) and only escalate when you need more signal.
Privacy warning: Every free online tool in this page makes your submission public. Never upload a sample from an active incident, a customer environment, or any file that may contain sensitive data. Use hashes to search for existing reports first.
Basic Static Analysis
Static analysis examines the file without running it. It is fast, safe, and often sufficient to triage commodity malware.
File Identification
Never trust a file extension. Use file to identify the true format based on magic bytes:
file suspicious.exe
file suspicious.pdf
file unknown_file
Get cryptographic hashes to use as stable identifiers for the sample:
md5sum suspicious.exe
sha256sum suspicious.exe
The SHA-256 hash is the universal key for looking up samples in threat intelligence databases, VirusTotal, and malware repositories.
Strings Extraction
The strings utility extracts printable ASCII sequences from a binary. Even without disassembly, strings can reveal:
- Hard-coded URLs, IP addresses, domain names
- File paths and registry keys the malware references
- Error messages and debug output left by the developer
- Encoded or obfuscated payloads (look for base64 blocks)
- Import names (Windows API functions the binary calls)
strings suspicious.exe | less
strings -n 8 suspicious.exe # minimum 8-char strings (fewer false positives)
strings -e l suspicious.exe # wide (UTF-16LE) strings — common in Windows malware
Useful filters to run against the output:
# URLs and hostnames
strings suspicious.exe | grep -iE 'https?://|\.com|\.net|\.ru|\.cn'
# Windows registry paths
strings suspicious.exe | grep -i 'HKEY\|\\Software\|\\CurrentVersion'
# File paths
strings suspicious.exe | grep -iE '\\Users\\|\\AppData\\|\\Temp\\'
# Base64 blobs (long runs of alphanumeric + / =)
strings suspicious.exe | grep -E '^[A-Za-z0-9+/]{40,}={0,2}$'
PE Header Analysis
Windows executables (PE format) carry a header that reveals structural information useful for triage. objdump, readpe (from pev), or pedump can parse these fields.
# View PE headers, sections, and imports
objdump -x suspicious.exe
# With pev tools (apt install pev)
pestr suspicious.exe # strings
pescan suspicious.exe # anomalies
pedis suspicious.exe # disassembly of entry point
readpe suspicious.exe # full header dump
Key fields to check:
| Field | What to look for |
|---|---|
| Compile timestamp | Far-future dates indicate tampering; very old dates may indicate reuse |
| Section names | Non-standard names (.text → .xyz) or high entropy sections suggest packing |
| Import table | Suspicious APIs: CreateRemoteThread, VirtualAllocEx, WriteProcessMemory, URLDownloadToFile, CryptEncrypt |
| Subsystem | GUI vs. console; packed samples often lack the expected imports |
| Section entropy | Entropy > 7.0 in a code section usually indicates packing or encryption |
Entropy Analysis
High Shannon entropy in a section means the data is either compressed, encrypted, or obfuscated. Legitimate executables have entropy around 5–6; packed malware often has sections near 8.0 (theoretical maximum for random data).
# With python-magic and scipy (or use `binwalk -E`)
binwalk -E suspicious.exe
# FLOSS (FireEye Labs Obfuscated String Solver) — extracts decoded strings from packed samples
floss suspicious.exe
YARA Rules
YARA matches patterns in files using rules that describe byte sequences, strings, and conditions. It is the standard tool for writing and applying malware signatures.
# Run a rule set against a file
yara /path/to/rules.yar suspicious.exe
# Download community rule sets
# Yara-Rules project: https://github.com/Yara-Rules/rules
# CAPE rules: https://github.com/kevoreilly/CAPEv2/tree/master/data/yara
A simple YARA rule:
rule Suspicious_PowerShell_Download {
meta:
description = "PowerShell download cradle in a PE"
author = "example"
strings:
$ps1 = "powershell" nocase
$dl = "DownloadString" nocase
$iex = "IEX" nocase
condition:
uint16(0) == 0x5A4D and all of them
}
File Format-Specific Tools
| File type | Tool | Notes |
|---|---|---|
| Office docs | oletools (olevba, oleid) |
Extracts macros, IOCs from OLE/OOXML |
| PDFs | pdfid, pdf-parser |
Flags JavaScript, embedded files, obfuscated streams |
| JavaScript | js-beautify, node --inspect |
Deobfuscates minified/encoded JS |
| Archives | 7z l, unzip -v |
Check contents before extracting |
| APKs (Android) | apktool, jadx |
Decompiles DEX bytecode to Java |
Example with olevba (from pip install oletools):
olevba suspicious.docm
This prints any VBA macros, auto-exec triggers (AutoOpen, Document_Open), and obfuscated strings — without executing the document.
VirusTotal
VirusTotal (https://www.virustotal.com/) scans a file against 70+ antivirus engines and aggregates behavioral reports from partner sandboxes. It is the fastest way to check whether a sample is already known.
Search by Hash First
Before uploading a file, search by its SHA-256. If the sample is already known, you get a full report without submitting anything new (and without making your submission visible to AV vendors):
https://www.virustotal.com/gui/file/<SHA256>
Or via the API:
curl -s "https://www.virustotal.com/api/v3/files/<SHA256>" \
-H "x-apikey: $VT_API_KEY" | python3 -m json.tool
Interpreting the Detection Tab
The detection ratio (X / 70) tells you how many engines flagged the file. Interpret it carefully:
| Ratio | Likely meaning |
|---|---|
| 0 / 70 | Unknown or very new; not necessarily clean |
| 1–3 / 70 | Possible false positive; check which engines fired |
| 5–15 / 70 | Suspicious; generic/heuristic detection |
| 20+ / 70 | Confirmed malware; look at family labels |
Engine names and family labels are inconsistent across vendors. A label of Trojan.GenericKD.123456 tells you almost nothing on its own. Look for agreement across multiple independent engines on a family name.
Behavior Tab
If behavioral reports are available (VirusTotal runs the file through partner sandboxes including its own), the Behavior tab shows:
- DNS resolutions — hostnames the sample queried
- IP connections — remote IPs contacted
- HTTP/S requests — full URLs with methods and headers
- Files written/deleted — paths on the filesystem
- Registry keys set or read
- Processes created (including command lines)
- MITRE ATT&CK techniques observed
This aggregated view across multiple sandbox environments is often more comprehensive than any single sandbox report.
Relations Tab
The Relations tab shows files, URLs, domains, and IPs linked to the sample:
- Dropped files and their hashes
- Contacted domains/IPs with their own VT reputation scores
- Parent files that dropped or contacted this sample
- Similarity clusters
API Usage
The free API allows 4 lookups/minute and 500/day. Useful for scripted triage:
import requests
VT_API_KEY = "your_api_key_here"
def vt_lookup(sha256):
url = f"https://www.virustotal.com/api/v3/files/{sha256}"
headers = {"x-apikey": VT_API_KEY}
r = requests.get(url, headers=headers)
if r.status_code == 200:
data = r.json()["data"]["attributes"]
stats = data["last_analysis_stats"]
print(f"Malicious: {stats['malicious']}/{sum(stats.values())}")
print(f"Popular threat label: {data.get('popular_threat_classification', {}).get('suggested_threat_label', 'unknown')}")
elif r.status_code == 404:
print("Not found in VT database")
else:
print(f"Error: {r.status_code}")
vt_lookup("put_sha256_here")
Sandboxed Dynamic Analysis
Dynamic analysis runs the sample in a controlled environment and records everything that happens. This is more expensive than static analysis but reveals behaviors that are invisible in the binary — network callbacks, payload staging, credential harvesting, persistence mechanisms.
How Sandboxes Work
Most automated sandboxes follow the same general architecture:
- A clean VM snapshot is restored
- The sample is submitted and executed (with optional arguments, environment variables, or simulated user interaction)
- A monitoring agent inside the VM intercepts system calls, API calls, file I/O, and network traffic
- After a timeout (typically 60–300 seconds), the VM is suspended and the monitoring data is collected
- A report is generated with behavioral indicators and IOC lists
Evasion: Modern malware frequently checks for sandbox indicators — virtual hardware fingerprints, unusual usernames, no recent documents, mouse that never moves, uptime below a threshold. A clean sandbox report does not prove a file is benign.
IOC Categories from Sandbox Reports
| IOC type | Examples | Use |
|---|---|---|
| File hashes | SHA-256 of dropped files | Detection, hunting |
| Mutexes | Global\{GUID} |
Detect reinfection checks |
| Registry keys | HKCU\Software\Run\malware |
Persistence detection |
| Network indicators | C2 domains, IPs, JA3 hashes | Firewall/DNS blocking |
| File paths | Drop locations, staging dirs | EDR rule writing |
| Process behavior | Injecting into svchost.exe |
Behavioral detection |
| MITRE ATT&CK IDs | T1055 (Process Injection) | Framework mapping |
Online Sandbox Platforms
Any.run
URL: https://app.any.run/
Any.run is an interactive sandbox: you watch the analysis in real time and can interact with the VM (click popups, enter credentials into fake forms) to trigger behavior that only fires with user interaction.
Free tier: 16 MB file limit, Windows 7 32-bit or Windows 10, 60-second analysis, all submissions public.
What it captures:
- Process tree with API call logging
- File system changes (created, modified, deleted)
- Registry modifications
- Network traffic (DNS, HTTP/S, TCP) with full request/response reconstruction
- Screenshots and execution video
- IOC export (hosts, domains, IPs, hashes, mutexes)
- MITRE ATT&CK mapping
Workflow:
- Upload file or paste a URL
- Choose OS and interaction mode
- Watch execution live; flag interesting events
- Export the IOC list as JSON or CSV
Best for: Interactive triage of samples that require user interaction; students learning what malware does in real time.
Hybrid Analysis (Falcon Sandbox)
URL: https://hybrid-analysis.com/
CrowdStrike’s free community sandbox. Supports files up to 250 MB and provides static + dynamic analysis in one report. The community database holds over 1.5 billion IOCs searchable by hash, filename, or string.
Free tier: Unlimited public submissions, 250 MB limit, Windows/Linux/Android.
What it captures:
- Process execution trace
- File I/O operations with full paths
- Registry read/write operations
- Network communications (DNS, HTTP/S, raw TCP)
- Memory artifacts
- YARA matches against the file and dropped files
- IOC summary with copy-to-clipboard export
Workflow:
# Search for an existing report by SHA-256
https://hybrid-analysis.com/search?query=<SHA256>
If no report exists, submit the file and choose the target OS environment.
Best for: Large files; hash-based searching across community submissions; integrated YARA hunting.
Hatching Triage (tria.ge)
URL: https://tria.ge/
Triage is a high-throughput multi-OS sandbox with real-time VM monitoring and strong malware configuration extraction — it identifies known malware families and dumps their C2 configuration (address, port, encryption key) when possible.
Free tier: Public cloud, multi-OS (Windows, Linux, macOS, Android), no stated file size limit for community accounts.
What it captures:
- Full behavioral analysis across multiple OS targets simultaneously
- C2 configuration extraction for known families (Emotet, Cobalt Strike, NanoCore, etc.)
- Memory forensics
- Network traffic with protocol reconstruction
- MITRE ATT&CK tagging
- Downloadable PCAP, memory dumps, and dropped files
Report URL format: https://tria.ge/<sample_id>/behavioral1
Best for: Multi-OS comparison runs; extracting C2 infrastructure from known malware families; high-volume automated triage via API.
Joe Sandbox
URL: https://www.joesandbox.com/
Joe Sandbox provides one of the most detailed reports in the industry, including a full executive summary, behavior graphs, and PCAP download. The free community tier allows 5 analyses per day / 15 per month.
Free tier: 5/day, 15/month, Windows/macOS/Linux/Android, all submissions public.
What it captures:
- API call trace with arguments
- Process and thread lifecycle
- File system and registry operations
- Network traffic (PCAP available for download)
- Screenshots at each behavioral change
- YARA matches
- Indicators of compromise with severity ratings
Best for: Comprehensive single-sample reports; when you need PCAP for deeper network analysis.
Intezer Analyze
URL: https://analyze.intezer.com/
Intezer uses code-reuse analysis (“genetic malware analysis”) to classify a sample by finding code blocks that appear in known malware families. It is most useful for attribution and family identification rather than behavioral analysis.
Free tier: Limited scans per month; community account required.
What it captures:
- Code similarity mapping to known malware families
- Shared code blocks (even across obfuscated variants)
- Static IOC extraction
- Limited dynamic analysis on paid tier
Best for: Attribution — “this binary shares code with Lazarus Group tooling”; identifying reuse of public exploit code or commodity RATs.
MalwareBazaar and the abuse.ch Ecosystem
MalwareBazaar is not a sandbox — it is a community malware repository. Use it to find samples by hash, tag, or malware family, and to download samples for analysis in other environments.
The broader abuse.ch ecosystem provides complementary threat intelligence:
| Service | URL | Purpose |
|---|---|---|
| MalwareBazaar | https://bazaar.abuse.ch/ | Sample repository and hash lookup |
| URLhaus | https://urlhaus.abuse.ch/ | Malicious URL database |
| Feodo Tracker | https://feodotracker.abuse.ch/ | C2 botnet IP/domain blocklist |
| ThreatFox | https://threatfox.abuse.ch/ | IOC sharing platform (domains, IPs, URLs) |
| SSL Blacklist | https://sslbl.abuse.ch/ | Malicious TLS certificate fingerprints |
API example — look up a hash:
curl -X POST https://mb-api.abuse.ch/api/v1/ \
-d "query=get_info&hash=<SHA256>"
Best for: Acquiring samples for lab use; enriching IOCs with family tags; downloading blocklists for firewall/DNS rules.
Self-Hosted: CAPE Sandbox
URL: https://github.com/kevoreilly/CAPEv2
CAPE (Configurable, Automated, Payload Extraction) is the actively maintained successor to Cuckoo. It adds advanced payload extraction through debugger-controlled execution — it can unpack and dump in-memory payloads that never touch disk, making it effective against loaders and droppers that evade simpler monitors.
Deployment: Ubuntu 22.04 host, Windows 10 KVM guests. Significant infrastructure commitment (nested virtualization or dedicated hardware, 16+ GB RAM, 500+ GB disk).
What it captures:
- Full system call and API trace
- File and registry operations
- Network traffic (PCAP)
- Memory dump and Volatility integration
- Payload extraction and hash of in-memory artifacts
- YARA matching against file, memory, and network traffic
- No submission privacy concerns — your data stays local
Best for: Privacy-sensitive analysis; advanced unpacking; institutional labs; teaching sandbox internals.
Worked Example: Triage Workflow
Suppose you receive a suspicious .docm file from a phishing email.
Step 1 — hash it
sha256sum invoice_Q2.docm
# d4e5f6a7b8c9... invoice_Q2.docm
Step 2 — search VT by hash (no upload yet)
curl -s "https://www.virustotal.com/api/v3/files/d4e5f6a7b8c9..." \
-H "x-apikey: $VT_API_KEY" | python3 -m json.tool | grep -A3 'last_analysis_stats'
If the hash is known, read the report. If not, continue.
Step 3 — static analysis
file invoice_Q2.docm
olevba invoice_Q2.docm
olevba might reveal a macro that calls Shell() with a PowerShell download cradle. Note the URL. That alone may be enough to write a detection rule.
Step 4 — submit to Any.run for interactive analysis
Upload to https://app.any.run/, select Office environment with macro execution enabled. Watch:
- Does it spawn
cmd.exeorpowershell.exe? - What does the process tree look like?
- What domains/IPs does it contact?
Step 5 — collect IOCs
From the Any.run report, export:
- C2 domains and IPs → add to DNS/firewall blocklist
- Dropped file hashes → add to EDR blocklist
- Registry persistence keys → add to SIEM detection rule
- MITRE ATT&CK IDs → document in incident report
Comparison of Online Sandboxes
| Platform | Free File Limit | Interactive | Multi-OS | Submissions | PCAP Download | Config Extraction |
|---|---|---|---|---|---|---|
| Any.run | 16 MB | Yes | Win, Android, Linux | Public | Yes | No |
| Hybrid Analysis | 250 MB | No | Win, Linux, Android | Public | No | No |
| Triage | Large | Yes | Win, Linux, macOS, Android | Public | Yes | Yes |
| Joe Sandbox | No limit | No | Win, macOS, Linux, Android | Public | Yes | No |
| Intezer | No limit | No | Win, Linux | Public | No | No |
| CAPE | Unlimited | No | Win, Linux | Private (self-hosted) | Yes | Yes |
References
- VirusTotal Documentation
- Any.run — Interactive Online Malware Sandbox
- Hybrid Analysis — Free Automated Malware Analysis
- Hatching Triage Sandbox
- Joe Sandbox Community
- Intezer Analyze
- CAPEv2 — Configurable, Automated, Payload Extraction
- MalwareBazaar — abuse.ch
- ThreatFox — abuse.ch IOC Sharing
- oletools — Tools for Malicious Office Documents
- FLOSS — FireEye Labs Obfuscated String Solver
- YARA-Rules Community Rule Set
- MITRE ATT&CK Framework
- Lenny Zeltser’s Malware Analysis Resources