This release is a pre-release and may not be stable for production use.
r2morph
Metamorphic mutation engine with structured validation and reporting
Overview
r2morph is a metamorphic mutation engine that applies tracked binary transformations with validation, rollback, and machine-readable reports. The 0.4.0-alpha.3 support contract is intentionally narrow: Linux ELF x86-64 is the official target. Other formats and architectures remain preview or experimental.
Key Features
| Feature | Description |
|---|---|
| Tier 1 Passes | NOP, instruction substitution, and register substitution on the official target |
| Declared Support | Linux ELF x86-64; preview and experimental targets are tracked separately |
| 4 Validation Modes | Structural, runtime, symbolic (angr), CFG integrity |
| Session Management | Checkpoint/rollback system preserving binary state across mutation passes |
| SARIF 2.1.0 Reports | OASIS SARIF with MITRE ATT&CK taxonomy, fingerprints, code flows |
| JSON Reports | Documented schema, metadata, timing, gate evaluation |
| Detection Suite | Packer signatures, entropy analysis, pattern matching, similarity hashing |
| Devirtualization | VM handler analysis, MBA simplification (Z3-based) |
Installation
Prerequisites
- Python 3.12 or 3.13
- radare2 installed
Install radare2
git clone https://github.com/radareorg/radare2
cd radare2
sys/install.sh
Install r2morph
pip install r2morph # Basic
pip install "r2morph[enhanced]" # + angr, lief, z3
pip install "r2morph[all]" # + frida, hypothesis
Development Install
git clone https://github.com/seifreed/r2morph.git
cd r2morph
python -m pip install --editable ".[dev]"
The CI dependency manifest remains available for reproducing the extended
analysis environment: python -m pip install -r requirements.txt followed by
python -m pip install --editable ..
Support Matrix
Formats
| Format | Status | Notes |
|---|---|---|
| ELF | Official: Linux x86-64 | Other ELF architectures are experimental |
| PE | Preview/alpha | No zero-defect guarantee |
| Mach-O | Experimental | No zero-defect guarantee |
Architectures
| Architecture | NOP | Substitute | Register | Expand | Block | Dead Code |
|---|---|---|---|---|---|---|
| x86_64 Linux ELF | Tier 1 | Tier 1 | Tier 1 | Experimental | Experimental | Experimental |
| x86 | Experimental | Experimental | Experimental | Experimental | Experimental | Experimental |
| AArch64/ARM | Experimental | Experimental | Experimental | Experimental | Experimental | Experimental |
The machine-readable contract is docs/support-matrix.json.
The reproducible GCC/Clang corpus and its build manifest live in the public
r2morph-corpus repository.
Instruction Equivalence Rules
- x86/x86_64: 100+ rules in
x86_rules.yaml- bidirectional groups covering zero registers, self-moves, flag-preserving patterns, XOR/SUB equivalence - ARM32: 10+ groups in
arm_rules.yaml- zero, increment, decrement, self-move, shift, negate, double, compare for r0-r11 - ARM64: Register classes defined in
arm64_rules.yaml
Mutation Passes
Stable (tested, production-ready)
| Pass | CLI Flag | Description |
|---|---|---|
| NOP Insertion | -m nop |
Inserts benign NOP equivalents at safe locations |
| Instruction Substitution | -m substitute |
Replaces instructions with semantically equivalent alternatives |
| Register Substitution | -m register |
Substitutes registers via liveness analysis |
Experimental (working, limited testing)
| Pass | CLI Flag | Description |
|---|---|---|
| Instruction Expansion | -m expand |
Expands single instructions into longer equivalent sequences |
| Block Reordering | -m block |
Reorders basic blocks with jump patching |
| Dead Code Injection | -m dead-code |
Injects semantically neutral code in padding regions |
| Control Flow Flattening | -m cff |
Inserts opaque predicates and jump obfuscation |
| Opaque Predicates | -m opaque |
Writes opaque predicate instructions into basic blocks |
| Code Virtualization | -m code-virtualization |
Translates instructions to VM bytecode with dispatcher |
| Anti-Disassembly | -m anti-disassembly |
Injects anti-disassembly snippets |
| Data Flow Mutation | -m data-flow |
Data flow analysis-driven safe substitutions |
| Short Jump Patching | -m short-jump |
Patches short jumps to equivalent sequences |
| Constant Unfolding | -m constant-unfolding |
Unfolds constant expressions into multi-instruction equivalents |
| Code Mobility | -m code-mobility |
Relocates blocks to code caves with trampolines |
| Function Outlining | -m function-outlining |
Distributes function chunks across code caves |
| API Hashing | -m api-hashing |
Hash trampolines obscuring PLT references |
| Import Obfuscation | -m import-obfuscation |
Jump stub indirection for import calls |
| Self-Modifying Code | -m self-modifying |
XOR-encrypts function bodies with runtime decryptor |
Validation
| Mode | Flag | Status | Description |
|---|---|---|---|
| Structural | --validation-mode structural |
Stable | Binary format integrity checks (always runs) |
| Runtime | --validation-mode runtime |
Stable | Compares original vs mutated execution (exit code, stdout, stderr, files) |
| Symbolic | --validation-mode symbolic |
Experimental | Bounded symbolic step via angr (ELF x86_64, advisory) |
| CFG Integrity | Automatic | Experimental | Reachability and edge preservation checks |
Quick Start
# Mutate with stable passes
r2morph mutate input.elf -o output.elf -m nop -m substitute -m register
# SARIF report for CI/CD
r2morph mutate input.elf -o output.elf --format sarif --report mutations.sarif
# Reproducible run
r2morph mutate input.elf -o output.elf --seed 1337
# Runtime validation
r2morph validate original.elf mutated.elf --corpus fixtures/dataset/runtime_corpus.json
# CI gate: fail if severity below threshold
r2morph mutate input.elf -o output.elf --report report.json --min-severity bounded-only
# Display and filter reports
r2morph report report.json --only-pass nop --summary-only
r2morph report report.json --format sarif -o report.sarif
CLI Reference
Commands
| Command | Description |
|---|---|
r2morph mutate |
Apply mutations, validate, export binary + report |
r2morph validate |
Compare original vs mutated binary behavior |
r2morph report |
Display, filter, or convert a saved report |
r2morph analyze |
Analyze binary structure and functions |
r2morph functions |
List functions in a binary |
r2morph version |
Show version |
Report Filters
| Filter | Purpose |
|---|---|
--format <json|sarif> |
Output format (JSON default, SARIF 2.1.0) |
--only-pass <name> |
Restrict to one mutation pass |
--only-mismatches |
Show only symbolic observable mismatches |
--only-failed-gates |
Show only failed severity gates |
--only-degraded |
Show only degraded validation modes |
--summary-only |
Print textual triage summary only |
--output <file> |
Export filtered JSON |
--require-results |
Exit 1 when filtered view is empty |
--min-severity <sev> |
Require minimum severity in view |
SARIF 2.1.0 Integration
Reports in SARIF format include:
- MITRE ATT&CK taxonomy - T1027 (Obfuscated Files), T1027.001 (Binary Padding), T1027.002 (Software Packing)
- Partial fingerprints (SHA256) for deduplication across CI runs
- Code flows showing mutation chains per function
- Related locations linking mutations to validation failures
- Disassembly snippets in the rendered field alongside hex bytes
- Fix suggestions with byte-level replacements
Compatible with GitHub Code Scanning, Azure DevOps, SonarQube, and any SARIF 2.1.0 consumer.
Python API
from r2morph import MorphEngine
from r2morph.mutations import NopInsertionPass, InstructionSubstitutionPass, RegisterSubstitutionPass
with MorphEngine() as engine:
engine.load_binary("input.elf").analyze()
engine.add_mutation(NopInsertionPass())
engine.add_mutation(InstructionSubstitutionPass())
engine.add_mutation(RegisterSubstitutionPass())
result = engine.run(validation_mode="structural", report_path="report.json")
engine.save("output.elf")
print(f"Applied {result['total_mutations']} mutations")
Detection & Analysis
| Module | Capability |
|---|---|
| Obfuscation Detector | Commercial packer signatures (VMProtect, Themida, UPX, etc.), confidence scoring |
| Entropy Analyzer | Section entropy analysis for packing/encryption detection |
| Pattern Matcher | Anti-debug, anti-VM, string encryption, import hiding detection |
| Similarity Hasher | Fuzzy hashing for binary comparison (ssdeep-style) |
| Control Flow Detector | CFF, opaque predicates, VM dispatch, MBA expression detection |
| Packer Signatures | 50+ categorized signature database |
Devirtualization (Experimental)
| Module | Status | Notes |
|---|---|---|
| VM Handler Analyzer | Working | Pattern-based handler classification |
| MBA Solver | Working | Z3 SMT solver, max 8 variables, timeout-bounded |
| CFO Simplifier | Framework | Pattern library defined, application incomplete |
| Binary Rewriter | Framework | Patch/relocation infrastructure |
Instrumentation (Experimental)
Frida integration for dynamic analysis: process spawning, script injection, API call logging, anti-analysis detection. Requires frida package.
Report Schema
JSON reports follow a documented schema at r2morph/reporting/report_schema.json. Each report includes:
- metadata: tool version, timestamp, duration, platform
- input/output: binary path, architecture, format, function count
- passes: per-pass mutation counts, timing, diff summaries
- mutations: flat list with address, bytes, disassembly, function, section
- validation: mode, results, symbolic coverage
- gate_evaluation: severity gate outcomes for CI
- summary: aggregated statistics
Requirements
- Python 3.10+
- radare2
- Optional:
lief(PE/Mach-O/section creation),angr(symbolic validation),frida(instrumentation),z3-solver(MBA simplification)
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Support the Project
If you find r2morph useful, consider supporting its development:
License
This project is licensed under the MIT License - see the LICENSE file for details.
Attribution Required:
- Author: Marc Rivero | @seifreed
- Repository: github.com/seifreed/r2morph
Made with dedication for the reverse engineering community
Metadata
Release files for r2morph 0.4.0a3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| r2morph-0.4.0a3.tar.gz | 775.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| r2morph-0.4.0a3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.8 MB
Release files / r2morph-0.4.0a3.tar.gz
| Download URL | r2morph-0.4.0a3.tar.gz |
|---|---|
| Size | 775.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b1b3c533734e2df275cc4bdd69df3939ff6c8f670c1f9f655e232aef2849ca6e
|
|
BLAKE2b-256 checksum How to use checksums |
79405c97ee26f288bcee02eb6a88adebbf89ade93b09b1af3b74d0a92c1e9466
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / r2morph-0.4.0a3-py3-none-any.whl
| Download URL | r2morph-0.4.0a3-py3-none-any.whl |
|---|---|
| Size | 1.0 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
82bb452f848968e1f0cb37b5eedba0ca480b21185097bbe2e868a090301377b6
|
|
BLAKE2b-256 checksum How to use checksums |
3a49ffe16ecbc820116ef4e2091cc0e1b21f5c6ef428a4725fd6867ca4f9ecbd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency log