README.md

March 25, 2026 ยท View on GitHub

r2morph

r2morph

Metamorphic mutation engine with structured validation and reporting

PyPI Version Python Versions License CI Status Coverage

GitHub Stars GitHub Issues Buy Me a Coffee


Overview

r2morph is a metamorphic mutation engine that applies tracked binary transformations with validation, rollback, and machine-readable reports. It uses radare2 for analysis and supports 18 mutation passes across 4 architectures.

Key Features

FeatureDescription
18 Mutation PassesFrom stable NOP/substitute/register to experimental CFF, virtualization, and self-modifying code
4 Architecturesx86_64, x86, ARM64, ARM32
3 Binary FormatsELF (stable), PE and Mach-O (experimental, via LIEF)
4 Validation ModesStructural, runtime, symbolic (angr), CFG integrity
Session ManagementCheckpoint/rollback system preserving binary state across mutation passes
SARIF 2.1.0 ReportsOASIS SARIF with MITRE ATT&CK taxonomy, fingerprints, code flows
JSON ReportsDocumented schema, metadata, timing, gate evaluation
Detection SuitePacker signatures, entropy analysis, pattern matching, similarity hashing
DevirtualizationVM handler analysis, MBA simplification (Z3-based)

Installation

Prerequisites

  • Python 3.10+
  • 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
pip install -e ".[dev]"

Support Matrix

Formats

FormatStatusSection CreationNotes
ELFStableVia LIEFFull section handling, relocations, code caves
PEExperimentalVia LIEFSection creation, checksum fixing
Mach-OExperimentalVia LIEFLoad command parsing, Fat binary support

Architectures

ArchitectureNOPSubstituteRegisterExpandBlockDead Code
x86_64YesYesYesYesYesYes
x86YesYesYesYesYesYes
ARM64YesYesYesYesYesYes
ARM32YesYesYesYesYesYes

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)

PassCLI FlagDescription
NOP Insertion-m nopInserts benign NOP equivalents at safe locations
Instruction Substitution-m substituteReplaces instructions with semantically equivalent alternatives
Register Substitution-m registerSubstitutes registers via liveness analysis

Experimental (working, limited testing)

PassCLI FlagDescription
Instruction Expansion-m expandExpands single instructions into longer equivalent sequences
Block Reordering-m blockReorders basic blocks with jump patching
Dead Code Injection-m dead-codeInjects semantically neutral code in padding regions
Control Flow Flattening-m cffInserts opaque predicates and jump obfuscation
Opaque Predicates-m opaqueWrites opaque predicate instructions into basic blocks
Code Virtualization-m code-virtualizationTranslates instructions to VM bytecode with dispatcher
Anti-Disassembly-m anti-disassemblyInjects anti-disassembly snippets
Data Flow Mutation-m data-flowData flow analysis-driven safe substitutions
Short Jump Patching-m short-jumpPatches short jumps to equivalent sequences
Constant Unfolding-m constant-unfoldingUnfolds constant expressions into multi-instruction equivalents
Code Mobility-m code-mobilityRelocates blocks to code caves with trampolines
Function Outlining-m function-outliningDistributes function chunks across code caves
API Hashing-m api-hashingHash trampolines obscuring PLT references
Import Obfuscation-m import-obfuscationJump stub indirection for import calls
Self-Modifying Code-m self-modifyingXOR-encrypts function bodies with runtime decryptor

Validation

ModeFlagStatusDescription
Structural--validation-mode structuralStableBinary format integrity checks (always runs)
Runtime--validation-mode runtimeStableCompares original vs mutated execution (exit code, stdout, stderr, files)
Symbolic--validation-mode symbolicExperimentalBounded symbolic step via angr (ELF x86_64, advisory)
CFG IntegrityAutomaticExperimentalReachability 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 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

CommandDescription
r2morph mutateApply mutations, validate, export binary + report
r2morph validateCompare original vs mutated binary behavior
r2morph reportDisplay, filter, or convert a saved report
r2morph analyzeAnalyze binary structure and functions
r2morph functionsList functions in a binary
r2morph versionShow version

Report Filters

FilterPurpose
--format <json|sarif>Output format (JSON default, SARIF 2.1.0)
--only-pass <name>Restrict to one mutation pass
--only-mismatchesShow only symbolic observable mismatches
--only-failed-gatesShow only failed severity gates
--only-degradedShow only degraded validation modes
--summary-onlyPrint textual triage summary only
--output <file>Export filtered JSON
--require-resultsExit 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

ModuleCapability
Obfuscation DetectorCommercial packer signatures (VMProtect, Themida, UPX, etc.), confidence scoring
Entropy AnalyzerSection entropy analysis for packing/encryption detection
Pattern MatcherAnti-debug, anti-VM, string encryption, import hiding detection
Similarity HasherFuzzy hashing for binary comparison (ssdeep-style)
Control Flow DetectorCFF, opaque predicates, VM dispatch, MBA expression detection
Packer Signatures50+ categorized signature database

Devirtualization (Experimental)

ModuleStatusNotes
VM Handler AnalyzerWorkingPattern-based handler classification
MBA SolverWorkingZ3 SMT solver, max 8 variables, timeout-bounded
CFO SimplifierFrameworkPattern library defined, application incomplete
Binary RewriterFrameworkPatch/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.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Support the Project

If you find r2morph useful, consider supporting its development:

Buy Me A Coffee

License

This project is licensed under the MIT License - see the LICENSE file for details.

Attribution Required:


Made with dedication for the reverse engineering community