Pivot Module

enum class IndirectType

Enum representing the type of indirect jump.

Values:

enumerator JMP
enumerator CALL
struct RopPivotInfo
#include <PivotFinder.h>

Encapsulates information about a successful ROP pivot.

Public Functions

void PrintDebugInfo() const

Prints debug information about the ROP pivot.

This includes details about the selected stack pivot, stack shifts, and ROP chain offset.

Public Members

const RopChain &rop

The ROP chain being pivoted to.

StackPivot pivot

The chosen stack pivot gadget.

uint64_t rop_min_offset

The minimum required offset for the ROP chain after shifting.

uint64_t rop_offset

The actual offset within the payload where the ROP chain is placed.

StackShiftingInfo stack_shift

Information about the stack shifting performed.

struct Pivot
#include <Pivots.h>

Base struct for all pivot gadgets.

Subclassed by OneGadgetPivot, PopRspPivot, PushIndirectPivot, StackShiftPivot

struct RegisterUsage
#include <Pivots.h>

Represents the usage of a register and the offsets relative to it that are used.

Public Members

Register reg

The register being used.

std::vector<int64_t> used_offsets

A vector of offsets relative to the register that are used.

struct StackShiftPivot : public Pivot
#include <Pivots.h>

Represents a stack shifting pivot gadget.

Public Functions

inline bool JumpsToShift() const

Checks if the gadget jumps to the shifted stack location.

Returns:

True if the gadget jumps to the shifted stack location, false otherwise.

Public Members

uint64_t ret_offset

The offset from the new stack pointer where the next return address is expected.

uint64_t shift_amount

The amount by which the stack pointer is shifted.

struct OneGadgetPivot : public Pivot
#include <Pivots.h>

Represents a one-gadget pivot.

Public Members

RegisterUsage pivot_reg

Information about the register used for the pivot.

int64_t next_rip_offset

The offset from the pivot register’s value to the next instruction pointer.

struct PushIndirectPivot : public Pivot
#include <Pivots.h>

Represents a push indirect pivot gadget.

Public Members

IndirectType indirect_type

The type of indirect jump (JMP or CALL).

RegisterUsage push_reg

Information about the register being pushed onto the stack.

RegisterUsage indirect_reg

Information about the register containing the indirect address.

int64_t next_rip_offset

The offset from the indirect register’s value to the next instruction pointer.

struct PopRspPivot : public Pivot
#include <Pivots.h>

Represents a pop RSP pivot gadget.

Public Members

uint64_t stack_change_before_rsp

The change in the stack pointer before the RSP register is popped.

int64_t next_rip_offset

The offset from the new RSP value to the next instruction pointer.

struct Pivots
#include <Pivots.h>

A collection of different types of pivot gadgets.

Public Members

std::vector<OneGadgetPivot> one_gadgets

A vector of one-gadget pivots.

std::vector<PushIndirectPivot> push_indirects

A vector of push indirect pivots.

std::vector<PopRspPivot> pop_rsps

A vector of pop RSP pivots.

std::vector<StackShiftPivot> stack_shifts

A vector of stack shifting pivots.

class StackPivot
#include <StackPivot.h>

Represents a potential stack pivot gadget or sequence of gadgets.

Represents a mechanism for changing the stack pointer (RSP) during exploit execution.

This class encapsulates information about different types of stack pivots (one-gadget, push/pop) and provides methods to apply them to a payload.

This class encapsulates different types of stack pivoting gadgets, such as one-gadget pivots or combined push-indirect/pop-RSP pivots. It provides functionality to describe the pivot, get relevant offsets, and apply the pivot’s effects to a payload buffer.

Public Functions

StackPivot(const OneGadgetPivot &one_gadget)

Constructs a StackPivot from a OneGadgetPivot.

Parameters:

one_gadget – The OneGadgetPivot to use.

StackPivot(const PushIndirectPivot &push_gadget, const PopRspPivot &pop_gadget)

Constructs a StackPivot from a PushIndirectPivot and a PopRspPivot.

Parameters:
std::string GetDescription(bool include_clobbers = true) const

Gets a string description of the stack pivot.

Parameters:

include_clobbers – Whether to include information about clobbered offsets in the description.

Throws:

ExpKitError – if the StackPivot is in an invalid state.

Returns:

A string describing the stack pivot.

uint64_t GetGadgetOffset()

Gets the address of the primary gadget in the stack pivot.

Returns:

The address of the primary gadget.

uint64_t GetDestinationOffset() const

Gets the destination offset within the buffer where the pivot will transfer execution.

This is typically the location where the next instruction or ROP chain should be placed.

Returns:

The destination offset.

void ApplyToPayload(Payload &payload, uint64_t kaslr_base)

Applies the stack pivot to a given payload.

Parameters:
  • payload – The Payload object to modify.

  • kaslr_base – The KASLR base address.

StackPivot(const OneGadgetPivot &one_gadget)

Constructs a StackPivot instance representing a one-gadget pivot.

Parameters:

one_gadget – The OneGadgetPivot structure describing the gadget.

StackPivot(const PushIndirectPivot &push_gadget, const PopRspPivot &pop_gadget)

Constructs a StackPivot instance representing a push-indirect and pop-RSP pivot combination.

Parameters:
std::string GetDescription(bool include_clobbers = true) const

Generates a human-readable description of the stack pivot.

This description includes details about the gadget’s address, registers used, destination, and optionally a list of clobbered offsets.

Parameters:

include_clobbers – If true, include a list of clobbered stack offsets in the description.

Throws:

ExpKitError – if the pivot instance is in an invalid state (neither one-gadget nor push/pop combination).

Returns:

A std::string containing the pivot’s description.

uint64_t GetGadgetOffset()

Returns the address of the primary gadget used for the pivot.

For a one-gadget pivot, this is the one-gadget’s address. For a push-indirect/pop-RSP pivot, this is the address of the push-indirect gadget.

Returns:

The 64-bit unsigned integer address of the pivot gadget.

uint64_t GetDestinationOffset() const

Returns the offset within the payload where the stack is intended to land.

For a one-gadget pivot, this is one_gadget_->next_rip_offset. For a push-indirect/pop-RSP pivot, this is pop_gadget_->next_rip_offset.

Returns:

The 64-bit unsigned integer offset within the payload.

void ApplyToPayload(Payload &payload, uint64_t kaslr_base)

Applies the effects of the stack pivot to a given payload.

This involves setting up the payload to execute the pivot, and reserving any stack offsets that might be clobbered by the pivot’s execution.

Parameters:
  • payload – A reference to the Payload object to modify.

  • kaslr_base – The Kernel Address Space Layout Randomization base address, used to calculate absolute gadget addresses.

struct StackShiftInfo
#include <StackShiftInfo.h>

Represents information about a single stack shifting gadget within a chain.

Public Members

uint64_t ret_offset

The offset within the payload where the address of this stack shift pivot is written.

const StackShiftPivot pivot

The stack shift pivot gadget.

struct StackShiftingInfo
#include <StackShiftInfo.h>

Stores information about a chain of stack shifting gadgets.

Public Members

std::vector<StackShiftInfo> stack_shifts

A vector of individual stack shift gadget information.

uint64_t from_offset

The starting offset within the payload where the first stack shift pivot address is written.

class PivotFinder
#include <PivotFinder.h>

Finds suitable stack pivots and stack shifting gadgets within a payload.

Public Functions

PivotFinder(const Pivots &pivots, Register buf_reg, Payload &payload)

Constructs a PivotFinder object with a single buffer register.

Parameters:
  • pivots – The collection of available pivot gadgets.

  • buf_reg – The single register pointing to the target buffer.

  • payload – The payload object to operate on.

PivotFinder(const Pivots &pivots, std::vector<Register> buf_regs, Payload &payload)

Constructs a PivotFinder object with multiple buffer registers.

Parameters:
  • pivots – The collection of available pivot gadgets.

  • buf_regs – A vector of registers pointing to the target buffer.

  • payload – The payload object to operate on.

bool CheckRegister(const RegisterUsage &reg)

Checks if a given register usage is compatible with the buffer registers and doesn’t overlap with reserved space in the payload.

Note

This function has TODOs related to more advanced checks for RIP control and skipping used space.

Parameters:

reg – The RegisterUsage to check.

Returns:

True if the register usage is valid for pivoting, false otherwise.

bool CheckOneGadget(const OneGadgetPivot &pivot, uint64_t free_bytes_after = 0)

Checks if a One-Gadget pivot is valid for the current payload state.

Parameters:
  • pivot – The OneGadgetPivot to check.

  • free_bytes_after – The minimum number of free bytes required after the pivot’s next RIP offset.

Returns:

True if the One-Gadget pivot is valid, false otherwise.

bool CheckPushIndirect(const PushIndirectPivot &pivot, uint64_t free_bytes_after = 0)

Checks if a Push/Indirect pivot is valid for the current payload state.

Parameters:
  • pivot – The PushIndirectPivot to check.

  • free_bytes_after – The minimum number of free bytes required after the pivot’s next RIP offset.

Returns:

True if the Push/Indirect pivot is valid, false otherwise.

std::vector<StackPivot> FindAll()

Finds all suitable stack pivot gadgets.

Returns:

A vector containing all found StackPivot objects.

std::optional<StackShiftPivot> FindShift(uint64_t min_shift, uint64_t upper_bound = std::numeric_limits<uint64_t>::max())

Finds a stack shift gadget with a shift amount greater than or equal to min_shift and less than upper_bound.

Parameters:
  • min_shift – The minimum required stack shift amount.

  • upper_bound – The exclusive upper bound for the stack shift amount.

Returns:

An optional StackShiftPivot if a suitable gadget is found, otherwise std::nullopt.

std::optional<StackPivot> Find(uint64_t free_bytes_after = 0)

Finds a single suitable stack pivot gadget.

Parameters:

free_bytes_after – The minimum number of free bytes required after the pivot’s next RIP offset.

Returns:

An optional StackPivot object. Contains a value if a pivot is found, otherwise std::nullopt.

std::optional<StackShiftingInfo> GetShiftToOffset(uint64_t from_offset, uint64_t min_to_offset)

Finds a sequence of stack shift gadgets to shift the stack pointer from a given offset to at least a minimum target offset.

Parameters:
  • from_offset – The starting offset of the stack pointer.

  • min_to_offset – The minimum desired offset for the stack pointer.

Returns:

An optional StackShiftingInfo object. Contains a value if a sequence of shifts is found, otherwise std::nullopt.

std::optional<StackShiftingInfo> GetShiftToRop(uint64_t from_offset, uint64_t byte_size, bool include_extra_slot, uint64_t min_rop_start = 0)

Finds a sequence of stack shift gadgets to shift the stack pointer to accommodate a ROP chain of a given size.

Parameters:
  • from_offset – The starting offset of the stack pointer.

  • byte_size – The size of the ROP chain in bytes.

  • include_extra_slot – If true, includes an extra 8 bytes in the required space.

Returns:

An optional StackShiftingInfo object. Contains a value if a sequence of shifts is found, otherwise std::nullopt.

std::optional<StackShiftingInfo> FindShiftsInternal(uint64_t from_offset, std::optional<uint64_t> min_to_offset, std::optional<uint64_t> min_next_space)

Internal helper function to find a sequence of stack shift gadgets using a breadth-first search.

The search aims to find a path of stack shifts that results in a stack pointer offset that meets either the minimum target offset or provides sufficient free space.

Parameters:
  • from_offset – The starting offset of the stack pointer.

  • min_to_offset – An optional minimum desired offset for the stack pointer.

  • min_next_space – An optional minimum required free space at the final stack pointer offset.

Throws:

ExpKitError – if both min_to_offset and min_next_space are not set.

Returns:

An optional StackShiftingInfo object. Contains a value if a sequence of shifts is found, otherwise std::nullopt.

StackShiftingInfo GetShiftInfoFromChain(const std::vector<StackShiftPivot> &chain, uint64_t from_offset)

Converts a chain of StackShiftPivot gadgets into a StackShiftingInfo structure.

This function calculates the resulting offsets and populates the StackShiftInfo vector based on the provided chain of gadgets and the starting offset.

Parameters:
  • chain – The vector of StackShiftPivot gadgets forming the chain.

  • from_offset – The starting offset of the stack pointer before the shifts.

Returns:

A StackShiftingInfo structure describing the sequence of shifts.

uint64_t ApplyShift(uint64_t kaslr_base, uint64_t from_offset, uint64_t min_to_offset)

Applies a sequence of stack shifts to the payload to reach at least a minimum target offset.

Parameters:
  • kaslr_base – The Kernel Address Space Layout Randomization base address.

  • from_offset – The starting offset of the stack pointer.

  • min_to_offset – The minimum desired offset for the stack pointer.

Throws:

ExpKitError – if a suitable stack shift gadget sequence cannot be found.

Returns:

The final offset of the stack pointer after applying the shifts.

RopPivotInfo PivotToRop(const RopChain &rop)

Attempts to find a stack pivot and a sequence of stack shifts to pivot to a given Rop chain.

Note

This function iterates through found pivots and attempts to apply shifts until a working combination is found.

Parameters:

rop – The ROP chain to pivot to.

Throws:

ExpKitError – if a suitable pivot and shift sequence cannot be found.

Returns:

A RopPivotInfo structure containing information about the successful pivot and shifts.

std::optional<PopRspPivot> GetPopRsp()

Finds a simple “pop rsp; ret” gadget that doesn’t change the stack before the RSP update and has its next RIP immediately after the gadget.

Returns:

An optional PopRspPivot. Contains a value if such a gadget is found, otherwise std::nullopt.

StackShiftPivot GetSingleRet()

Finds a simple “ret” gadget that shifts the stack by 8 bytes and jumps to the shifted location.

Returns:

A StackShiftPivot representing a simple “ret”.