Skip to main content
The MemChanger class builds ROP chains that perform arithmetic and logical operations directly on memory locations. It supports add, xor, or, and operations.

Overview

Accessed through the ROP instance as rop.mem_add(), rop.mem_xor(), rop.mem_or(), and rop.mem_and(), MemChanger automatically:
  • Finds gadgets that operate on memory
  • Handles different data sizes (1, 2, 4, 8 bytes)
  • Verifies operations are correct
  • Manages register dependencies

Class Definition

Located in angrop/chain_builder/mem_changer.py

Public Methods

mem_add

Add a value to data at a memory location.
int | RopValue
required
Memory address to modify.
int | RopValue
required
Value to add.
int | None
default:"None"
Number of bytes to operate on (1, 2, 4, or 8). Defaults to architecture word size.
Returns: A RopChain that performs the addition.

mem_xor

XOR data at a memory location with a value.
int | RopValue
required
Memory address to modify.
int | RopValue
required
Value to XOR with.
int | None
default:"None"
Number of bytes (1, 2, 4, or 8).
Returns: A RopChain that performs the XOR.

mem_or

Perform bitwise OR on data at a memory location.
int | RopValue
required
Memory address to modify.
int | RopValue
required
Value to OR with.
int | None
default:"None"
Number of bytes (1, 2, 4, or 8).
Returns: A RopChain that performs the OR.

mem_and

Perform bitwise AND on data at a memory location.
int | RopValue
required
Memory address to modify.
int | RopValue
required
Value to AND with.
int | None
default:"None"
Number of bytes (1, 2, 4, or 8).
Returns: A RopChain that performs the AND.

verify

Verifies that a memory operation chain works correctly.
str
required
Operation name: ‘add’, ‘xor’, ‘or’, or ‘and’.
RopChain
required
Chain to verify.
RopValue
required
Memory address.
RopValue
required
Operation value.
int
required
Data size in bits (8, 16, 32, or 64).
Raises: RopException if verification fails.

ROP Instance Methods

Implementation Details

Memory Change Gadgets

MemChanger requires gadgets with specific properties:
  1. Self-contained: No dependencies on initial state
  2. Single memory change: Only one read-modify-write operation
  3. Independent addr/data: Address and data controlled separately
From source code (mem_changer.py:87-100):

Gadget Examples

Operation Verification

From source code (mem_changer.py:32-71):

Usage Examples

Memory Addition

Memory XOR

Memory OR

Memory AND

Complete Memory Operations Example

Incrementing a Counter

Toggling a Flag

Enabling/Disabling Bits in Bitmask

Badbyte Avoidance

MemChanger is crucial for writing data with badbytes:

Size Specification

All operations support explicit size:
If you don’t specify size, MemChanger uses the architecture’s word size (4 bytes for 32-bit, 8 bytes for 64-bit).

Effect Tuple

MemChanger filters gadgets based on their effect: From source code (mem_changer.py:73-81):
This ensures only unique gadgets are kept.

Operation-Specific Gadget Lists

MemChanger maintains separate lists: From source code (mem_changer.py:25-30):

Error Handling

”Fail to perform _mem_change for operation!”

Raised when no suitable gadgets are found. Solutions:
  1. Use fast_mode=False when initializing ROP
  2. Check if binary has memory change gadgets
  3. Try a different operation (XOR instead of ADD)

” cannot be represented by -byte”

Raised when value is too large for specified size. Solution: Use larger size or split operation:

“does not support finding raw chain that bytes”

Raised when size is invalid. Solution: Use valid sizes: 1, 2, 4, or 8 bytes.

Gadget Requirements

For memory changes to work:
  1. Read-modify-write: Gadget must read, modify, then write
  2. Controllable address: Can set address register
  3. Controllable data: Can set data/operand register
  4. Independence: Address and data registers are different
  5. Self-contained: No special initial state required
Example gadget analysis:

Deprecated Method

add_to_mem

This method is deprecated. Use mem_add() instead.
From source code (mem_changer.py:217-219):

Performance Considerations

  • Gadgets are sorted by data_size (larger first) for efficiency
  • Verification adds overhead but ensures correctness
  • Multiple operations can be chained efficiently
  • Size should match actual data requirements

Architecture Support

Works across all supported architectures:
  • x86/x86_64: Full support
  • ARM/ARM64: Full support
  • MIPS: Full support
  • PowerPC: Full support

See Also