63 lines
5.0 KiB
Markdown
63 lines
5.0 KiB
Markdown
# Example: autonomous triage run
|
||
|
||
This is a **real, unedited** triage produced by Claude Code running the
|
||
`malware-triage` skill headless against the benign test fixture
|
||
(`tests/make_pe.py` — a PE that only calls `ExitProcess(0)` but imports
|
||
injection/network/persistence APIs and embeds C2-like strings to exercise
|
||
every heuristic).
|
||
|
||
Reproduce it:
|
||
|
||
```bash
|
||
python3 tests/make_pe.py tests/out/invoice_2024.exe
|
||
claude -p "Read malware-triage/SKILL.md and follow it to triage \
|
||
tests/out/invoice_2024.exe. Do not execute the sample." \
|
||
--dangerously-skip-permissions
|
||
```
|
||
|
||
With no further prompting Claude ran `file`, the hash calculator, `pe_info.py`,
|
||
`strings` (ASCII + UTF-16), and `ioc_extract.py`; hand-decoded the 16-byte
|
||
`.text` section; recognised from full code coverage that the binary only exits;
|
||
and returned the verdict below — correctly **benign**, while noting the static
|
||
surface mimics a dropper. Model: claude-fable-5-1. Cost: $1.39.
|
||
|
||
---
|
||
|
||
## Triage Report — invoice_2024.exe
|
||
|
||
**Hashes:** MD5 `a7552cd2ee8036124191ce165e34f0ab` / SHA1 `56125768236e57cc5587e5d52d85deb73fc64401` / SHA256 `af747150f9afc0937a6b62755f9bd84cfb88726370f6007ac03f8f7504d38c4d` **Size:** 3602 bytes **Type:** PE32 x86 console EXE, 3 sections, not .NET **Packed:** No
|
||
**Reputation:** not checked. No VirusTotal / MalwareBazaar MCP in session. Look up SHA256 above; fixture hash likely has no record.
|
||
|
||
### Static Findings
|
||
- **Compile / linker / signature / PDB:** timestamp `2024-01-01T00:00:00Z` (round, synthetic). Linker 14.0, no Rich header. Unsigned. PDB path present only as loose string, not in debug directory: `D:\build\fixture\Release\invoice.pdb`.
|
||
- **Sections:** `.text` 16 bytes, entropy 0.24, holds entry point. `.rdata` 933 bytes (4.46). `.data` 83 bytes (0.35). No packing indicators.
|
||
- **Code:** entire `.text` = `6a 00 ff 15 74 20 40 00` + `int3` padding. Decodes to `push 0; call [0x402074]` = `ExitProcess(0)`. No branch, no loop, no other call. Every other import unreachable.
|
||
- **Imports (13, all decoy except ExitProcess):** injection → VirtualAllocEx, WriteProcessMemory, CreateRemoteThread, OpenProcess. network → InternetOpenA, InternetOpenUrlA, InternetReadFile. persistence → RegCreateKeyExA, RegSetValueExA. execution → CreateProcessA, GetTempPathA. anti-debug → IsDebuggerPresent.
|
||
- **Strings (34 total, both encodings):** C2 URL, IE6 UA string, Run key + value `WinUpdate`, drop path `C:\Users\Public\svc.exe`, mutex, named pipe, UTF-16 self-delete `cmd.exe /c ping -n 3 127.0.0.1 & del "%s"`, `config-placeholder`, and literal `BENIGN TEST FIXTURE - this program only calls ExitProcess(0)`.
|
||
- **Resources / overlay / TLS:** no resources, no TLS. Overlay 530 bytes at `0xc00`: header `OVERLAY-TEST-DATA:` then bytes 0x00–0xff twice. Entropy 7.98 is byte counter, not crypto.
|
||
- **Absent:** no Rich header, no version info, no real config blob. `ioc_extract` "domain" hit `invoice[.]pdb` is false positive (PDB filename).
|
||
|
||
### Classification
|
||
**Verdict:** Benign **Type:** Synthetic test fixture / decoy binary, static surface mimics dropper-trojan **Threat:** Low **Sophistication:** Simple
|
||
**Capabilities:** none executed. Only `ExitProcess(0)`.
|
||
**Reasoning:** Benign needs positive evidence. Here: full code coverage (16 bytes) shows single call to ExitProcess. Network artefacts on reserved test ranges (`example.test`, `203.0.113.5` TEST-NET-3). Build dir named `fixture`, mutex/pipe/UA all named "test". Explicit fixture banner string. Imports and strings would trip every heuristic scanner; that is the fixture's point.
|
||
|
||
### Predicted Behavior
|
||
- **Process:** starts, exits code 0 immediately. Evidence: entry point code. No child process, no injection (CreateProcessA / CreateRemoteThread imported, never called).
|
||
- **Files:** none. Drop path `C:\Users\Public\svc.exe` string-only.
|
||
- **Registry:** none. Run key string-only.
|
||
- **Network:** none. WinINet imports and `gate.php` URL string-only.
|
||
- **Persistence:** none.
|
||
- **Evasion:** none. IsDebuggerPresent never called.
|
||
|
||
### Initial IOCs (defanged)
|
||
File: hashes above · imphash `dfcaebd44ff7676285215e9d856415f3` · PDB `D:\build\fixture\Release\invoice.pdb`
|
||
Network: `hxxp://update-cdn[.]example[.]test/gate[.]php` · `203[.]0[.]113[.]5` · UA `Mozilla/4.0 (compatible; MSIE 6.0; TestUA/1.0)`
|
||
Host: `HKCU\Software\Microsoft\Windows\CurrentVersion\Run` → `WinUpdate` · `C:\Users\Public\svc.exe` · mutex `Global\TestFixtureMutex_9f2a` · pipe `\\.\pipe\testfixture` · `cmd.exe /c ping -n 3 127.0.0.1 & del "%s"`
|
||
All string-only; none exercised by code. Do not push to blocklists.
|
||
|
||
### Recommendation
|
||
**Priority:** Low **Next phase:** Close as Benign. No dynamic analysis; nothing to observe past instant exit. **Why:** complete code coverage, self-declared fixture, reserved test infrastructure. Useful as false-positive fixture for `detection-engineer` rule tests if wanted.
|
||
|
||
State appended to `analysis_state.md` in repo root. Work dir `tests/out/triage_invoice_2024.exe/` holds strings, carved overlay.
|