Skip to main content
The Pivot class builds ROP chains that perform stack pivoting - moving the stack pointer to a different memory location to enable exploitation when stack space is limited.

Overview

Accessed through the ROP instance as rop.pivot(), Pivot automatically:
  • Finds gadgets that modify the stack pointer
  • Supports pivoting to addresses or register values
  • Handles different pivot mechanisms (mov, xchg, add, etc.)
  • Manages pre-pivot stack setup
  • Verifies pivot operations

Class Definition

Located in angrop/chain_builder/pivot.py

Public Methods

pivot

Builds a chain that pivots the stack pointer.
RopValue
required
Target for the pivot. Can be:
  • Address (RopValue with concrete address)
  • Register (RopValue with register name)
Returns: A RopChain that pivots the stack. Raises: RopException if pivot cannot be performed.

pivot_addr

Pivots stack to a specific address.
RopValue
required
Target address for the new stack location.
Returns: A RopChain that pivots to the address.

pivot_reg

Pivots stack to an address stored in a register.
RopValue
required
RopValue representing a register containing the target address.
Returns: A RopChain that pivots to the register value.

ROP Instance Method

Automatically detects whether target is address or register:

Implementation Details

Pivot Gadget Types

Pivot recognizes several gadget patterns:
  1. Direct move: mov rsp, rbp; ret
  2. Exchange: xchg rsp, rax; ret
  3. Add to SP: add rsp, 0x100; ret
  4. Pop to SP: pop rsp; ret
  5. Leave: leave; ret (equivalent to mov rsp, rbp; pop rbp; ret)
From source code (pivot.py:10-25):

SP Controllers

Gadgets are analyzed to identify which registers control the final SP value: From source code (pivot.py:111-113):
Example:

Pivot to Address

From source code (pivot.py:43-75):

Pivot to Register

From source code (pivot.py:77-109):

Usage Examples

Basic Stack Pivot to Address

Pivot to Register

Complete Pivot Example

Pivot for Buffer Extension

Chained Pivots

Pivot with Leave Gadget

Gadget Requirements

For pivoting to work:
  1. SP modification: Gadget must change stack pointer
  2. Controllable: SP target must be controllable via registers or offsets
  3. No conditional branches: Ensures predictable execution
  4. Not jmp_reg: Direct jumps don’t help with pivoting
  5. No symbolic access: Memory accesses must be concrete
From source code (pivot.py:118-123):

Common Pivot Patterns

x86_64 Patterns

x86 (32-bit) Patterns

ARM Patterns

Stack Change Tracking

Pivot gadgets track two stack changes:
  1. stack_change_before_pivot: Stack movement before SP is modified
  2. stack_change_after_pivot: Stack movement after pivot
From source code (pivot.py:113):
Example:

Verification

Pivot chains are verified using symbolic execution:
The stop_at_pivot=True flag stops execution when SP changes significantly.

Error Handling

”Fail to pivot the stack to !”

Raised when no pivot chain can be built. Solutions:
  1. Check if pivot gadgets exist: rop.pivot_gadgets
  2. Try pivoting to a register instead
  3. Use find_gadgets(fast_mode=False) for more gadgets
  4. Verify target address is valid

”Fail to pivot the stack to !”

Raised when register-based pivot fails. Solutions:
  1. Check if gadgets control SP via that register
  2. Try a different register
  3. Use address-based pivot instead

Performance Considerations

  • Pivot gadgets are pre-filtered and sorted during bootstrap
  • Symbolic execution adds overhead for verification
  • Simpler pivots (direct moves) are faster
  • Complex pivots may require multiple gadgets

Architecture Support

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

Advanced Techniques

Partial Overwrites

Info Leak + Pivot

Best Practices

  1. Verify target alignment: Stack should be aligned to word boundary
  2. Plan stack layout: Know what will be at target address
  3. Test pivot gadgets: Use chain.pp() to inspect
  4. Consider stack growth: Stack grows down on most architectures
  5. Account for saved values: Leave gadget pops rbp first

See Also