malware analysis

Analyzing Malware Behavior with Cuckoo Sandbox

Executes malware samples in Cuckoo Sandbox to observe runtime behavior including process creation, file system modifications, registry changes, network communications, and API calls. Generates comprehensive behavioral reports for malware classification and IOC extraction. Activates for requests involving dynamic malware analysis, sandbox detonation, behavioral analysis, or automated malware execution.

behavioral-analysiscuckoodynamic-analysismalwaresandbox
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

When to Use

  • A suspicious sample passed static analysis triage and requires behavioral observation in a controlled environment
  • You need to capture network traffic, file drops, registry modifications, and API calls from a malware execution
  • Determining the full infection chain including second-stage payload downloads and persistence mechanisms
  • Generating behavioral signatures and YARA rules based on observed runtime activity
  • Automated analysis of bulk malware samples requiring consistent reporting

Do not use when the sample is a known ransomware variant that may spread via network shares in a misconfigured sandbox; verify network isolation first.

Prerequisites

  • Cuckoo Sandbox 3.x installed on a dedicated analysis server (Ubuntu 22.04 recommended)
  • Guest VMs configured with Windows 10/11 snapshots (Cuckoo agent installed, snapshots taken at clean state)
  • VirtualBox, KVM, or VMware configured as the Cuckoo virtualization backend
  • Isolated network with InetSim or FakeNet-NG for simulating internet services
  • Suricata or Snort integrated for network-level signature matching during analysis
  • Sufficient disk space for PCAP captures and memory dumps (minimum 500 GB recommended)

Workflow

Step 1: Submit Sample to Cuckoo

Submit the malware sample for automated analysis:

# Submit via command line
cuckoo submit /path/to/suspect.exe
 
# Submit with specific analysis timeout (300 seconds)
cuckoo submit --timeout 300 /path/to/suspect.exe
 
# Submit with specific VM and analysis package
cuckoo submit --machine win10_x64 --package exe --timeout 300 /path/to/suspect.exe
 
# Submit via REST API
curl -F "file=@suspect.exe" -F "timeout=300" -F "machine=win10_x64" \
  http://localhost:8090/tasks/create/file
 
# Submit URL for analysis
curl -F "url=http://malicious-site.com/payload" -F "timeout=300" \
  http://localhost:8090/tasks/create/url
 
# Check task status
curl http://localhost:8090/tasks/view/1 | jq '.task.status'

Step 2: Monitor Execution in Real-Time

Track the analysis progress and observe live behavior:

# Watch Cuckoo analysis log
tail -f /opt/cuckoo/log/cuckoo.log
 
# Monitor analysis task status
cuckoo status
 
# Access Cuckoo web interface for live screenshots and process tree
# Navigate to http://localhost:8080/analysis/<task_id>/

Key behavioral events to watch during execution:

  • Process creation chain (parent-child relationships)
  • Network connection attempts to external IPs
  • File drops in temporary directories or system folders
  • Registry modifications to Run keys or service entries
  • API calls related to encryption (CryptEncrypt), injection (WriteProcessMemory), or evasion

Step 3: Analyze Process Activity

Review the process tree and API call trace from the Cuckoo report:

# Parse Cuckoo JSON report programmatically
import json
 
with open("/opt/cuckoo/storage/analyses/1/reports/report.json") as f:
    report = json.load(f)
 
# Process tree analysis
for process in report["behavior"]["processes"]:
    pid = process["pid"]
    ppid = process["ppid"]
    name = process["process_name"]
    print(f"PID: {pid} PPID: {ppid} Name: {name}")
 
    # Extract suspicious API calls
    for call in process["calls"]:
        api = call["api"]
        if api in ["CreateRemoteThread", "VirtualAllocEx", "WriteProcessMemory",
                    "NtCreateThreadEx", "RegSetValueExA", "URLDownloadToFileA"]:
            args = {arg["name"]: arg["value"] for arg in call["arguments"]}
            print(f"  [!] {api}({args})")

