Malware Dynamic Analysis

SkillFiles & storage

Execute and monitor malware in controlled sandbox environments. Use when you need to observe runtime behavior, capture network traffic, monitor process activity, analyze file/registry changes, or understand actual malware functionality beyond static analysis. Guides safe execution with Procmon, Wire

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Malware Dynamic Analysis skill

What this skill tells your AI

The instructions your AI receives, as published by gl0bal01/malware-analysis-claude-skills in malware-dynamic-analysis/SKILL.md and read by ahel’s review.

Two halves. Part A is a runbook the analyst follows inside the isolated VM (REMnux / FlareVM); you tailor it from triage predictions and it ends with text-format evidence exports. Part B is your work: parse that evidence on the host, reconstruct what the sample did, extract behavioral IOCs, and write findings to analysis_state.md.

Execution Model

  • You never execute the sample. The VM is network-isolated and has no Claude in it. Everything you run is on the host against exported evidence files.
  • Locate skill files. Scripts and reference files ship in this skill's directory. Set R="${CLAUDE_PLUGIN_ROOT:-<dir containing this SKILL.md>}" once (when installed as a plugin $CLAUDE_PLUGIN_ROOT is set; otherwise it is this skill folder). Your working directory is the user's analysis workspace, so prefix every script path below with $R, e.g. python3 "$R"/scripts/ioc_extract.py.
  • Before the VM run: read the triage findings in analysis_state.md and emit a runbook tailored to the predictions (which process names to filter, which Sysmon event IDs matter, expected protocol, expected persistence, expected evasion). Skip the tailoring only if triage is missing — then use the default runbook as-is.
  • After the VM run: the user hands you an evidence directory. Inventory it, reject binary formats with the conversion command (see Converting Binary Evidence), and then work through Part B with Bash and the bundled scripts. Do not ask the user to summarize the evidence for you.
  • Scripts (relative to this skill dir): scripts/procmon_summary.py, scripts/sysmon_summary.py; plus ../scripts/ioc_extract.py at repo root. All stdlib Python 3.
  • Sandbox reports count as evidence. ANY.RUN / Joe Sandbox / Hybrid Analysis / Threat.Zone (MCP) JSON or text reports go through Part B Step 6.
  • Large files: wc -l first. Use the summary scripts and grep, never cat a 200k-line Procmon CSV.

Part A — VM Runbook (analyst executes this)

Emit this to the user, filled in with the sample name and triage predictions. Keep the safety checklist verbatim.

A1. Safety checklist — all boxes or do not execute

  • Clean VM snapshot taken
  • Network: host-only / internal, with INetSim or FakeNet-NG answering (never NAT to the real internet unless the engagement explicitly allows it)
  • No shared folders, no clipboard sharing, no drag-and-drop
  • Guest time sync disabled
  • Monitoring tools started before execution (order below)
  • Analysis persona active — no real credentials, names, or corporate artifacts on the VM
  • Evidence transfer path decided (USB / one-way share) and a C:\evidence\ directory created

Full VM hardening and anti-VM-detection countermeasures: references/sandbox_setup.md, references/anti_analysis_bypass.md.

A2. Start monitoring (in this order)

  1. INetSim / FakeNet-NG (network simulation)
  2. Sysmon — already installed with olafhartong/sysmon-modular or SwiftOnSecurity config
  3. Procmon — clear capture (Ctrl+X), apply filters (below)
  4. Wireshark — capture on the VM adapter
  5. System Informer
  6. Regshot 1st shot (optional) / autorunsc baseline (below)

Tool configuration details: references/tool_setup.md.

Procmon filters (tailor from triage — add predicted child processes and LOLBins):

Process Name  is        <sample.exe>              Include
Process Name  is        <predicted child, e.g. powershell.exe, rundll32.exe>   Include
Operation     contains  Process                   Include   (keeps Process Create for the tree)
Process Name  is        procmon.exe / SystemInformer.exe / wireshark.exe   Exclude

Do not filter to the sample alone if injection is predicted — include the predicted target (explorer.exe, svchost.exe, RegAsm.exe, …).

Baseline persistence snapshot (Sysinternals Autoruns, run as admin):

