binary-triage
Skill0 starsChanged 3 months agoMITView on GitHub
Use when extracting evidence from closed binaries (DLL/SO/EXE/AAR) without heavy RE tooling - engine version, symbols, getter constants, exports, diff between builds, ctypes runtime probing. Answers in minutes what would take hours in Ghidra; escalate to re-binary/Ghidra only when static triage cannot close the question.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- xiebrooooo/rev-skillstheir own version, first seen Nov 1, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- xiebrooooo/rev-skills★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository110 other files it gives its agents.
- AGENTS.mdAGENTS.md
- skills/project-bootstrap/templates/agents.mdAGENTS.md
- a11y-auditSkill
- agentic-ragSkill
- agent-reachSkill
- ai3d-genSkill
- ai-coding-dictionarySkill
- ai-toolsSkill
- animation-directionSkill
- api-specSkill
- architecture-diagramsSkill
- architectureSkill
- ascii-artSkill
- ask-bundleSkill
- bragSkill
- brag-slimSkill
- career-opsSkill
- code-reviewSkill
- computer-useSkill
- context7Skill
- context-hygieneSkill
- creative-engineeringSkill
- cu-realtimeSkill
- data-analystSkill
- databaseSkill
- dead-wireSkill
- debuggingSkill
- deploySkill
- devin-configSkill
- dispatching-parallel-agentsSkill
- dmaSkill
- dockerSkill
- drift-reportSkill
- e2e-testingSkill
- edge-casesSkill
- executionSkill
- fact-checkSkill
- finishing-a-development-branchSkill
- firmware-probeSkill
- frontend-designSkill
- gatesSkill
- ghidraSkill
- ghSkill
- github-actionsSkill
- git-workflowsSkill
- grillingSkill
- handoffSkill
- humanizerSkill
- hyperframesSkill
- i18nSkill
- image-forensicsSkill
- impeccableSkill
- implement-layaSkill
- intakeSkill
- jiraSkill
- knowledge-modelingSkill
- laya-orchestratorSkill
- learn-modeSkill
- mcp-governanceSkill
- media-toolsSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 4 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 111
Do not open Ghidra before steps 1-4: 80% of "version/format" questions die on strings + exports + getters.
- Distinctive: line 112
Do not conclude "function does not exist" from a missing string in PE (internal symbol stripped).
- Very specific: line 113
Do not trust the package/wrapper version.
- Distinctive: line 114
Do not report "probably incompatible" without a concrete delta and an API-level confirmation test.
- Distinctive: line 115
Do not scan the whole disk hunting RE tools.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Binary Triage
Extract answers from a closed DLL/.so/.aar in minutes with light tools (strings, nm, objdump, python) before paying the cost of Ghidra/IDA. Born from a real case: proving an Android engine was generation 5.3.x incompatible with a 4.8.4.0 server via the internal FIR version.
When to use
- Compare builds/engines of the same lib across platforms or versions ("which DLL is this Android .so equivalent to?").
- Extract an undocumented internal constant (format version, magic, fixed size) without source.
- Confirm whether a function/symbol exists in a binary that stripped exports.
- Evaluate a binary-incompatibility hypothesis (template, protocol, serialized struct) before heavy disassembly.
Tools (cost order)
strings,nm -D,objdump -T(mingw/scoop ships all three under~/scoop/apps/mingw/current/bin/).- Python stdlib to parse ELF/PE and read bytes at offsets (snippets below, tested).
sigcheck(scoop) or PowerShellGet-Item ... .VersionInfofor Windows DLL/EXE FileVersion.- ctypes runtime probing:
Init+GetVersionsometimes answer in 20 lines what takes hours statically. - Heavy RE only when the above does not close it:
re-binaryskill (rea-opswrapper -> Hopper/Ghidra engines) orghidraskill for raw firmware. - .NET managed: dnSpy/ILSpy/dotPeek (the assembly is not native; a native disassembler does not help).
Steps
- Metadata first: FileVersion/ProductVersion of the binary and all "siblings" (other versions, other platforms, inner .aar). In .aar, unzip:
unzip -o lib.aar -d outand inspectjni/<abi>/*.so. The inner .aar/lib name sometimes leaks the real engine version (real case: wrapper "v2.0.0.8" containedsdk-release-5.3.0.7.aar). - Symbol map:
nm -D(ELF) or export table (PE, snippet below). Cross-check sets between builds: identical internal symbol set = same codebase/generation. PE strips internal symbols; NDK ELFs often do not. So "symbol absent in the DLL" proves nothing; "symbol present" proves presence. - Constants via 1-instruction getters: functions like
GetXxxVersionare usuallymov reg, imm; ret. Find the symbol in the .so and disassemble:objdump -d --start-address=<va> --stop-address=<va+16> lib.so- AArch64:
MOVZ w0,#imm=(instr >> 5) & 0xFFFF(e.g.52812000->0x900). - x86-64:
b8 <imm32> c3=mov eax, imm; ret. Scanning the whole PE forb8(....)\xc3finds these getters without symbols (snippet below).
- AArch64:
- vaddr -> file offset: ELF uses program headers, PE uses the section table. Ready snippets below; do not compute by hand.
- Runtime probe when possible: load the DLL with ctypes, call
Init/version function. Failed (VALIDITY_FAIL, AV, license)? Note it and go back to static; do not insist. - Conclude with a delta, not a vibe: report what differs between the binaries (internal version, symbol on only one side, struct size) and the application-level confirmation test (e.g. log the
Versionfield of the API-returned header).
Ready snippets
ELF vaddr->offset + instruction read (python stdlib):
import struct
data = open('lib.so','rb').read()
e_phoff = struct.unpack('<Q', data[0x20:0x28])[0]
e_phentsize, e_phnum = struct.unpack('<HH', data[0x36:0x3a])
segs = []
for i in range(e_phnum):
t,f,off,va,pa,fs,ms,al = struct.unpack('<IIQQQQQQ', data[e_phoff+i*e_phentsize:e_phoff+i*e_phentsize+56])
if t == 1: segs.append((va,off,fs))
def v2o(va):
for v,o,s in segs:
if v <= va < v+s: return o+(va-v)
# symbol addr from: nm -D lib.so | grep Name
# instr = struct.unpack('<I', data[v2o(addr):v2o(addr)+4])[0]PE export table walker (file offset of an exported function):
import struct
data = open('lib.dll','rb').read()
pe = struct.unpack('<I', data[0x3c:0x40])[0]
opt = pe+24
magic = struct.unpack('<H', data[opt:opt+2])[0]
ddir = opt + (112 if magic == 0x20b else 96)
exp_rva = struct.unpack('<I', data[ddir:ddir+4])[0]
nsec = struct.unpack('<H', data[pe+6:pe+8])[0]
sec_off = opt + struct.unpack('<H', data[pe+20:pe+22])[0]
secs = [struct.unpack('<IIII', data[sec_off+i*40+8:sec_off+i*40+24]) for i in range(nsec)]
def r2o(rva):
for vs,va,rs,rp in secs:
if va <= rva < va+vs: return rp+(rva-va)
eo = r2o(exp_rva)
nf, nn = struct.unpack('<II', data[eo+20:eo+28])
af, an, aon = struct.unpack('<III', data[eo+28:eo+40])
for i in range(nn):
no = r2o(struct.unpack('<I', data[r2o(an)+i*4:r2o(an)+i*4+4])[0])
name = data[no:data.find(b'\x00', no)].decode()
ordi = struct.unpack('<H', data[r2o(aon)+i*2:r2o(aon)+i*2+2])[0]
frva = struct.unpack('<I', data[r2o(af)+ordi*4:r2o(af)+ordi*4+4])[0]
print(name, 'fileoff', hex(r2o(frva)))Scanner for mov eax,imm;ret getters across a whole PE:
import re
data = open('lib.dll','rb').read()
for m in re.finditer(rb'\xb8(....)\xc3', data):
v = int.from_bytes(m.group(1), 'little')
print(hex(m.start()), hex(v))
# adjacent pairs of small getters (e.g. 0x100 and 0x10 side by side)
# are typically GetVersion/GetMinVersion of the same familyctypes probing (Windows):
import ctypes, os
os.add_dll_directory(r'C:\dir\with\deps')
d = ctypes.CDLL(r'C:\path\lib.dll') # cdecl; WinDLL if stdcall
h = ctypes.c_ulong(0)
print(d.SomeApi_Init(ctypes.byref(h))) # adapt to the SDK in questionAnti-patterns
- Do not open Ghidra before steps 1-4: 80% of "version/format" questions die on strings + exports + getters.
- Do not conclude "function does not exist" from a missing string in PE (internal symbol stripped); look for code patterns or test at runtime.
- Do not trust the package/wrapper version; the version that matters is the inner engine's (.so/.dll).
- Do not report "probably incompatible" without a concrete delta and an API-level confirmation test.
- Do not scan the whole disk hunting RE tools; use what is on PATH, look for Ghidra once, proceed without it if absent.
Cascade
debugging: binary triage is an investigation step, not the end.re-binary: heavy RE via rea-ops (Hopper/Ghidra engines) under engagement contract.ghidra: raw firmware headless decompilation recipe.security: same tooling audits third-party binaries (supply chain).
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

