Binary RE toolkit for stripped firmware. No symbols. No source.
Version: 2.57.0 — pip install -e ~/ablation/ (editable install, already done)
GitHub: Ablation-Tool/ablation — all repo ops via gh CLI. mcp__github is BANNED.
ablation/
core/ # parsers + platform detection (not for direct use)
analyzers/ # all analysis tools — the RE surface
profiles/ # vendor-specific YAML sinks/safe patterns
sweeps/ # standalone sweep scripts
re/ # LOCAL ONLY — per-target findings + session state
docs/ # module reference + tool selection guide
tests/
Read SESSION.md (root) before any work. Per-target state: re/<vendor>/SESSION_<target>.md.
from ablation.analyzers.binary_context import BinaryContext
ctx = BinaryContext.load_or_build('/path/to/target.so')
print(ctx.summary())
if ctx.names_count():
print(ctx.names_table())
# ctx.name(va) everywhere. ctx.set_name(0xVA, "name", source="confirmed")See docs/guide-tool-selection.md for the full task→tool lookup table.
Ordering: BinaryContext → SemanticSearcher (new binary/vuln class) → FuncProfiler (candidate) → SinkArgClassifier (eliminate RODATA_CONST first) → TaintTracker (ARG_PROPAGATED/UNKNOWN sinks only) → PathSolver (confirm feasibility). Manual capstone only when TaintTracker has no configured sink.
See docs/reference-modules/ for per-module constructor patterns and key methods. Also docs/INDEX.md.
New binary, initial triage:
- Read
SESSION.md(root) +re/<vendor>/SESSION_<target>.md BinaryContext.load_or_build()+ctx.summary()+ctx.names_table()CorpusBuilder.build()if no prior coverageSemanticSearcher.query(): sweep ALL vuln classes before touching disasmPatternLibrary.sweep(): replay confirmed patterns from prior engagementsFuncProfiler.profile()on top candidates 6.5.SinkArgClassifier.from_path(elf).classify_all(): classify ALL shell sink call sites as RODATA_CONST / SNPRINTF_RODATA / ARG_PROPAGATED / UNKNOWN — eliminate RODATA_CONST and parameterless SNPRINTF_RODATA before TaintTracker runsTaintTrackeron ARG_PROPAGATED / UNKNOWN sinks only (not RODATA_CONST)IPRegAnnotatorfor cross-library call chainsWindowAnalyzer.dump_text()for manual disasm only when automated tools don't have the sink
Confirming a finding:
- Byte-verify every VA.
data = open(binary,'rb').read(); off = va - base; assert data[off:off+n] == expected_bytes. No exceptions. C16 was carried as CONFIRMED HIGH for six sessions on pattern-match alone — the bytes were wrong. PathSolver.solve_path()for feasibilityctx.set_name(va, name, source="confirmed")PatternLibrary.record_hit(confirmed=True)FindingRegistry.register()- Write finding to
re/<vendor>/<target>_re.py(NOT into ablation itself) - Update
re/<vendor>/SESSION_<target>.md
Custom scanner workflow:
- Confirm SemanticSearcher has no existing pattern (run a query first)
- Create
ablation/analyzers/<scanner_name>.py; followlength_underflow.pyas template - Wire:
from_context(ctx)classmethod,scan()→ findings list,report(findings)→ str - Run on a known-positive binary first; analyze FPs (cross-BB clobber? trusted source? callee reads register?)
- Add to
docs/guide-tool-selection.md - Write
docs/reference-modules/<module>.md— open with "Why this exists" as numbered gaps
Cross-version patch analysis:
DTWMatcher.score_functions(): same era?MatrixProfileDiff.diff_functions(): what changed?VersionTracker.find_homolog(): where did it move?
- GitHub: active account is
Ablation-Tool. ALL repo ops viaghCLI.mcp__githubis BANNED. - Push: after every commit:
env HOME=/home/cowboy GIT_LFS_SKIP_SMUDGE=1 git push origin main - Edits: main session only. Never fork or delegate ablation work.
- Repo integrity:
~/ablation/is never deleted, moved, or destructively modified. - No findings in repo: reports, disclosures, and write-ups never go into the ablation repo.
- No Ghidra: ever.
- Semantic sweep first: before ANY manual disasm on a new binary or new vuln class.
- Gaps become modules: every missing sink, scanner pattern, or analysis gap → new ablation module. Never a workaround script.
- Findings go in RE modules:
re/<vendor>/<target>_re.py. Nowhere else. NOTmodules/. - Name everything:
ctx.set_name()the moment a function is confirmed.ctx.name(va)everywhere. - Session files: update
re/<vendor>/SESSION_<target>.mdat end of each session. Update rootSESSION.mdif active target changes.