Skip to main content
The MemWriter class builds ROP chains that write arbitrary data to memory addresses. It handles badbytes, chunk optimization, and uses memory arithmetic operations when needed.

Overview

Accessed through the ROP instance as rop.write_to_mem(), MemWriter automatically:
  • Finds optimal memory write gadgets
  • Handles data with badbytes using arithmetic transformations
  • Writes data in efficient chunks (1, 2, 4, or 8 bytes)
  • Manages address and data register dependencies

Class Definition

Located in angrop/chain_builder/mem_writer.py

Public Method

write_to_mem

Builds a ROP chain that writes data to a memory address.
int | RopValue
required
Target memory address where data will be written.
bytes
required
Data to write (must be a bytes object).
set | None
default:"None"
Set of register names that must not be modified.
bytes
default:"b'\\xff'"
Single byte used to pad data if necessary. Must not be a badbyte.
Returns: A RopChain that writes the data to memory. Raises:
  • RopException if data cannot be written
  • RopException if fill_byte is a badbyte
  • RopException if addr is symbolic

ROP Instance Method

When you call rop.write_to_mem(), it invokes MemWriter.write_to_mem() internally:

Implementation Details

Memory Write Gadgets

MemWriter requires gadgets with specific properties:
  1. Self-contained: No dependencies on initial state
  2. Single memory write: Only one symbolic write operation
  3. Independent addr/data: Address and data controlled by different registers
From source code (mem_writer.py:358-375):

Gadget Examples

Badbyte Handling

When data contains badbytes, MemWriter uses multiple strategies:

1. Chunk Transforms

Transforms safe bytes into target bytes using arithmetic: From source code (mem_writer.py:213-250):
Example:

2. Per-Byte Operations

Handles each byte with different operations:

3. Write Plans

From source code (mem_writer.py:607-629):

MemWriteChain Caching

MemWriter caches chain templates for efficiency: From source code (mem_writer.py:18-132):

Usage Examples

Basic Memory Write

Writing Binary Data

Writing with Register Preservation

Building Execve Chain

Writing File Paths

Writing with Badbytes

Building Data Structures

Writing Pointer Arrays

Write Size Optimization

MemWriter automatically chooses optimal chunk sizes:

Error Handling

”Fail to write data to memory :(”

Raised when no suitable gadgets are found. Solutions:
  1. Use fast_mode=False when initializing ROP
  2. Check if binary has memory write gadgets
  3. Try alternative addresses or data

”fill_byte is a bad byte!”

Raised when fill_byte contains a badbyte. Solution: Choose a different fill_byte that’s not in badbytes.

”cannot write to a symbolic address”

Raised when addr parameter is symbolic. Solution: Use a concrete address value.

”data is not a byte string”

Raised when data is not bytes type. Solution: Convert to bytes: data.encode() or bytes([...])

Gadget Requirements

For memory writes to work:
  1. Controllable address: Can set address register to any value
  2. Controllable data: Can set data register to any value
  3. Independence: Address and data registers are different
  4. Self-contained: Gadget doesn’t require special initial state
Example verification from source code (mem_writer.py:413-422):

Performance Considerations

  • Writing large data may generate long chains
  • Badbyte handling adds overhead (arithmetic operations)
  • Caching reduces overhead for repeated writes
  • Chunk size optimization minimizes total gadgets used

See Also