Depth-first RE investigation loop for a single binary or function cluster: decompile→rename→retype→comment→re-read, with context-rot guards and on-task checks. Use when triage has already identified the interesting area and the goal is full understanding: what does function X do, identify cryptographic primitives, locate C2 protocol, recover data structures. Triggers on: 'deep analysis', 'understand function', 'recover struct', 'crypto identification', 'C2 protocol', 'reverse this binary fully', 'what does this function do'.
88%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Depth-first RE for full understanding of a specific target area. Distinct from
breadth-first triage (reverser/triage) — here you don't stop at a signal,
you keep iterating until the function is fully understood.
Triage finds the surface; deep-analysis excavates one shaft. Commit to one question at a time. Context-rot (losing track of what you've already renamed or retyped) is the primary failure mode — guard against it explicitly.
Before decompiling anything, state the question in writing:
kg_add_node("hypothesis", "deep-analysis target",
props={"question": "<exact question, e.g. 'what does sub_401A20 do'>",
"binary": "/workspace/target",
"entry_function": "<hex addr or name>",
"key": "deep-analysis:entry"})Commit to one question. Do not pivot mid-session unless the current function is fully annotated and the answer is "it delegates to X".
For each function under analysis, follow this cycle exactly:
In hosted runs, use ghidra_find_tools(query="decompile") to discover the
native decompiler tool and its argument schema, then pass the imported program
and target function. Do not infer a decompiler call from a local-only example.
Read the full output before touching anything.
As soon as you understand a variable's purpose, rename it. Collect related
renames and use the native rename tool discovered with
ghidra_find_tools(query="rename"); inspect its schema before calling it.
Do not leave a decompiled function with placeholder names (param_1,
local_8, uVar1) if you know what they are.
Correct types catch bugs in decompiler reasoning. Discover the native type
editing operation with ghidra_find_tools(query="type") and use the returned
schema for the active program.
Pay special attention to: size_t vs int (sign confusion), pointer-as-int
patterns, struct pointer vs void*, callback function pointers.
At every branch point whose purpose is now understood, add a comment with the
native annotation tool discovered by ghidra_find_tools(query="comment").
After rename+retype, decompile again. The output will often look dramatically cleaner and reveal previously hidden logic.
Repeat 2a–2e until the function's purpose is unambiguous.
After each batch of tool calls, answer explicitly:
If you've called into a callee 3+ levels deep without updating the KG, that's context-rot — surface the findings upward before going deeper.
kg_add_node("note", "deep-analysis progress",
props={"function": "decrypt_config_blob",
"finding": "RC4 variant — XOR stream cipher, 16-byte key from .rdata:0x40D0C0",
"status": "complete",
"key": "deep-analysis:decrypt_config_blob"})ghidra_get_xrefs_from tool for the imported program; use ghidra_find_tools when another reference view is needed.calls edge chain.High-entropy constants are the fastest path:
# Search for known crypto constants (AES S-box, RC4 init, ChaCha sigma, etc.)
grep -r "0x63636363\|0x6B617479\|0xE2280613\|0xDB3D18\|0x61707865\|0x3320646E" \
/workspace/target.bin 2>/dev/null || true
# Capa identifies crypto more reliably
capa /workspace/target --json > /workspace/capa_crypto.json
cat /workspace/capa_crypto.json | python3 -c "
import json, sys
d = json.load(sys.stdin)
for r in d.get('rules', {}).values():
if 'crypto' in r.get('rule',{}).get('namespace','').lower():
print(r['rule']['name'])
"Constants to recognize:
| Constant | Algorithm |
|---|---|
0x61707865 / expand 32-byte k | ChaCha20 / Salsa20 |
AES S-box start 0x63,0x7c,0x77,0x7b | AES |
0x67452301,0xEFCDAB89 | MD5 init |
0x6A09E667,0xBB67AE85 | SHA-256 init |
0x9E3779B9 | TEA / XTEA Δ |
0xB7E15163,0x9E3779B9 | RC5/RC6 magic |
| Byte-by-byte XOR loop with index-mod key | RC4 or custom XOR |
Once identified, rename the function accordingly and document the key schedule location if observable.
connect, WSAConnect,
send, write, curl_easy_perform..data or .rdata.# Find all large-ish .rdata blobs (>16 bytes, high entropy)
python3 -c "
import pefile, math
pe = pefile.PE('/workspace/target.exe')
for s in pe.sections:
if b'.rdata' in s.Name:
data = s.get_data()
# scan in 16-byte windows
for off in range(0, len(data)-16, 4):
chunk = data[off:off+16]
counts = [chunk.count(bytes([b])) for b in range(256)]
ent = -sum((c/16)*math.log2(c/16) for c in counts if c)
if ent > 7.0:
print(hex(s.VirtualAddress + off), 'entropy', round(ent,2))
" 2>/dev/null | head -20decrypt_c2_config. Document
algorithm + key in KG.When you see pointer arithmetic into a struct you don't have a definition for:
[param_1 + 0x28]).ghidra_find_tools(query="struct"); inspect their schemas.status:blocked
and surface to orchestrator rather than spiraling.The deep-analysis session is done when:
kg_add_node("finding", "deep-analysis complete",
props={"question": "<original question>",
"answer": "<concise answer>",
"key_functions": ["decrypt_config_blob", "build_beacon_packet"],
"crypto": "ChaCha20 — key at .data:0x40E0A0",
"c2_format": "TLV over TCP port 4444",
"key": "deep-analysis:complete"})| Tool | Purpose |
|---|---|
Native Ghidra decompiler tool, discovered with ghidra_find_tools | C pseudocode for a function |
Native rename and type tools, discovered with ghidra_find_tools | Update symbols and type annotations |
ghidra_get_xrefs_to / ghidra_get_xrefs_from | Callers / callees of an address in hosted runs |
Native struct tools, discovered with ghidra_find_tools | Define a data structure |
capa | High-level capability + crypto detection |
pefile / lief | PE/ELF structure access from Python |
PurpleAILAB/Decepticon
49888ee
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.