autorunsc64.exe -accepteula -a * -c -h -s -nobanner | Out-File -Encoding utf8 C:\evidence\autoruns_before.csv

A3. Execute

# EXE
.\sample.exe                     # add args if triage found a required switch, e.g. /install /silent
# DLL — triage lists the exports; try DllMain first, then each named export
rundll32.exe sample.dll,DllMain
rundll32.exe sample.dll,<Export>
# Scripts
powershell.exe -ExecutionPolicy Bypass -File sample.ps1
cscript.exe //NoLogo sample.vbs
wscript.exe sample.js
mshta.exe sample.hta

Observe 15 minutes minimum; 60+ if triage found sleep/time checks. Interact where the sample expects it (click the decoy, dismiss dialogs). Note the wall-clock time of execution — it anchors every timeline.

Watch for: new processes, network attempts (INetSim log), files in %TEMP%, %APPDATA%, C:\ProgramData, C:\Users\Public, registry Run keys, new services/tasks, UI changes (ransom note, fake error), CPU spikes.

If nothing happens: see references/anti_analysis_bypass.md (VM checks, sleep patching, required arguments, missing parent process, locale/keyboard checks).

A4. Export evidence — text formats only

Run these before reverting. Every file lands in C:\evidence\ (or /evidence on REMnux) and must be text.

