Multiarchitecture support and bugfixes - #40
Merged
Conversation
… matrix Extend rop3 beyond x86 to a multi-architecture gadget finder, rework the operation matcher around explicit per-architecture operand roles, and broaden the binary-format coverage. Documentation and the test suite are updated to match. - AArch64 (ARM64) and RISC-V (RV64, including the compressed RVC extension) join x86 and x86-64. Architecture is detected from the binary; RV32 is explicitly rejected. - `rop3/archs/aarch64_arch.py` and `rop3/archs/riscv_arch.py` implement the Architecture ABC (registers, terminations, alignment, written-register derivation). RISC-V derives written registers from the instruction encoding because capstone does not implement `regs_access()` for it. - Framed gadget search (`--frame`/`--no-frame`, on by default): on AArch64 and RISC-V, where the return address lives in a register, only gadgets that restore it from the stack are kept. No effect on x86. JOP gadgets are never gated by framing. Framed architectures scan serially regardless of `--jobs`. - Instruction alignment is architecture-aware (4-byte on AArch64/RISC-V, 2-byte under RVC), and `--depth` now defaults per architecture instead of a fixed 5 bytes. The scan engine lives in `rop3/search.py` (galileo + aligned sweeps). - PE now detects i386, AMD64 and ARM64; Mach-O detects i386, x86_64 and arm64 (thin and fat, with `--arch` selecting a slice); ELF adds AArch64 and RISC-V. - `--verbose` prints a per-binary summary (format, architecture, bit width, instruction alignment and executable sections); exposed on the library as `Rop3.describe()`. - Operations take positional, n-ary operands: `--op mov --operands rdi rax` (op1, op2, op3, ...) and `Rop3.find_op(op, operands=[...])`, replacing the old `--dst`/`--src` pair. - ROPLang definitions (`rop3/roplang/*.yaml`) are per architecture, with explicit `dst`/`src` operand roles and an `available: false` marker for operations an architecture cannot realize (the carry-flag operations `eqc`, `ltc`, `gcf-eqc`, `gcf-ltc` are unavailable on RISC-V). Composite operations chain other operations through `operation:` references. - `rop3/operation.py` is reworked: matching anchors an operation's first instruction after the architecture's frame prologue and allows the remaining instructions to be separated; dst/src register sets are computed from the operation's role metadata; and "contradictory" gadgets (destination overwritten before the terminator) are rejected during the match, with `--keep-contradictory` to disable it. - New flags: `--ret-imm` (include `ret <imm>`/`retf <imm>` terminators, off by default), `--reg-aliases` (let sub-registers stand in for their full register), and `--tuple` output. - New `tests/test_roplang_gadgets.py`: a cross-architecture matrix that checks every ROPLang operation on x86, x86-64, AArch64 and RISC-V. Primitive (single-gadget) operations are matched against a representative gadget; composite operations are checked for availability and realizations; a completeness test guarantees no operation is silently skipped. RISC-V carry operations are asserted unavailable rather than searched. - New per-architecture and per-format suites: `tests/test_aarch64.py`, `tests/test_riscv.py`, `tests/test_pe.py`, `tests/test_info.py`, plus in-memory Mach-O/PE builders in `tests/conftest.py` (no committed binary fixtures). - `tests/test_search.py` covers the extracted scan engine. - Fix-guarding assertions (immediate operands not leaking into src, stores not flagged contradictory, stack-pointer ops not contradictory) are folded into the relevant behavior tests instead of standalone regression cases. - README rewritten: supported architecture/format matrix, framed search, n-ary operands and composite operations, updated option list, library and interactive examples. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Added support for AArch64 and RISC-V architectures. Implemented several improvements in gadget finding and filtering and refactored ropchain.py and gadfinder.py to remove circular dependencies (now ropchain -> gadfinder -> operation.py).
ROPLANG operands are now defined positionally, and operations with multiple sources and/or destinations are correctly tracked.