Step 4: Review Network Activity

Examine network connections, DNS queries, and HTTP requests:

# Network analysis from Cuckoo report
network = report["network"]
 
# DNS resolutions
print("DNS Queries:")
for dns in network.get("dns", []):
    print(f"  {dns['request']} -> {dns.get('answers', [])}")
 
# HTTP requests
print("\nHTTP Requests:")
for http in network.get("http", []):
    print(f"  {http['method']} {http['uri']} (Host: {http['host']})")
    if http.get("body"):
        print(f"    Body: {http['body'][:200]}")
 
# TCP connections
print("\nTCP Connections:")
for tcp in network.get("tcp", []):
    print(f"  {tcp['src']}:{tcp['sport']} -> {tcp['dst']}:{tcp['dport']}")
 
# Extract PCAP for deeper Wireshark analysis
# PCAP location: /opt/cuckoo/storage/analyses/1/dump.pcap

Step 5: Examine File System and Registry Changes

Document persistence mechanisms and dropped files:

# File operations
print("Files Created/Modified:")
for f in report["behavior"].get("summary", {}).get("files", []):
    print(f"  {f}")
 
# Dropped files with hashes
print("\nDropped Files:")
for dropped in report.get("dropped", []):
    print(f"  Path: {dropped['filepath']}")
    print(f"  SHA-256: {dropped['sha256']}")
    print(f"  Size: {dropped['size']} bytes")
    print(f"  Type: {dropped['type']}")
 
# Registry modifications
print("\nRegistry Keys Modified:")
for key in report["behavior"].get("summary", {}).get("keys", []):
    print(f"  {key}")

Step 6: Review Signatures and Scoring

Check Cuckoo's behavioral signatures and threat scoring:

# Behavioral signatures triggered
print("Triggered Signatures:")
for sig in report.get("signatures", []):
    severity = sig["severity"]
    name = sig["name"]
    description = sig["description"]
    marker = "[!]" if severity >= 3 else "[*]"
    print(f"  {marker} [{severity}/5] {name}: {description}")
    for mark in sig.get("marks", []):
        if mark.get("call"):
            print(f"      API: {mark['call']['api']}")
        if mark.get("ioc"):
            print(f"      IOC: {mark['ioc']}")
 
# Overall score
score = report.get("info", {}).get("score", 0)
print(f"\nOverall Threat Score: {score}/10")

Step 7: Extract Memory Dump Artifacts

Analyze the full memory dump captured during execution:

# Memory dump is saved at:
# /opt/cuckoo/storage/analyses/1/memory.dmp
 
# Use Volatility to analyze the memory dump
vol3 -f /opt/cuckoo/storage/analyses/1/memory.dmp windows.pslist
vol3 -f /opt/cuckoo/storage/analyses/1/memory.dmp windows.malfind
vol3 -f /opt/cuckoo/storage/analyses/1/memory.dmp windows.netscan

Key Concepts

Term Definition
Dynamic Analysis Executing malware in a controlled environment to observe runtime behavior including system calls, network activity, and file operations
Sandbox Evasion Techniques malware uses to detect virtual/sandbox environments and alter behavior to avoid analysis (sleep timers, VM checks, user interaction checks)
API Hooking Cuckoo's method of intercepting Windows API calls made by the malware to log function names, parameters, and return values
InetSim Internet services simulation tool that responds to malware network requests (HTTP, DNS, SMTP) within the isolated analysis network
Process Injection Malware technique of injecting code into legitimate processes; detected by monitoring VirtualAllocEx and WriteProcessMemory API sequences
Behavioral Signature Rule-based detection matching specific sequences of API calls, file operations, or network activity to known malware behaviors
Analysis Package Cuckoo module defining how to execute a specific file type (exe, dll, pdf, doc) within the guest VM for proper behavioral capture

Tools & Systems

  • Cuckoo Sandbox: Open-source automated malware analysis system providing behavioral reports, network captures, and memory dumps
  • InetSim: Internet services simulation suite providing fake HTTP, DNS, SMTP, and other services for isolated malware analysis networks
  • FakeNet-NG: FLARE team's network simulation tool that intercepts and redirects all network traffic for analysis
  • Suricata: Network IDS/IPS integrated with Cuckoo for real-time signature-based detection of malicious network traffic
  • Volatility: Memory forensics framework used to analyze memory dumps captured during Cuckoo analysis

Common Scenarios

Scenario: Analyzing a Multi-Stage Dropper

Context: Static analysis reveals a packed executable with minimal imports and high entropy. The sample needs sandbox execution to observe unpacking, payload delivery, and C2 establishment.

Approach:

  1. Submit sample to Cuckoo with extended timeout (600 seconds) to capture slow-acting behavior
  2. Review process tree for child process creation (dropper spawning payload processes)
  3. Identify dropped files in %TEMP%, %APPDATA%, or system directories
  4. Extract dropped files and compute hashes for separate analysis
  5. Map network connections to identify C2 infrastructure contacted after initial execution
  6. Check for persistence mechanisms (Run keys, scheduled tasks, services) in registry modifications
  7. Compare behavioral signatures against known malware families

Pitfalls:

  • Using insufficient analysis timeout causing the sandbox to terminate before second-stage payload executes
  • Not configuring InetSim to respond to DNS and HTTP requests, preventing the malware from progressing past C2 check-in
  • Ignoring sandbox evasion detections; if the sample exits immediately, it may be detecting the virtual environment
  • Not analyzing dropped files separately; the initial dropper may be less interesting than the final payload

Output Format

DYNAMIC ANALYSIS REPORT - CUCKOO SANDBOX
==========================================
Task ID:          1547
Sample:           suspect.exe (SHA-256: e3b0c44298fc1c149afbf4c8996fb924...)
Analysis Time:    300 seconds
VM:               win10_x64 (Windows 10 21H2)
Score:            8.5/10
 
PROCESS TREE
suspect.exe (PID: 2184)
  └── cmd.exe (PID: 3456)
      └── powershell.exe (PID: 4012)
          └── svchost_fake.exe (PID: 4568)
 
FILE SYSTEM ACTIVITY
[CREATED]  C:\Users\Admin\AppData\Local\Temp\payload.dll
[CREATED]  C:\Windows\System32\svchost_fake.exe
[MODIFIED] C:\Windows\System32\drivers\etc\hosts
 
REGISTRY MODIFICATIONS
[SET] HKCU\Software\Microsoft\Windows\CurrentVersion\Run\WindowsUpdate = "C:\Windows\System32\svchost_fake.exe"
[SET] HKLM\SYSTEM\CurrentControlSet\Services\FakeService\ImagePath = "C:\Windows\System32\svchost_fake.exe"
 
NETWORK ACTIVITY
DNS:    update.malicious[.]com -> 185.220.101.42
HTTP:   POST hxxps://185.220.101[.]42/gate.php (beacon)
TCP:    10.0.2.15:49152 -> 185.220.101.42:443 (237 connections)
 
BEHAVIORAL SIGNATURES
[!] [4/5] injection_createremotethread: Injects code into remote process
[!] [4/5] persistence_autorun: Modifies Run registry key for persistence
[!] [3/5] network_cnc_http: Performs HTTP C2 communication
[*] [2/5] antiav_detectfile: Checks for antivirus product files
 
DROPPED FILES
payload.dll    SHA-256: abc123... Size: 98304  Type: PE32 DLL
svchost_fake.exe SHA-256: def456... Size: 184320 Type: PE32 EXE
Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 1

api-reference.md2.6 KB

API Reference: Cuckoo Sandbox

Cuckoo CLI

