Writing to Memory: write_to_mem()
The write_to_mem() method writes arbitrary data to a specified memory address.
Method Signature
addr: Target memory address (integer or RopValue)data: Bytes to write (must be a bytes object)preserve_regs: Set of register names that should not be modifiedfill_byte: Single byte used to pad data if needed (default:b"\xff")
RopChain that writes the data to memory
Basic Examples
1
Write a string to memory
2
Write binary data
3
Write with register preservation
Angrop automatically handles writing data in chunks based on available gadgets. It will use the most efficient write size (8, 4, 2, or 1 byte) depending on what gadgets are available.
Real-World Example: Building an Execve Chain
From angrop’s Python API documentation:Writing Files and Paths
Memory Addition: mem_add()
Add a value to data stored at a memory location.
Method Signature
addr: Memory address to modifyvalue: Value to add (integer or RopValue)size: Number of bytes to operate on (1, 2, 4, or 8). Default is architecture word size.
RopChain that performs the addition
Example
The memory operation methods require gadgets that can perform memory writes with arithmetic operations, such as
add dword ptr [rax], ebx; ret.Memory XOR: mem_xor()
XOR data at a memory location with a value.
Method Signature
addr: Memory address to modifyvalue: Value to XOR withsize: Number of bytes (1, 2, 4, or 8)
Example
Memory OR: mem_or()
Perform bitwise OR on data at a memory location.
Method Signature
addr: Memory address to modifyvalue: Value to OR withsize: Number of bytes (1, 2, 4, or 8)
Example
Memory AND: mem_and()
Perform bitwise AND on data at a memory location.
Method Signature
addr: Memory address to modifyvalue: Value to AND withsize: Number of bytes (1, 2, 4, or 8)
Example
Complete Memory Operations Example
From angrop’s Python API documentation:Writing with Badbytes
When badbytes are configured, angrop uses sophisticated techniques to avoid them:How Badbyte Avoidance Works
From the source code (mem_writer.py:606-630), angrop uses multiple strategies:
1
Try chunk transforms
Find operations (XOR, OR, AND, ADD) that can transform safe bytes into target bytes:
2
Try per-byte operations
Handle each byte individually using different operations:
3
Use register arithmetic
Construct values in registers using arithmetic, then write to memory.
Memory Write Gadget Requirements
For memory operations to work, angrop needs specific types of gadgets:For write_to_mem():
- Gadgets like:
mov [rax], rbx; ret - Controllable address register (rax)
- Controllable data register (rbx)
- Address and data must be independent
For mem_add(), mem_xor(), etc.:
- Gadgets like:
add [rax], ebx; ret xor [rdi], rsi; retor [rcx], rdx; retand [r8], r9; ret
If you get “Fail to write data to memory” or “Fail to perform _mem_change” errors, it means angrop couldn’t find suitable gadgets. Try:
- Using
fast_mode=Falsewhen initializing ROP - Checking if the binary has the necessary gadgets
- Using alternative approaches (e.g., setting up registers and using library functions)
Advanced Memory Techniques
Building Data Structures
Writing Pointer Arrays
Modifying Existing Data
Size Specification
All memory operations support explicit size specification:Error Handling
Best Practices
- Choose safe addresses: Use addresses that don’t contain badbytes
- Minimize writes: Write larger chunks when possible instead of byte-by-byte
- Use fill_byte wisely: Choose a fill byte that’s not a badbyte
- Verify operations: Use
chain.pp()to inspect generated chains - Consider data alignment: Some gadgets may require aligned addresses
Performance Considerations
- Writing large data may generate long chains
- Memory operations with badbytes are slower due to additional transformations
- Using
sizeparameter efficiently can reduce chain length - Preservation of registers adds constraints and may increase chain complexity
Next Steps
- Function Calls - Use memory writes to set up function arguments
- Syscalls - Combine memory writes with syscalls for exploits
- Badbytes - Learn more about handling restricted bytes