Payloads Module
-
std::string intToHex(uint64_t value)
Converts a 64-bit unsigned integer to its hexadecimal string representation.
- Parameters:
value – The 64-bit unsigned integer to convert.
- Returns:
A
std::string
containing the “0x” prefixed hexadecimal representation of the value (uppercase).
-
struct PayloadData
- #include <PayloadBuilder.h>
Helper struct to encapsulate payload data for the builder.
This struct groups a Payload object, associated registers, and an optional offset for the next RIP (Instruction Pointer).
Note
The
registers
member is stored by value, meaning a copy is made.Public Functions
-
inline PayloadData(Payload &payload_ref, const std::vector<Register> ®s = {}, std::optional<size_t> rip_ptr_offset = std::nullopt)
Constructs a PayloadData instance.
- Parameters:
payload_ref – Reference to the Payload.
regs – Optional vector of Registers pointing to this buffer when RIP control is triggered (defaults to empty).
rip_ptr_offset – Optional offset of a field containing a function pointer which if overwritten can lead to RIP control. If nullopt, then this payload does not contain such a field.
Public Members
-
const std::vector<Register> registers
Registers pointing to this buffer when RIP control is triggered.
-
const std::optional<size_t> rip_ptr_offset
Optional offset of a field containing a function pointer which if overwritten can lead to RIP control. If nullopt, then this payload does not contain such a field.
-
inline PayloadData(Payload &payload_ref, const std::vector<Register> ®s = {}, std::optional<size_t> rip_ptr_offset = std::nullopt)
-
struct RopAction
- #include <RopChain.h>
Represents a single ROP (Return-Oriented Programming) action.
A RopAction is a sequence of 64-bit values that form part of a ROP chain. These values can represent addresses, immediate data, or arguments for gadgets.
Public Members
-
std::vector<uint64_t> values
The sequence of 64-bit values comprising this ROP action.
-
std::vector<uint64_t> values
-
class Payload
- #include <Payload.h>
Manages a dynamic, contiguous block of memory, tracking used sections.
This class provides functionalities to allocate, reserve, release, and write data to a buffer. It maintains a separate tracking mechanism to mark which bytes in the buffer are considered “used” or “reserved”. It also offers methods to find empty contiguous blocks for new data.
Public Functions
-
Payload(int size)
Constructs a new Payload object with a specified size.
Initializes the internal data buffer and a corresponding
used_bytes
tracking vector, marking all bytes as free initially.- Parameters:
size – The total size in bytes for the payload buffer.
-
Payload(const Payload &other)
Copy constructor for the Payload class.
Creates a new Payload object by deep-copying the data, used bytes map, and used size from another Payload instance.
- Parameters:
other – The Payload object to copy from.
-
size_t Size()
Returns the total size of the internal data buffer.
- Returns:
The total size of the buffer in bytes.
-
std::vector<uint8_t> &GetData()
Gets a reference to the raw internal data vector.
Warning
Modifying this vector directly can lead to inconsistencies with
used_bytes_
.- Returns:
A reference to the underlying
std::vector<uint8_t>
data buffer.
-
std::vector<uint8_t> GetUsedData() const
Returns a copy of the data that is currently marked as “used”.
- Returns:
A new
std::vector<uint8_t>
containing the data from the beginning of the buffer up toused_size_
.
-
bool CheckFree(uint64_t offset, uint64_t len, bool throws = false)
Checks if a specified range of bytes is free (not marked as used).
- Parameters:
offset – The starting offset in the buffer to check.
len – The length of the contiguous block to check.
throws – If true, an ExpKitError is thrown if the range is not free or out of bounds. If false, it simply returns
false
.
- Throws:
ExpKitError – if
throws
istrue
and the range is out of bounds or occupied.- Returns:
true
if the entire range is free and within bounds,false
otherwise.
-
uint8_t *Reserve(uint64_t offset, uint64_t len)
Reserves a contiguous block of memory and marks it as used.
This method checks if the specified range is free. If so, it marks the bytes as used and returns a pointer to the beginning of the reserved block within the internal data buffer. It updates
used_size_
if the new reservation extends beyond the previously used area.- Parameters:
offset – The starting offset in the buffer to reserve.
len – The length of the contiguous block to reserve.
- Throws:
ExpKitError – if the range is not free or out of bounds.
- Returns:
A
uint8_t*
pointer to the reserved memory location within the buffer.
-
void Release(uint64_t offset, uint64_t len)
Releases a previously reserved block of memory.
Marks the specified range of bytes as free. If the released block was at the end of the
used_size_
area,used_size_
is adjusted downwards.- Parameters:
offset – The starting offset of the block to release.
len – The length of the block to release.
-
uint64_t *ReserveU64(uint64_t offset)
Reserves space for a
uint64_t
at a given offset.Warning
This function assumes the underlying buffer’s memory address will not change during its lifetime, which is generally true for
std::vector
unless it’s resized.- Parameters:
offset – The starting offset for the
uint64_t
.- Throws:
ExpKitError – if the space is not free or out of bounds.
- Returns:
A
uint64_t*
pointer to the reserved memory location.
-
uint32_t *ReserveU32(uint64_t offset)
Reserves space for a
uint32_t
at a given offset.Warning
This function assumes the underlying buffer’s memory address will not change during its lifetime, which is generally true for
std::vector
unless it’s resized.- Parameters:
offset – The starting offset for the
uint32_t
.- Throws:
ExpKitError – if the space is not free or out of bounds.
- Returns:
A
uint32_t*
pointer to the reserved memory location.
-
void Set(uint64_t offset, void *src, size_t len)
Sets a block of bytes in the payload.
Reserves the specified range and then copies data from
src
into it.- Parameters:
offset – The starting offset in the payload.
src – A pointer to the source data to copy.
len – The number of bytes to copy.
- Throws:
ExpKitError – if the space is not free or out of bounds.
-
void Set(uint64_t offset, const std::vector<uint8_t> &bytes)
Sets a block of bytes from a
std::vector
in the payload.Reserves the necessary space and then copies the bytes from the provided vector.
- Parameters:
offset – The starting offset in the payload.
bytes – The
std::vector
containing the data to copy.
- Throws:
ExpKitError – if the space is not free or out of bounds.
-
void SetU32(uint64_t offset, uint32_t value)
Sets a 32-bit unsigned integer value at a specific offset.
Reserves space for a
uint32_t
and writes the value.- Parameters:
offset – The starting offset in the payload.
value – The
uint32_t
value to set.
- Throws:
ExpKitError – if the space is not free or out of bounds.
-
void SetU64(uint64_t offset, uint64_t value)
Sets a 64-bit unsigned integer value at a specific offset.
Reserves space for a
uint64_t
and writes the value.- Parameters:
offset – The starting offset in the payload.
value – The
uint64_t
value to set.
- Throws:
ExpKitError – if the space is not free or out of bounds.
-
std::optional<uint64_t> FindEmpty(uint64_t len, uint64_t alignment = 1, uint64_t min_offset = 0)
Finds the first contiguous block of empty (unused) bytes of a given length.
Searches for a free block starting from
min_offset
, respecting optional alignment. The algorithm is O(n) where n is the size of the buffer.- Parameters:
len – The desired length of the empty block.
alignment – The required alignment for the found offset (default is 1).
min_offset – The minimum offset to start searching from (default is 0).
- Returns:
An
std::optional
containing the found offset if a suitable block is found, orstd::nullopt
otherwise.
-
Payload(int size)
-
class PayloadBuilder
- #include <PayloadBuilder.h>
A class designed to construct and optimize exploit payloads.
This builder manages multiple payload components, ROP (Return-Oriented Programming) chains, and stack pivots to create a cohesive and functional exploit payload. It attempts to find suitable stack pivots and apply ROP actions efficiently.
The implementation tracks
StackShiftingInfo
for everyRopAction
. If two actions can be stored adjacently, theStackShiftingInfo
between them will represent an empty shift.Public Functions
-
inline PayloadBuilder(const Pivots &pivots, uint64_t kaslr_base)
Constructs a PayloadBuilder instance.
- Parameters:
pivots – Available stack pivot gadgets.
kaslr_base – The Kernel Address Space Layout Randomization base address.
-
void AddPayload(Payload &payload, const std::vector<Register> ®isters = {}, std::optional<size_t> rip_ptr_offset = std::nullopt)
Adds a new payload component to the builder.
- Parameters:
payload – A reference to the Payload object to add.
registers – Optional vector of Registers pointing to this buffer when RIP control is triggered (defaults to empty).
rip_ptr_offset – Optional offset of a field containing a function pointer which if overwritten can lead to RIP control. If nullopt, then this payload does not contain such a field.
-
void AddPayload(Payload &payload, std::optional<Register> reg = std::nullopt, std::optional<size_t> rip_ptr_offset = std::nullopt)
Adds a new payload component with an optional single register.
- Parameters:
payload – A reference to the Payload object to add.
reg – Optional register pointing to this buffer when RIP control is triggered (defaults to nullopt - so no register points to this buffer).
rip_ptr_offset – Optional offset of a field containing a function pointer which if overwritten can lead to RIP control. If nullopt, then this payload does not contain such a field.
-
void AddRopChain(const RopChain &rop_chain)
Appends a ROP chain to the builder’s sequence of ROP actions.
- Parameters:
rop_chain – The RopChain object to add.
-
void SetRopShift(const uint64_t shift_value)
Uses stack shift gadgets to shift the stack by at least shift_value.
This method is useful for moving the rop chain towards the end of the buffer. This can prevent function calls from clobbering data before the buffer.
- Parameters:
shift_value – Shifts the stack by at least shift_value.
-
bool Build(bool need_pivot = true)
Attempts to build the final payload.
This method tries to find a suitable stack pivot, applies it to the payload, and then attempts to integrate all ROP actions, performing stack shifts as necessary.
- Parameters:
need_pivot – If true, the builder will explicitly look for a pivot (defaults to
true
).- Throws:
ExpKitError – if multiple RIP offsets are found when
need_pivot
is true.- Returns:
true
if a successful payload is built,false
otherwise.
-
void PrintDebugInfo() const
Prints debug information about the built payload, if successful.
This includes details about the chosen stack pivot, stack shifts, and ROP chain layout.
-
StackPivot GetStackPivot()
Returns the chosen stack pivot.
This function may be called after Build() to get the stack pivot gadget that was chosen.
-
inline PayloadBuilder(const Pivots &pivots, uint64_t kaslr_base)
-
class RopChain
- #include <RopChain.h>
Manages an ordered sequence of ROP actions to form a ROP chain.
The RopChain class allows for the construction of complex ROP chains by adding individual ROP actions or raw 64-bit values. It handles KASLR (Kernel Address Space Layout Randomization) offsets and argument substitution for actions defined by a Target.
Public Functions
-
RopChain(Target &target, uint64_t kaslr_base)
Constructs a new RopChain.
- Parameters:
target – A reference to the Target object which provides definitions for ROP actions.
kaslr_base – The base address for KASLR, used to adjust symbol addresses.
-
void AddRopAction(RopActionId id, std::vector<uint64_t> arguments = {})
Adds a predefined ROP action to the chain.
This method retrieves the sequence of ROP items for a given action ID from the associated Target and constructs a RopAction, substituting arguments and applying KASLR offsets where necessary.
- Parameters:
id – The ID of the ROP action to add.
arguments – A vector of 64-bit arguments to substitute into the action. The index of an argument in this vector corresponds to its
item.value
whenitem.type == RopItemType::ARGUMENT
.
- Throws:
ExpKitError – If an unexpected RopAction item type is encountered or if there are not enough arguments provided for an action.
-
void Add(uint64_t item, bool offset = false)
Adds a raw 64-bit item directly to the ROP chain as a single-value action.
This is useful for adding arbitrary values (e.g., stack pivots, return addresses, or immediate values) that are not part of a predefined RopAction.
- Parameters:
item – The 64-bit value to add.
offset – If true, the
kaslr_base_
will be added to the item. Defaults to false.
-
std::vector<uint8_t> GetData() const
Retrieves the entire ROP chain as a vector of bytes.
The 64-bit items in the chain are converted to a contiguous byte array. This is useful for writing the ROP chain directly to memory or a file.
- Returns:
A
std::vector<uint8_t>
representing the ROP chain in byte format.
-
std::vector<uint64_t> GetDataWords() const
Retrieves the entire ROP chain as a vector of 64-bit words.
This method collects all individual 64-bit values from the sequence of RopActions into a single flat vector.
- Returns:
A
std::vector<uint64_t>
representing the ROP chain as 64-bit words.
-
uint64_t GetByteSize() const
Calculates the total size of the ROP chain in bytes.
- Returns:
The total size of the ROP chain in bytes.
Public Members
-
uint64_t kaslr_base_
The KASLR base address used for symbol offsetting.
-
std::vector<RopAction> actions_
Stores the ordered sequence of ROP actions.
-
RopChain(Target &target, uint64_t kaslr_base)