Sample Submission

cuckoo submit /path/to/sample.exe
cuckoo submit --timeout 300 /path/to/sample.exe
cuckoo submit --machine win10_x64 --package exe sample.exe
cuckoo submit --url "http://malicious-url.com"

Status

cuckoo status
tail -f /opt/cuckoo/log/cuckoo.log

Cuckoo REST API

Submit File

curl -F "file=@sample.exe" -F "timeout=300" \
  http://localhost:8090/tasks/create/file

Response: {"task_id": 1}

Submit URL

curl -F "url=http://malicious.com" -F "timeout=300" \
  http://localhost:8090/tasks/create/url

Check Task Status

curl http://localhost:8090/tasks/view/<task_id>

Status values: pending, running, completed, reported

Get Report

curl http://localhost:8090/tasks/report/<task_id>
curl http://localhost:8090/tasks/report/<task_id>/json

List Tasks

curl http://localhost:8090/tasks/list
curl http://localhost:8090/tasks/list?limit=50&offset=0

Report JSON Structure

Key Paths

Path Content
info.score Threat score (0-10)
info.duration Analysis duration (seconds)
behavior.processes Process tree with API calls
behavior.summary.files Created/modified files
behavior.summary.keys Modified registry keys
network.dns DNS resolutions
network.http HTTP requests
network.tcp TCP connections
dropped Dropped files with hashes
signatures Triggered behavioral signatures

Signature Severity Levels

Level Meaning
1 Informational
2 Low
3 Medium
4 High
5 Critical

Analysis Packages

Package File Type
exe Windows executables
dll DLL files (uses rundll32)
doc Word documents
xls Excel spreadsheets
pdf PDF documents
js JavaScript files
vbs VBScript files
ps1 PowerShell scripts
zip Archives (auto-extracted)

InetSim - Network Simulation

Syntax

inetsim --bind-address 192.168.56.1
inetsim --report-dir /var/log/inetsim

Simulated Services

  • HTTP/HTTPS (ports 80, 443)
  • DNS (port 53)
  • SMTP (port 25)
  • FTP (port 21)
  • IRC (port 6667)

FakeNet-NG - Network Redirection

Syntax

fakenet
fakenet -c custom_config.ini

Volatility Integration

Syntax

vol3 -f /opt/cuckoo/storage/analyses/<id>/memory.dmp windows.pslist
vol3 -f /opt/cuckoo/storage/analyses/<id>/memory.dmp windows.malfind
vol3 -f /opt/cuckoo/storage/analyses/<id>/memory.dmp windows.netscan

Scripts 1

agent.py9.1 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Cuckoo Sandbox behavioral analysis agent for automated malware detonation and reporting."""

import json
import os
import sys
import hashlib

try:
    import requests
    HAS_REQUESTS = True
except ImportError:
    HAS_REQUESTS = False


CUCKOO_API = os.environ.get("CUCKOO_API", "http://localhost:8090")
CUCKOO_STORAGE = os.environ.get("CUCKOO_STORAGE", "/opt/cuckoo/storage/analyses")


def submit_file(filepath, timeout=300, machine=None, package=None):
    """Submit a malware sample to Cuckoo via REST API."""
    if not HAS_REQUESTS:
        return None
    url = f"{CUCKOO_API}/tasks/create/file"
    files = {"file": (os.path.basename(filepath), open(filepath, "rb"))}
    data = {"timeout": timeout}
    if machine:
        data["machine"] = machine
    if package:
        data["package"] = package
    resp = requests.post(url, files=files, data=data, timeout=30)
    if resp.status_code == 200:
        return resp.json().get("task_id")
    return None


def submit_url(url_to_analyze, timeout=300):
    """Submit a URL to Cuckoo for analysis."""
    if not HAS_REQUESTS:
        return None
    url = f"{CUCKOO_API}/tasks/create/url"
    data = {"url": url_to_analyze, "timeout": timeout}
    resp = requests.post(url, data=data, timeout=30)
    if resp.status_code == 200:
        return resp.json().get("task_id")
    return None


def get_task_status(task_id):
    """Check the status of a Cuckoo analysis task."""
    if not HAS_REQUESTS:
        return None
    url = f"{CUCKOO_API}/tasks/view/{task_id}"
    resp = requests.get(url, timeout=30)
    if resp.status_code == 200:
        return resp.json().get("task", {}).get("status")
    return None


def load_report(task_id, report_dir=None):
    """Load a Cuckoo JSON report from disk."""
    if report_dir is None:
        report_dir = CUCKOO_STORAGE
    report_path = os.path.join(report_dir, str(task_id), "reports", "report.json")
    if os.path.exists(report_path):
        with open(report_path, "r") as f:
            return json.load(f)
    return None


def analyze_processes(report):
    """Extract and analyze the process tree from the Cuckoo report."""
    processes = []
    for proc in report.get("behavior", {}).get("processes", []):
        pid = proc.get("pid")
        ppid = proc.get("ppid")
        name = proc.get("process_name")
        suspicious_apis = []
        dangerous_apis = [
            "CreateRemoteThread", "VirtualAllocEx", "WriteProcessMemory",
            "NtCreateThreadEx", "RegSetValueExA", "URLDownloadToFileA",
            "ShellExecuteA", "ShellExecuteW", "WinExec", "CreateProcessA",
            "NtWriteVirtualMemory", "QueueUserAPC",
        ]
        for call in proc.get("calls", []):
            if call.get("api") in dangerous_apis:
                args = {arg["name"]: arg["value"] for arg in call.get("arguments", [])}
                suspicious_apis.append({"api": call["api"], "args": args})
        processes.append({
            "pid": pid,
            "ppid": ppid,
            "name": name,
            "suspicious_api_calls": len(suspicious_apis),
            "top_suspicious": suspicious_apis[:10],
        })
    return processes


def analyze_network(report):
    """Extract network activity from the Cuckoo report."""
    network = report.get("network", {})
    return {
        "dns": [
            {"request": d.get("request"), "answers": d.get("answers", [])}
            for d in network.get("dns", [])
        ],
        "http": [
            {"method": h.get("method"), "host": h.get("host"),
             "uri": h.get("uri"), "body_size": len(h.get("body", ""))}
            for h in network.get("http", [])
        ],
        "tcp_connections": [
            {"src": t.get("src"), "sport": t.get("sport"),
             "dst": t.get("dst"), "dport": t.get("dport")}
            for t in network.get("tcp", [])
        ],
        "udp_connections": [
            {"src": u.get("src"), "sport": u.get("sport"),
             "dst": u.get("dst"), "dport": u.get("dport")}
            for u in network.get("udp", [])
        ],
    }


def analyze_dropped_files(report):
    """Extract dropped file information from the report."""
    dropped = []
    for d in report.get("dropped", []):
        dropped.append({
            "filepath": d.get("filepath", ""),
            "sha256": d.get("sha256", ""),
            "size": d.get("size", 0),
            "type": d.get("type", ""),
        })
    return dropped


def analyze_signatures(report):
    """Extract triggered behavioral signatures."""
    signatures = []
    for sig in report.get("signatures", []):
        marks = []
        for mark in sig.get("marks", []):
            if mark.get("ioc"):
                marks.append(mark["ioc"])
            elif mark.get("call"):
                marks.append(mark["call"].get("api", ""))
        signatures.append({
            "name": sig.get("name"),
            "severity": sig.get("severity"),
            "description": sig.get("description"),
            "marks": marks[:5],
        })
    return sorted(signatures, key=lambda x: x.get("severity", 0), reverse=True)


def analyze_registry(report):
    """Extract registry modifications from behavior summary."""
    summary = report.get("behavior", {}).get("summary", {})
    return {
        "keys_modified": summary.get("keys", [])[:20],
        "files_created": summary.get("files", [])[:20],
        "mutexes": summary.get("mutexes", [])[:10],
    }


def generate_summary(report, processes, network, dropped, signatures, registry):
    """Generate a consolidated analysis summary."""
    info = report.get("info", {})
    score = info.get("score", 0)
    return {
        "task_id": info.get("id"),
        "sample": info.get("category", "file"),
        "analysis_time": info.get("duration", 0),
        "machine": info.get("machine", {}).get("name", ""),
        "threat_score": score,
        "process_count": len(processes),
        "suspicious_api_total": sum(p["suspicious_api_calls"] for p in processes),
        "dns_queries": len(network["dns"]),
        "http_requests": len(network["http"]),
        "tcp_connections": len(network["tcp_connections"]),
        "dropped_files": len(dropped),
        "signatures_triggered": len(signatures),
        "high_severity_sigs": len([s for s in signatures if s["severity"] >= 3]),
        "registry_keys_modified": len(registry["keys_modified"]),
        "files_created": len(registry["files_created"]),
    }


if __name__ == "__main__":
    print("=" * 60)
    print("Cuckoo Sandbox Behavioral Analysis Agent")
    print("Automated malware detonation and report parsing")
    print("=" * 60)

    if len(sys.argv) > 1:
        arg = sys.argv[1]

        # Check if argument is a report JSON path
        if arg.endswith(".json") and os.path.exists(arg):
            print(f"\n[*] Loading report: {arg}")
            with open(arg, "r") as f:
                report = json.load(f)
        elif arg.isdigit():
            print(f"\n[*] Loading report for task ID: {arg}")
            report = load_report(int(arg))
        elif os.path.exists(arg):
            print(f"\n[*] Submitting sample: {arg}")
            sha256 = hashlib.sha256(open(arg, "rb").read()).hexdigest()
            print(f"[*] SHA-256: {sha256}")
            task_id = submit_file(arg)
            if task_id:
                print(f"[*] Task submitted: ID={task_id}")
                print(f"[*] Monitor at: {CUCKOO_API.replace('8090', '8080')}/analysis/{task_id}/")
            else:
                print("[ERROR] Failed to submit. Check Cuckoo API connection.")
            sys.exit(0)
        else:
            report = None

        if report:
            processes = analyze_processes(report)
            network = analyze_network(report)
            dropped = analyze_dropped_files(report)
            signatures = analyze_signatures(report)
            registry = analyze_registry(report)
            summary = generate_summary(report, processes, network, dropped, signatures, registry)

            print(f"\n--- Analysis Summary ---")
            print(f"  Score: {summary['threat_score']}/10")
            print(f"  Processes: {summary['process_count']}")
            print(f"  Suspicious APIs: {summary['suspicious_api_total']}")
            print(f"  Signatures: {summary['signatures_triggered']} "
                  f"({summary['high_severity_sigs']} high severity)")

            print(f"\n--- Network ---")
            print(f"  DNS: {summary['dns_queries']}, HTTP: {summary['http_requests']}, "
                  f"TCP: {summary['tcp_connections']}")
            for http in network["http"][:5]:
                print(f"    {http['method']} {http['host']}{http['uri']}")

            print(f"\n--- Dropped Files ---")
            for d in dropped[:5]:
                print(f"    {d['filepath']} ({d['size']} bytes)")

            print(f"\n--- Top Signatures ---")
            for s in signatures[:5]:
                print(f"  [{s['severity']}/5] {s['name']}: {s['description']}")
    else:
        print(f"\n[DEMO] Usage:")
        print(f"  python agent.py <sample.exe>      # Submit to Cuckoo")
        print(f"  python agent.py <task_id>          # Parse existing report")
        print(f"  python agent.py <report.json>      # Parse JSON report file")
Keep exploring