rizin/librz/include/rz_gadget.h

222 lines
9.1 KiB
C

// SPDX-FileCopyrightText: 2026 MrQuantum1915 <darshanpatelgdh@gmail.com>
// SPDX-FileCopyrightText: 2024 z3phyr <giridh1337@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#ifndef RZ_GADGET_H
#define RZ_GADGET_H
/**
* \file rz_gadget.h
* \brief Gadget (ROP, JOP, COP) related APIs and structures.
*
* This file contains definitions, structures, and function prototypes for handling ROP, JOP and COP gadgets and constraints.
*/
#include <rz_cmd.h>
#include <rz_il.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Information about a register.
*/
typedef struct rz_gadget_reg_info_t {
char *name;
bool is_mem_read; ///< Register involved in Memory read.
bool is_pc_write; ///< PC write flag.
bool is_var_read; ///< Register involved in Variable read.
bool is_var_write; ///< Register involved in Variable write.
bool is_mem_write; ///< Register involved in Memory write.
ut64 init_val;
ut64 new_val;
ut64 bits; ///< Register bits for capturing cast
RzILOpPure *value_transformations; ///< TODO: Captures Value transformations.
} RzGadgetRegInfo;
/**
* \brief Information about a gadget.
*/
typedef struct rz_gadget_info_t {
ut64 address; ///< Gadget address.
ut64 stack_change; ///< Stack change.
ut64 curr_pc_val; ///< Current PC value.
ut32 size; ///< Gadget size.
bool is_pc_write; ///< PC write flag.
bool is_syscall; ///< Syscall flag.
RzIterator /*RzAnalysisBytes *>*/ *analysis_cache; ///< Stores \p RzAnalysisBytes for the gadget.
RzPVector /*<RzGadgetRegInfo *>*/ *modified_registers; ///< Modified registers.
RzList /*<RzGadgetRegInfo *>*/ *dependencies; ///< Dependencies.
} RzGadgetInfo;
/**
* \brief Type of gadget to search for.
*/
typedef enum {
RZ_GADGET_TYPE_ROP, ///< Return-Oriented Programming.
RZ_GADGET_TYPE_JOP, ///< Jump-Oriented Programming.
RZ_GADGET_TYPE_COP, ///< Call-Oriented Programming.
} RzGadgetType;
/**
* \brief Types of IL instructions for Gadget constraints.
*/
typedef enum rz_gadget_il_instr_type {
MOV_CONST, ///< reg <- const
MOV_REG, ///< reg <- reg
MOV_OP_CONST, ///< reg <- reg OP const
MOV_OP_REG, ///< reg <- reg OP reg
SYSCALL, ///< syscall
} RzGadgetILInstructionType;
/**
* \brief Argument types for Gadget constraints.
*/
typedef enum {
SRC_REG,
DST_REG,
SRC_CONST,
SRC_REG_SECOND,
OP,
NUM_ARGS
} RzGadgetArgType;
/**
* \brief Gadget request mask for filtering gadgets.
*/
typedef enum {
RZ_GADGET_PRINT = 1 << 0, ///< Print Gadget.
RZ_GADGET_PRINT_DETAIL = 1 << 1, ///< Detailed Gadget.
RZ_GADGET_ANALYZE = 1 << 2, ///< Detailed Gadget.
RZ_GADGET_ALL = RZ_GADGET_PRINT | RZ_GADGET_PRINT_DETAIL | RZ_GADGET_ANALYZE ///< All Gadget requests.
} RzGadgetRequestMask;
/**
* \brief Gadget search mask for filtering gadgets given details.
*/
typedef enum {
RZ_GADGET_DETAIL_SEARCH_NON = 0,
RZ_GADGET_DETAIL_SEARCH_STACK = 1 << 0, ///< Search gadgets by stack changes.
RZ_GADGET_DETAIL_SEARCH_SIZE = 1 << 1, ///< Search gadgets by gadget sizes.
// RZ_GADGET_DETAIL_SEARCH_WRITE = 1 << 2, ///< Search gadgets by written registers.
// RZ_GADGET_DETAIL_SEARCH_READ = 1 << 3, ///< Search gadgets by read registers.
} RzGadgetDetailSearchMask;
/**
* \brief Filter conditions while searching gadgets by stack changes.
*/
typedef enum {
RZ_GADGET_DETAIL_CMP_EQ = 1, ///< ==
RZ_GADGET_DETAIL_CMP_GT = 1 << 1, ///< >
RZ_GADGET_DETAIL_CMP_GE = RZ_GADGET_DETAIL_CMP_GT | RZ_GADGET_DETAIL_CMP_EQ, ///< >=
RZ_GADGET_DETAIL_CMP_LT = 1 << 2, ///< <
RZ_GADGET_DETAIL_CMP_LE = RZ_GADGET_DETAIL_CMP_LT | RZ_GADGET_DETAIL_CMP_EQ, ///< <=
} RzGadgetDetailSearchCmpOp;
/**
* \brief Pair representing an end gadget with instruction offset and delay size.
*/
typedef struct rz_gadget_endlist_pair_t {
int instr_offset; ///< Instruction offset.
int delay_size; ///< Delay size.
} RzGadgetEndListPair;
/**
* \brief Structure representing a Gadget constraint.
*/
typedef struct rz_gadget_constraint_t {
RzGadgetILInstructionType type; ///< IL instruction type.
char *args[NUM_ARGS]; ///< Arguments.
} RzGadgetConstraint;
/**
* \brief Structure representing a Gadget search context.
*/
typedef struct rz_gadget_search_context_t {
RzGadgetType type; ///< Type of gadget to search for.
ut8 max_instr; ///< Gadget search max length.
bool subchains; ///< Display every length gadget from gadget.len=X to 2.
bool allow_conditional; ///< Include conditional jump, calls and returns in gadget search.
bool comments; ///< Display comments in gadget search output.
char *greparg; ///< Grep argument string.
const char *arch; ///< Architecture of the binary.
bool regexp; ///< Regular expression argument flag.
bool cache; ///< Cache the search results.
RzGadgetRequestMask mask; ///< Mask for kind of gadget request operation.
RzGadgetDetailSearchMask detail_mask; ///< Mask for searching gadgets given details.
RzCmdStateOutput *state; ///< Command state output.
int increment; ///< Gadget search increment value.
ut64 max_count; ///< Maximum number of hits (0: no limit).
ut64 from; ///< Start address to start gadget search.
ut64 to; ///< End address to stop gadget search.
RzList /*<RzGadgetEndListPair *>*/ *end_list; ///< List of end gadgets.
HtSU *unique_hitlists; ///< Cache unique gadget hitlists.
bool ret_val; ///< Flag to indicate return the search results.
RzStrBuf *buf; ///< String buffer for storing search results.
RzPVector /*<RzGadgetConstraint *>*/ *constraints; ///< User constraints for filtering.
} RzGadgetSearchContext;
/**
* \brief Enum for different Gadget register events.
*/
typedef enum {
RZ_GADGET_EVENT_VAR_READ,
RZ_GADGET_EVENT_VAR_WRITE,
RZ_GADGET_EVENT_MEM_READ,
RZ_GADGET_EVENT_MEM_WRITE,
RZ_GADGET_EVENT_PC_WRITE,
RZ_GADGET_EVENT_COUNT ///< This should always be the last element.
} RzGadgetEvent;
/**
* \brief Function pointer type for event check functions.
*/
typedef bool (*rz_gadget_event_check_fn)(const RzGadgetRegInfo *);
/**
* \brief Array of event check functions.
*/
extern rz_gadget_event_check_fn rz_gadget_event_functions[RZ_GADGET_EVENT_COUNT];
// Command APIs
RZ_API RzCmdStatus rz_core_gadget_search(RZ_NONNULL RzCore *core, RZ_NONNULL RzGadgetSearchContext *context);
RZ_API RzCmdStatus rz_core_gadget_info(RZ_NONNULL RzCore *core, RZ_NONNULL RZ_OWN RzGadgetSearchContext *context);
RZ_API bool rz_core_gadget_analyze_constraint(const RZ_NONNULL RzCore *core, const RZ_NONNULL char *str,
RZ_NULLABLE RZ_OUT RzGadgetConstraint *gadget_constraint);
RZ_API RZ_OWN RzPVector /*<RzGadgetConstraint *>*/ *rz_core_gadget_constraint_map_parse(const RZ_NONNULL RzCore *core, int argc, const char **argv);
RZ_API bool rz_core_handle_gadget_request_type(RZ_NONNULL RzCore *core, RZ_NONNULL RzGadgetSearchContext *context, RZ_NONNULL RzPVector /*<RzCoreAsmHit *>*/ *hitlist);
RZ_API RZ_NULLABLE RZ_OWN RzList /*<char *>*/ *rz_core_gadget_handle_grep_args(RZ_NULLABLE const char *greparg, const bool regexp);
// Gadget Search Context APIs
RZ_API RZ_OWN RzGadgetSearchContext *rz_core_gadget_search_context_new(RZ_NONNULL const RzCore *core, const RzGadgetType gadget_type, RZ_NULLABLE const char *greparg, bool regexp,
RzGadgetRequestMask mask, RzGadgetDetailSearchMask detail_mask, RZ_NULLABLE RZ_BORROW RzCmdStateOutput *state);
RZ_API void rz_core_gadget_search_context_free(RZ_NULLABLE RzGadgetSearchContext *context);
// Gadget Constraint APIs
RZ_API void rz_core_gadget_constraint_free(RZ_NULLABLE void *data);
RZ_API RZ_OWN RzGadgetConstraint *rz_core_gadget_constraint_parse_args(const RZ_NONNULL RzCore *core, const RZ_NONNULL char *token);
// Gadget Info APIs
RZ_API void rz_core_gadget_info_free(RZ_NULLABLE RzGadgetInfo *gadget_info);
RZ_API void rz_core_gadget_info_add_register(const RZ_NONNULL RZ_OUT RzGadgetInfo *gadget_info,
RZ_NONNULL RzGadgetRegInfo *reg_info, bool is_dependency);
RZ_API void rz_core_gadget_info_update_register(const RZ_INOUT RzGadgetInfo *gadget_info, RZ_INOUT RZ_NONNULL RzGadgetRegInfo *new_reg_info);
RZ_API RZ_OWN RzGadgetInfo *rz_core_gadget_info_new(ut64 address);
RZ_API RZ_OWN RzGadgetRegInfo *rz_core_gadget_reg_info_dup(RZ_BORROW RZ_NONNULL RzGadgetRegInfo *src);
RZ_API void rz_core_gadget_reg_info_free(RZ_NULLABLE RzGadgetRegInfo *reg_info);
RZ_API RZ_OWN RzGadgetRegInfo *rz_core_gadget_reg_info_new(RZ_NONNULL const RzCore *core, RZ_NONNULL const RzILEvent *evt,
ut64 init_val, ut64 new_val);
RZ_API RZ_BORROW RzGadgetRegInfo *rz_core_gadget_info_get_modified_register(const RZ_NONNULL RzGadgetInfo *gadget_info,
const RZ_NONNULL char *name);
RZ_API bool rz_core_gadget_info_has_register(const RZ_NONNULL RzGadgetInfo *gadget_info, const RZ_NONNULL char *name);
RZ_API RZ_OWN RzPVector /*<RzGadgetRegInfo *>*/ *rz_core_gadget_get_reg_info_by_event(const RZ_NONNULL RzGadgetInfo *gadget_info, RzGadgetEvent event);
RZ_API RZ_OWN RzPVector /*<RzGadgetRegInfo *>*/ *rz_core_gadget_get_reg_info_by_reg_names(const RZ_NONNULL RzGadgetInfo *gadget_info, RZ_NONNULL const RzPVector /*<char *>*/ *registers);
RZ_API bool rz_core_gadget_reg_info_has_event(const RZ_NONNULL RzGadgetInfo *gadget_info,
RzGadgetEvent event, const RZ_NULLABLE char *reg_name);
RZ_API RZ_OWN RzPVector /*<RzGadgetRegInfo *>*/ *rz_core_gadget_reg_info_find(const RZ_NONNULL RzGadgetInfo *gadget_info, const RZ_NONNULL char *name);
#ifdef __cplusplus
}
#endif
#endif // RZ_GADGET_H