SourceCommand / actionFile
ProcmonFile → Save → All eventsCSV (or procmon.exe /OpenLog cap.pml /SaveAs procmon.csv)procmon.csv
SysmonGet-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'} | Select-Object Id,TimeCreated,Message | ConvertTo-Json -Depth 3 | Out-File -Encoding utf8 C:\evidence\sysmon.jsonsysmon.json
Wireshark → tsharksee block belowdns.txt, http.txt, conns.txt, tls.txt, syn.txt
Wireshark objectsFile → Export Objects → HTTP → save allhttp_objects/
INetSimcopy /var/log/inetsim/service.log and report/inetsim_service.log
System InformerFile → Save → processes.txt; for suspicious process: right-click → Create dump fileprocesses.txt, <proc>.dmp
Memory dump stringsstrings -a -n 8 -e l proc.dmp > proc_strings_wide.txt; strings -a -n 8 proc.dmp > proc_strings.txt (REMnux strings, or FLOSS)*_strings*.txt
Persistenceautorunsc64.exe -accepteula -a * -c -h -s -nobanner | Out-File -Encoding utf8 C:\evidence\autoruns_after.csvautoruns_after.csv
Scheduled tasks / services / WMIPowerShell block belowpersistence.txt
RegshotCompare → output TXTregshot.txt
Dropped filesPowerShell block below; copy the files themselves into dropped/ (they are new samples)dropped_hashes.csv, dropped/
Screenshotsransom notes, dialogs, anything visualscreenshots/*.png

tshark exports (run on REMnux against the saved capture.pcapng, or in the FlareVM Wireshark install dir):

P=capture.pcapng
tshark -r $P -Y "dns.flags.response==0" -T fields -e frame.time -e ip.src -e dns.qry.name > dns.txt
tshark -r $P -Y "http.request" -T fields -e frame.time -e ip.dst -e http.host -e http.request.method -e http.request.uri -e http.user_agent > http.txt
tshark -r $P -Y "tls.handshake.type==1" -T fields -e frame.time -e ip.dst -e tcp.dstport -e tls.handshake.extensions_server_name -e tls.handshake.ja3 > tls.txt
tshark -r $P -q -z conv,tcp -z conv,udp > conns.txt
tshark -r $P -Y "tcp.flags.syn==1 && tcp.flags.ack==0" -T fields -e frame.time_epoch -e ip.dst -e tcp.dstport > syn.txt
tshark -r $P -Y "http.request.method==POST" -T fields -e ip.dst -e http.request.uri -e http.content_length -e http.file_data > http_post.txt

Persistence and dropped files (PowerShell, after execution):

$E = "C:\evidence"
Get-ScheduledTask | ? {$_.TaskPath -notlike "\Microsoft*"} | Select TaskName,TaskPath,State,@{n='Action';e={$_.Actions.Execute + ' ' + $_.Actions.Arguments}} | Format-List | Out-File -Encoding utf8 "$E\persistence.txt"
Get-CimInstance Win32_Service | ? {$_.PathName -notlike "C:\Windows\*"} | Select Name,PathName,StartMode,State | Format-List | Out-File -Encoding utf8 "$E\persistence.txt" -Append
Get-CimInstance -Namespace root\Subscription -Class __FilterToConsumerBinding | Format-List | Out-File -Encoding utf8 "$E\persistence.txt" -Append
foreach ($k in 'HKCU','HKLM') { Get-ItemProperty "${k}:\Software\Microsoft\Windows\CurrentVersion\Run*" | Out-File -Encoding utf8 "$E\persistence.txt" -Append }

$t = (Get-Date).AddMinutes(-90)   # adjust to execution time
mkdir "$E\dropped" -Force | Out-Null
Get-ChildItem -Path $env:TEMP,$env:APPDATA,$env:LOCALAPPDATA,C:\ProgramData,C:\Users\Public,C:\Windows\Temp -Recurse -File -Force -ErrorAction SilentlyContinue |
  ? {$_.CreationTime -gt $t} | % { Copy-Item $_.FullName "$E\dropped\" -Force -ErrorAction SilentlyContinue; $_ } |
  Get-FileHash -Algorithm SHA256 | Export-Csv "$E\dropped_hashes.csv" -NoTypeInformation

Then: transfer C:\evidence\ to the host, revert the snapshot, verify the revert.

Converting Binary Evidence

If the user brings PML / PCAP(NG) / EVTX instead, reply with the conversion command and wait:

GotConvert with
.pmlWindows VM: procmon.exe /OpenLog x.pml /SaveAs x.csv
.pcap / .pcapngThe tshark block in A4 (tshark exists on REMnux and on any host with Wireshark) — you can run this yourself on the host if tshark is installed: command -v tshark
.evtxWindows: Get-WinEvent -Path sysmon.evtx | Select Id,TimeCreated,Message | ConvertTo-Json -Depth 3 | Out-File -Encoding utf8 sysmon.json. Host/REMnux: evtx_dump --format jsonl sysmon.evtx > sysmon.jsonl (pip install evtx) — sysmon_summary.py reads both
.dmpstrings -a -n 8 x.dmp > x_strings.txt; strings -a -n 8 -e l x.dmp > x_strings_wide.txt — run on the host, it is not executable

PCAP and memory dumps are safe to handle on the host; the PE files in dropped/ are new samples and go back through triage.


Part B — Evidence Analysis (you do this)

B0. Inventory

E=/path/to/evidence
ls -la "$E"; file "$E"/* | grep -v ':.*text' ; wc -l "$E"/*.csv "$E"/*.txt "$E"/*.json 2>/dev/null
head -2 "$E/procmon.csv"           # confirm columns: Time of Day, Process Name, PID, Operation, Path, Result, Detail

Anything that is not text → Converting Binary Evidence. Note the sample's process name(s) from triage/state; you will scope everything on them.

B1. Process behavior — Procmon

python3 malware-dynamic-analysis/scripts/procmon_summary.py "$E/procmon.csv" --process sample.exe > "$E/procmon_summary.txt"
wc -l "$E/procmon_summary.txt"; sed -n 1,80p "$E/procmon_summary.txt"

The summary gives: process tree with command lines, files created/written/renamed/deleted, registry writes with persistence keys flagged, network endpoints, DLLs loaded from outside C:\Windows, event counts. Read it fully (page with sed -n). Then drill into specifics straight from the CSV:

# everything one child did
grep -F '"powershell.exe"' "$E/procmon.csv" | cut -d, -f2,4,5 | sort | uniq -c | sort -rn | head -40
# a specific path or key
grep -iF 'CurrentVersion\Run' "$E/procmon.csv" | head
# timeline of process starts (first-seen order)
grep -F '"Process Start"' "$E/procmon.csv" | cut -d, -f1,2,3,7 | head -40

Interpret against the triage predictions: confirmed, refuted, or unexpected. Injection shows up as the sample writing to another process's address space only indirectly in Procmon — cross-check with Sysmon EID 8/10 in B2. Self-deletion (SetDispositionInformationFile on its own path, or cmd /c del), decoy launches, and LOLBin chains (rundll32, regsvr32, mshta, wscript, msiexec, certutil, bitsadmin) are the usual tells.

B2. Process behavior — Sysmon

python3 malware-dynamic-analysis/scripts/sysmon_summary.py "$E/sysmon.json" --process sample.exe > "$E/sysmon_summary.txt"
sed -n 1,120p "$E/sysmon_summary.txt"

Sections and what they prove:

Section (EID)Read it for
Process tree (1)Authoritative parent/child + full command lines + hashes of every executed image
Network (3)Per-process destinations; BEACON-LIKE tag = regular intervals (coefficient of variation < 0.3 over ≥5 connections)
DNS (22)Queried names and resolved IPs, even when the connection failed
Files (11)Dropped files by process — the source of truth for dropped/
Registry (12/13/14)PERSISTENCE flags: Run/RunOnce, Services, Winlogon, IFEO, TaskCache, AppInit
Remote threads (8)CreateRemoteThread injection: source → target, start address
Process access (10)OpenProcess with high rights (0x1F0FFF, 0x1FFFFF, 0x143A) → injection prep, LSASS access → credential theft
Image loads (7)Unsigned DLLs from user-writable paths, sideloading
Pipes (17/18)Named pipes = Cobalt Strike / Meterpreter / custom IPC IOCs
WMI (19/20/21)WMI event subscription persistence
Tampering (25)Process hollowing / herpaderping

Correlate B1 and B2: Procmon has more file/registry granularity, Sysmon has hashes, injection, DNS, and command lines. Where they disagree, trust Sysmon for process identity and Procmon for file operations.

B3. Network

cat "$E/dns.txt" | awk '{print $NF}' | sort | uniq -c | sort -rn | head -30
cat "$E/http.txt" | head -40
cat "$E/tls.txt" | awk -F'\t' '{print $2":"$3, $4, $5}' | sort -u
sed -n 1,60p "$E/conns.txt"
grep -v '^$' "$E/http_post.txt" | head -20
grep -iE 'connect|request|GET|POST' "$E/inetsim_service.log" | head -40

Beacon detection from syn.txt (interval regularity per destination):

python3 - "$E/syn.txt" <<'EOF'
import sys, statistics, collections
by = collections.defaultdict(list)
for line in open(sys.argv[1]):
    p = line.split()
    if len(p) == 3: by[(p[1], p[2])].append(float(p[0]))
for (ip, port), ts in by.items():
    ts.sort(); gaps = [b-a for a, b in zip(ts, ts[1:])]
    if len(gaps) >= 4:
        m = statistics.mean(gaps); cv = statistics.pstdev(gaps)/m if m else 9
        print(f"{ip}:{port}  n={len(ts)}  mean={m:.1f}s  cv={cv:.2f}  {'BEACON' if cv < 0.3 else ''}")
EOF

What to establish: C2 hosts (DNS name → IP → port → protocol), beacon interval and jitter, User-Agent and URI pattern (Suricata material), TLS SNI/JA3, download URLs and what came back (http_objects/file them; PE payloads go back to triage), exfiltration (POST sizes, encoding), DGA signs (many NXDOMAIN, random-looking labels), and whether traffic went to INetSim or the sample gave up (matters for what you can claim).

B4. Persistence and system changes

cat "$E/persistence.txt"
# autoruns diff: entries present after but not before
python3 - "$E/autoruns_before.csv" "$E/autoruns_after.csv" <<'EOF'
import csv, sys
key = lambda r: (r.get('Entry Location',''), r.get('Entry',''), r.get('Image Path',''))
before = {key(r) for r in csv.DictReader(open(sys.argv[1], encoding='utf-8-sig', errors='replace'))}
for r in csv.DictReader(open(sys.argv[2], encoding='utf-8-sig', errors='replace')):
    if key(r) not in before: print(r.get('Entry Location'), '|', r.get('Entry'), '|', r.get('Image Path'), '|', r.get('Signer',''))
EOF
grep -iE 'Run|Services|TaskCache|Winlogon' "$E/regshot.txt" | head -40

Map each mechanism to ATT&CK (T1547.001 Run keys, T1053.005 scheduled task, T1543.003 service, T1546.003 WMI, T1574.002 sideloading, …) — the detection phase needs the technique IDs.

B5. Dropped files and memory strings

cat "$E/dropped_hashes.csv"
file "$E"/dropped/*
python3 scripts/ioc_extract.py "$E"/*_strings*.txt        # C2, keys, paths decrypted only at runtime
grep -iE 'user-agent|/gate|/panel|\.php|password|token|Bearer' "$E"/*_strings*.txt | sort -u | head -40

Every PE in dropped/ is a new sample: add it to analysis_state.md and route back through malware-triage. Runtime strings that were absent from the static strings dump are the decrypted config — call that out explicitly, it is the strongest YARA/Suricata material.

B6. Sandbox reports (if provided)

ANY.RUN / Joe / Hybrid Analysis / Threat.Zone JSON: jq the process tree, network, dropped files, and MITRE sections; treat them as a fourth evidence source and reconcile with B1-B5. Sandbox results are weaker than your own VM run when the sample is VM-aware — say so if behaviors differ.

jq -r '.. | .processes? // empty' report.json | head; jq -r '.. | .network? // empty' report.json | head

B7. Consolidate

cat "$E/procmon_summary.txt" "$E/sysmon_summary.txt" "$E"/dns.txt "$E"/http.txt "$E"/tls.txt "$E"/persistence.txt 2>/dev/null | python3 scripts/ioc_extract.py > "$E/iocs_defanged.txt"

Remove your own lab artifacts (VM hostname, INetSim IPs, analyst username) and Windows-internal noise from the IOC list before recording it.

Output

Append to analysis_state.md under the sample's Analysis Findings and IOCs Identified, then print the findings summary:

## Dynamic Analysis — [sample]   (executed [UTC time], observed [n] min, VM: [FlareVM/REMnux], network: [INetSim/FakeNet/none])

### Execution chain
[process tree with command lines; injection targets; LOLBins; self-deletion]

### Predictions vs observed
| Triage prediction | Observed | Evidence |

### File system
Created / modified / deleted, with hashes for dropped PE files

### Registry & persistence
Mechanism → key/task/service → payload path → ATT&CK ID

### Network
C2: host → IP:port, protocol, beacon interval/jitter, UA, URI pattern, TLS SNI/JA3 · Downloads · Exfil · DGA

### Evasion observed
Sleep, VM checks, debugger checks, tampering (EID 25), what was bypassed and how

### Behavioral IOCs (defanged)
Process (names, cmdlines, mutexes, pipes) · File (paths, hashes) · Registry · Network

### MITRE ATT&CK
Technique IDs with the observation that supports each

### Not observed / limitations
[network to real C2 blocked; sample exited after VM check; only 15 min observed …]

Recommend detection-engineer next (behaviors + network IOCs are ready) unless dropped payloads need triage first.

Quality Gate

Evidence inventoried and all text · process tree with command lines · every prediction marked confirmed/refuted/unexpected · dropped files hashed and routed · persistence mapped to ATT&CK · C2 characterized (or explicitly "no network observed") · IOCs defanged and lab noise removed · limitations stated · state file updated.

References

  • references/tool_setup.md — Procmon filters/columns, Wireshark filters, System Informer, Sysmon install, Regshot, TCPView, Noriben, INetSim, FakeNet-NG
  • references/sandbox_setup.md — REMnux/FlareVM build, isolation, snapshots, CAPE/Cuckoo
  • references/anti_analysis_bypass.md — VM/debugger/sleep evasion and how to defeat it
  • scripts/procmon_summary.py, scripts/sysmon_summary.py — evidence condensers (--self-test to verify)
  • ../scripts/ioc_extract.py — IOC extraction and defanging

Signals

GitHub stars
46
Forks
3
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
malware-dynamic-analysis
Source
github.com/gl0bal01/malware-analysis-claude-skills