Skip to content

feat: upgrade to v0.5 - introduce x64 architecture support, type annotations, and robust NOP generation - #21

Open
anonymouschichvy wants to merge 18 commits into
a0rtega:masterfrom
anonymouschichvy:master
Open

feat: upgrade to v0.5 - introduce x64 architecture support, type annotations, and robust NOP generation#21
anonymouschichvy wants to merge 18 commits into
a0rtega:masterfrom
anonymouschichvy:master

Conversation

@anonymouschichvy

Copy link
Copy Markdown

Description

Overview

This pull request upgrades the metamorphic engine to version 0.5. The codebase has been extensively refactored to support both 32-bit (x86) and 64-bit (x64) executables with type-safe handlers, modernized packaging, safer inputs/parsing, and significantly improved NOP generation mechanics. In addition, the documentation has been updated with detailed instructions and a detection comparison catalog.


🛠️ Key Changes

1. Handler Redesign & Static Typing

  • New 64-Bit & 32-Bit Instruction Handler: Replaced the legacy x86handler.py with x64handler.py.
  • Type Annotations: Added comprehensive type annotations (typing.Dict, List, Tuple, etc.) to the X64Handler class.
  • Modernized Syntax: Converted legacy % string formatting to modern Python f-strings.
  • Opcode Normalization: Added normalize_opcode to parse and standardize whitespaces, commas, and casing variations in disassembler outputs.

2. Advanced & Safe NOP Generation

  • Address-Aware Relocation: Changed X64Handler.get_nops signature from (self, size, prev_ins_size=0) to (self, size: int, addr: int = 0) to support absolute instruction addresses, ensuring jumps are resolved correctly at patch time.
  • Multi-Byte Long NOPs: Implemented multi-byte NOP instructions (e.g., nop dword ptr [rax] for 64-bit, nop dword ptr [eax] for 32-bit) which perform no operation and guarantee EFLAGS/RFLAGS stability.
  • Instruction Substitution Variety: Added new size-constrained templates like xchg ax, ax, xor reg, 0; nop, and add reg, 0 to increase metamorphic entropy without affecting register states.

3. Radare2 Parser & CLI Enhancements

  • Safe Metadata Queries: Refactored r2parser.py to parse binary JSON metadata safely using .get() rather than unsafe direct lookups, raising descriptive exceptions if architecture or bit details are missing.
  • Error Logging: Wrapped function disassembly calls in try-except blocks to prevent parser crashes on corrupted functions while reporting details.
  • Early Fail Validation: Updated init.py to verify if the input binary path exists using os.path.exists() before launching radare2.

4. Packaging & Documentation Overhaul

  • Version Bump: Bumped version to 0.5 and moved from deprecated distutils to setuptools in setup.py.
  • New Documentation: Created a highly detailed README.md that outlines the metamorphic mechanisms, a complete catalog of supported mutation patterns and NOP sequences, and a VirusTotal detection comparison.
  • Asset Clean-up: Reorganized screenshots from screens/ into a structured /docs directory.

🧪 Verification Plan

Automated Verification

  • Verify package installation and CLI entrypoint setup using pip install -e ..
  • Run metame on 32-bit and 64-bit ELF/PE binaries to ensure successful mutation patches.

Manual Verification

  • Test input path validation by running metame -i non_existent.exe -o output.exe and verifying that the [ERROR] Input file does not exist message is displayed cleanly.
  • Verify that disassembled outputs and multi-byte NOPs are properly generated by examining the modified binaries in a debugger/disassembler.

Introduce metame/x64handler.py implementing a new X64Handler using Keystone with dynamic NOP generation and optimized mnemonic-indexed substitution rules. Update metame/r2parser.py to import and instantiate X64Handler (and improve disassembly error logging), add README notes about the x64 engine and its O(1) mnemonic indexing and dynamic NOP replacement, and delete the legacy metame/x86handler.py. The new handler preserves the replace_fcn_opcodes/assemble_code API and adds runtime NOP placeholder resolution and more robust matching/assembly checks.
Add input file existence check in CLI. Make R2Parser resilient to missing or incomplete 'bin' metadata, surface clearer errors, and read arch/bits safely before validating supported architectures/bits. Improve X64Handler robustness: add normalize_opcode, perform case-insensitive regex matching, normalize opcodes before matching, lowercase captured groups when substituting, shuffle candidate replacements and retry assembly while checking assembled size, and add clearer debug output on failures. Include new unit tests (tests/test_x64handler.py) to exercise initialization, get_nops, normalize_opcode and replace_fcn_opcodes behavior for 32/64-bit handlers.
Extend X64Handler with additional mutation variants and control-flow aliases. Added new random nop/arith substitutions (inc/dec, add/sub with zero/or/xor no-ops), shl/add expansions, and je/jz / jne/jnz swap rules; expanded the mutable mnemonic set for both 32/64-bit modes. assemble_code now accepts an optional addr and passes it to Keystone, and replace_fcn_opcodes uses the operation offset when assembling to preserve correct addresses. Adjusted random-choice branches and size-specific operand sequences to increase mutation diversity. Added test_replace_fcn_opcodes_advanced to verify replacements and size conservation.
Replace prev_ins_size with an explicit addr parameter for get_nops and update NOP generation to favor flag/register-safe multi-byte NOPs and size-preserving patterns. Changes include: using relative jmp targets computed from addr, adding safe NOPs (e.g. xchg ax, ax and nop dword ptr ...), correcting random branch ranges and reg usage, and threading addr into recursive get_nops calls and the nop placeholder resolver. README and tests updated to document and validate the new safe NOP choices and behavior.
metame/x64handler.py: Accept both 'offset' and 'addr' keys by introducing op_offset = op.get('offset', op.get('addr')) and use it when resolving NOP placeholders, assembling code, and recording replacements. Add a traceback print when Keystone assembly fails and debug is enabled to aid troubleshooting.
Revise README to reflect Version 0.5: add centered logo, simplify and reformat the features/comparison section, update the mermaid flowchart, and replace mutation examples with before/after signature analysis and a detection comparison table. Add new image assets under docs/ (logo.png, screen_bef.png, screen_aft.png, Screenshot 2026-07-03 221657.png) and remove legacy screenshots from screens/ (screen1.png, screen2.png).
Replace absolute local file URLs in README with repository-relative paths and update the LICENSE link. Remove a redundant Usage subsection and add a new "Metamorphic Transformation Process" section with explanatory text and an embedded image. Rename the screenshot to docs/metame-process.png for clarity and to match the new reference.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant