Pivot Module
-
enum class IndirectType
Enum representing the type of indirect jump.
Values:
-
enumerator JMP
-
enumerator CALL
-
enumerator JMP
-
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.
-
void PrintDebugInfo() const
-
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.
-
Register reg
-
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.
-
inline bool JumpsToShift() const
-
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.
-
RegisterUsage pivot_reg
-
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.
-
IndirectType indirect_type
-
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.
-
uint64_t stack_change_before_rsp
-
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.
-
std::vector<OneGadgetPivot> one_gadgets
-
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:
push_gadget – The PushIndirectPivot to use.
pop_gadget – The PopRspPivot to use.
-
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:
push_gadget – The PushIndirectPivot structure.
pop_gadget – The PopRspPivot structure.
-
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 ispop_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.
-
StackPivot(const OneGadgetPivot &one_gadget)
-
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.
-
uint64_t ret_offset
-
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.
-
std::vector<StackShiftInfo> stack_shifts
-
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 ®)
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 thanupper_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
andmin_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”.
-
PivotFinder(const Pivots &pivots, Register buf_reg, Payload &payload)