Skip to main content
The Shifter class builds ROP chains that shift the stack pointer by specific byte amounts, enabling precise stack manipulation and ret-sled construction.

Overview

Accessed through the ROP instance as rop.shift() and rop.retsled(), Shifter automatically:
  • Finds pop chains that shift SP by exact amounts
  • Constructs ret-sleds of arbitrary length
  • Manages stack value placement
  • Supports custom next PC positioning
  • Verifies stack shifts

Class Definition

Located in angrop/chain_builder/shifter.py

Public Methods

shift

Builds a chain that shifts the stack pointer by a specific number of bytes.
int
required
Number of bytes to shift the stack (must be word-aligned).
set | None
default:"None"
Set of register names that should not be modified.
int
default:"-1"
Index (in words) where the next PC should be placed. Supports negative indexing.
  • -1: Next PC at end (default)
  • 0: Next PC at start
  • Positive: Absolute position
Returns: A RopChain that shifts the stack. Raises: RopException if shift cannot be performed.

retsled

Builds a ret-sled of specified size (chain of ret gadgets).
int
required
Total size in bytes for the ret-sled (must be word-aligned).
set | None
default:"None"
Set of register names that should not be modified.
Returns: A RopChain consisting only of ret gadgets. Raises: RopException if ret-sled cannot be built.

verify_shift

Verifies that a chain correctly shifts the stack.
RopChain
required
Chain to verify.
int
required
Expected shift amount.
set
required
Registers that should not be modified.
Returns: True if verification passes, False otherwise.

verify_retsled

Verifies that a ret-sled has the correct size.
RopChain
required
Chain to verify.
int
required
Expected size in bytes.
set
required
Registers that should not be modified.
Returns: True if verification passes, False otherwise.

ROP Instance Methods

Implementation Details

Shift Gadget Dictionary

Shifter maintains a dictionary mapping stack changes to gadgets: From source code (shifter.py:140-159):
Example dictionary:

Shift Implementation

From source code (shifter.py:62-110):

Retsled Implementation

From source code (shifter.py:112-130):

Usage Examples

Basic Stack Shift

Output:

Shift with Custom Next PC Position

Stack Arguments for Function Calls

Used internally by FuncCaller for stack arguments: From source code context:

Ret-Sled

Output:

NOP Sled Equivalent

Preserving Registers During Shift

Stack Cleanup After Function

Shift Gadget Patterns

Common Patterns by Stack Change

8 bytes (1 word)

16 bytes (2 words)

24 bytes (3 words)

32 bytes (4 words)

PC Offset Importance

The pc_offset determines where ret pops from:

Verification

From source code (shifter.py:26-42):

Effect and Comparison Tuples

From source code (shifter.py:132-138):
This ensures:
  1. Gadgets grouped by stack_change and pc_offset
  2. Within groups, prefer fewer register changes
  3. Then prefer smaller stack changes
  4. Then simpler transit types
  5. Finally fewer instructions

Error Handling

”Currently, we do not support shifting misaligned sp change”

Raised when length is not word-aligned. Solution: Use multiples of word size:

“Encounter a shifting request that requires chaining multiple shifting gadgets”

Raised when exact shift amount isn’t available. Solutions:
  1. Try a different shift amount
  2. Use fast_mode=False for more gadgets
  3. Manually chain multiple shifts:

“the size of a retsled must be word aligned”

Raised when retsled size is not aligned. Solution: Use word-aligned sizes.

”fail to find a ret-equivalent gadget”

Raised when no simple ret gadget exists. Solution: Very rare; binary likely has unusual structure.

Performance Considerations

  • Gadget dictionary is pre-built during bootstrap
  • Shifts are fast (single gadget)
  • Retsleds may be long but simple
  • Verification adds small overhead

Architecture Support

  • x86/x86_64: Full support, many pop patterns
  • ARM/ARM64: Full support
  • MIPS: Full support
  • PowerPC: Basic support

Advanced Techniques

Precise Stack Control

Custom Stack Layouts

Ret-Sled for Alignment

Best Practices

  1. Use for exact amounts: When you need precise stack shifts
  2. Prefer simpler shifts: Fewer words = fewer clobbered registers
  3. Check alignment: Always use word-aligned values
  4. Verify shifts: Use chain.pp() to inspect
  5. Consider alternatives: Sometimes pivot() is better

See Also

  • Pivot - Stack pivoting to arbitrary locations
  • FuncCaller - Uses shift for stack arguments
  • ChainBuilder - Main chain building interface