Commit graph

4 commits

Author SHA1 Message Date
trvon
374aa7475d
many good updates for binary and SAST / DAST scanning 2026-06-02 12:39:03 -04:00
trvon
b18f1890b1
feat: write-what-where /bin/sh planting + conditional gadget handling (Part 3c)
Completes the symbolic gadget solver. When the binary has no "/bin/sh" string,
the planner now plants one via a write-what-where gadget into scratch memory and
points execve's arg0 at it; conditional gadgets are excluded from chains (prefer
unconditional, never assume a branch).

- r2_backend: writableSectionAddr returns a writable (.bss/.data preferred)
  scratch address via iSj.
- rop_chain: synthesizeChain refactored around a reusable `satisfy` register-
  setup helper; for execve with no /bin/sh it finds a mem-write gadget
  (addr=reg, value=reg, ret-terminated; findWriteGadget), sets the address reg to
  scratch and the value reg to the "/bin/sh\0" qword, lands on the write gadget,
  then builds execve with arg0 = scratch. Caveat records the planted string.
- binary_pcode_scan: passes the writable scratch address into the planner.

Conditional gadgets are skipped in pickPopGadget/findWriteGadget (term must be
Ret, not Cond) — safe by construction.

Validated: unit test_rop_chain — write-what-where plants /bin/sh and uses the
write gadget (21 assertions); execve/win/multi-pop cases unchanged. Corpus BOF
parity (3/1/1); meson test 78/78. Part 3 (3a effects + 3b planner + 3c
write-what-where) complete.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 11:46:42 -04:00
trvon
68ea402a6e
feat: semantics-driven ROP chain planner (Part 3b)
Replace the text-heuristic chain builder with a planner over per-gadget symbolic
effects (3a). Because effects are concrete classifications (stack-slot@offset /
const / reg / sp-relative + sp_delta), the payload layout is deterministic stack
arithmetic — each chain step carries its exact byte offset relative to the
overwritten return address.

- ghidra_lifter: liftRegisterInfo resolves the arch's register file by name from
  the SLEIGH spec (getAllRegisters) — used to build the gadget RegModel
  arch-correctly (no hardcoded offsets).
- r2_backend: extractRopGadgets returns each gadget's byte length and (opt-in)
  its bytes, so gadgets can be re-lifted; RopGadgetRaw struct.
- binary_pcode_scan: discoverGadgetEffects lifts each gadget (liftRaw) and runs
  analyzeGadgetEffect; buildRegModel maps SLEIGH names → the solver model;
  attachExploitPrimitives now feeds effects + win targets + /bin/sh to the planner.
- rop_chain: synthesizeChain consumes GadgetEffects — greedily satisfies each
  goal register with a ret-terminated pop gadget (multi-pop gadgets fill several
  at once; clobber-aware), threads sp_delta to place values at exact payload
  offsets, and lands on a win function or syscall gadget. Auto target (win else
  execve). Conditional gadgets are excluded (prefer unconditional); ChainStep
  gains stack_offset, serialized in JSON (round-trip) + SARIF.

Validated: libbof_overflow chain is solver-produced (target + offsets); unit
test_rop_chain — win+arg, execve with 4 pops + syscall at correct offsets,
multi-pop coverage, no-target → none (17 assertions); test_gadget_semantics
(22). Corpus BOF parity (3/1/1); meson test 78/78.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 11:41:07 -04:00
trvon
2ffa58c50f
feat: ROP chain synthesis attached to binary buffer-overflow findings (Part B)
Turn a detected overflow + gadget inventory into a candidate ROP chain
scaffold (auto target) attached to the finding.

- rop_chain (pure, fold::binary, unit-tested): synthesizeChain auto-selects a
  target — a recovered "win" function (system/execve/puts/printf), else an
  execve("/bin/sh") syscall chain assembled from syscall + register-control
  gadgets (x0/x1/x2/x8 on AArch64, rdi/rsi/rdx/rax on x86-64). Emits ordered
  pad/gadget/value/target steps + explicit caveats (PIE/ASLR base, canary, and
  that padding_len is the buffer capacity — the exact saved-return-address
  offset is target-frame-dependent and must be verified).
- ghidra_lifter: expose each pointer arg's recovered stack-frame offset
  (in_buffer_offsets) alongside its size; signed-offset helper. (Exact RA-slot
  recovery is left for future work — the saved return address for these
  overflows lives in the caller's frame, which a single-function lift can't see;
  honest caveats cover this rather than emit a wrong padding.)
- r2_backend: findStringAddress ("/bin/sh" via r2 /j) to seed execve chains.
- report: ExploitContext gains an optional RopChainInfo (padding_len, target,
  steps, caveats); serialized in JSON (write + read round-trip) and SARIF.
- binary_pcode_scan: attachExploitPrimitives now also synthesizes a chain per
  buffer-overflow finding from the gadget inventory + recovered capacity.

Validated: baby_bof's decode_base64 overflow carries a chain (target win:printf,
padding 256, steps + caveats). Unit: test_rop_chain (17 assertions). Corpus BOF
counts unchanged; meson test 77/77.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 09:34:37 -04:00