Arion 1.0.2-alpha
A high-performance C++ framework for emulating executable binaries.
 
Loading...
Searching...
No Matches
hooks_manager.hpp
Go to the documentation of this file.
1#ifndef ARION_HOOKS_MANAGER_HPP
2#define ARION_HOOKS_MANAGER_HPP
3
6#include <arion/unicorn/unicorn.h>
7#include <functional>
8#include <map>
9#include <memory>
10#include <stack>
11#include <variant>
12
13namespace arion
14{
15
16class Arion; // forward declaration to prevent circular dependencies
17
19using HOOK_ID = uint64_t;
20
26using NO_PARAM_HOOK_CALLBACK = std::function<void(std::shared_ptr<Arion> arion, void *user_data)>;
33using NO_PARAM_BOOL_HOOK_CALLBACK = std::function<bool(std::shared_ptr<Arion> arion, void *user_data)>;
40using U32_HOOK_CALLBACK = std::function<void(std::shared_ptr<Arion> arion, uint32_t val, void *user_data)>;
48using ADDR_SZ_HOOK_CALLBACK = std::function<void(std::shared_ptr<Arion> arion, ADDR addr, size_t sz, void *user_data)>;
59using MEM_HOOK_CALLBACK = std::function<bool(std::shared_ptr<Arion> arion, uc_mem_type type, uint64_t addr, int size,
60 int64_t val, void *user_data)>;
68using EDGE_HOOK_CALLBACK = std::function<void(std::shared_ptr<Arion> arion, uc_tb *cur, uc_tb *prev, void *user_data)>;
78using TCG_HOOK_CALLBACK = std::function<void(std::shared_ptr<Arion> arion, uint64_t addr, uint64_t arg1, uint64_t arg2,
79 int size, void *user_data)>;
89using TLB_HOOK_CALLBACK = std::function<bool(std::shared_ptr<Arion> arion, uint64_t addr, uc_mem_type type,
90 uc_tlb_entry *result, void *user_data)>;
98 std::function<void(std::shared_ptr<Arion> arion, std::shared_ptr<Arion> child, void *user_data)>;
108using SYSCALL_HOOK_CALLBACK = std::function<void(std::shared_ptr<Arion> arion, uint64_t sysno,
109 std::vector<SYS_PARAM> params, bool *handled, void *user_data)>;
114
140
142extern std::map<ARION_HOOK_TYPE, uc_hook_type> ARION_UC_HOOK_TYPES;
144extern std::map<ARION_HOOK_TYPE, void *> ARION_UC_HOOK_FUNCS;
145
164
184
191void arion_intr_hook(uc_engine *uc, uint32_t intno, void *user_data);
197void arion_insn_hook(uc_engine *uc, void *user_data);
205void arion_code_hook(uc_engine *uc, uint64_t address, uint32_t size, void *user_data);
213void arion_block_hook(uc_engine *uc, uint64_t address, uint32_t size, void *user_data);
224bool arion_mem_read_unmapped_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val,
225 void *user_data);
236bool arion_mem_write_unmapped_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val,
237 void *user_data);
248bool arion_mem_fetch_unmapped_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val,
249 void *user_data);
260bool arion_mem_read_prot_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val, void *user_data);
271bool arion_mem_write_prot_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val,
272 void *user_data);
283bool arion_mem_fetch_prot_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val,
284 void *user_data);
295bool arion_mem_read_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val, void *user_data);
306bool arion_mem_write_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val, void *user_data);
307
318bool arion_mem_fetch_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val, void *user_data);
329bool arion_mem_read_after_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val,
330 void *user_data);
337bool arion_insn_invalid_hook(uc_engine *uc, void *user_data);
345void arion_edge_generated_hook(uc_engine *uc, uc_tb *cur, uc_tb *prev, void *user_data);
355void arion_tcg_opcode_hook(uc_engine *uc, uint64_t addr, uint64_t arg1, uint64_t arg2, int size, void *user_data);
365bool arion_tlb_fill_hook(uc_engine *uc, uint64_t addr, uc_mem_type type, uc_tlb_entry *result, void *user_data);
366
369{
370 private:
372 std::weak_ptr<Arion> arion;
374 uc_engine *uc;
376 HOOK_ID curr_id = 1;
378 std::map<HOOK_ID, std::shared_ptr<ARION_HOOK>> hooks;
380 std::stack<HOOK_ID> free_hook_ids;
397 template <typename... UcParams>
398 HOOK_ID hook_uc(ARION_HOOK_TYPE type, HOOK_CALLBACK callback, void *user_data, ADDR start = 0,
399 ADDR end = ARION_MAX_U64, UcParams... uc_params);
407 HOOK_ID hook_arion(ARION_HOOK_TYPE type, HOOK_CALLBACK callback, void *user_data);
408
409 public:
414 HooksManager(std::weak_ptr<Arion> arion);
424 static std::unique_ptr<HooksManager> initialize(std::weak_ptr<Arion> arion);
434 void *user_data = nullptr);
444 HOOK_ID ARION_EXPORT hook_insn(NO_PARAM_HOOK_CALLBACK callback, uint64_t insn, ADDR start = 0,
445 ADDR end = ARION_MAX_U64, void *user_data = nullptr);
455 void *user_data = nullptr);
463 HOOK_ID ARION_EXPORT hook_addr(ADDR_SZ_HOOK_CALLBACK callback, ADDR addr, void *user_data = nullptr);
473 void *user_data = nullptr);
483 void *user_data = nullptr);
493 void *user_data = nullptr);
503 void *user_data = nullptr);
513 void *user_data = nullptr);
523 void *user_data = nullptr);
533 void *user_data = nullptr);
543 void *user_data = nullptr);
553 void *user_data = nullptr);
563 void *user_data = nullptr);
573 void *user_data = nullptr);
583 ADDR end = ARION_MAX_U64, void *user_data = nullptr);
594 void *user_data = nullptr);
605 HOOK_ID ARION_EXPORT hook_tcg_opcode(TCG_HOOK_CALLBACK callback, uint64_t aux1, uint64_t aux2, ADDR start = 0,
606 ADDR end = ARION_MAX_U64, void *user_data = nullptr);
616 void *user_data = nullptr);
623 HOOK_ID ARION_EXPORT hook_fork(PROCESS_HOOK_CALLBACK callback, void *user_data = nullptr);
630 HOOK_ID ARION_EXPORT hook_execve(PROCESS_HOOK_CALLBACK callback, void *user_data = nullptr);
637 HOOK_ID ARION_EXPORT hook_syscall(SYSCALL_HOOK_CALLBACK callback, void *user_data = nullptr);
647
654 template <typename... HookParams> void trigger_arion_hook(ARION_HOOK_TYPE type, HookParams... params)
655 {
656 for (auto &hook : this->hooks)
657 {
658 if (hook.second->type == type)
659 {
660 HOOK_CALLBACK &callback = hook.second->param->callback;
661 std::shared_ptr<Arion> arion = hook.second->param->arion.lock();
662 if (!arion)
664 void *user_data = hook.second->param->user_data;
665
666 std::visit(
667 [&](auto &&cb) {
668 using CallbackType = std::decay_t<decltype(cb)>;
669 if constexpr (std::is_invocable_v<CallbackType, std::shared_ptr<Arion>, HookParams..., void *>)
670 cb(arion, params..., user_data);
671 else
673 },
674 callback);
675 }
676 }
677 }
678};
679
680}; // namespace arion
681
682#endif // ARION_HOOKS_MANAGER_HPP
This class purpose is to manage user-defined Arion hooks including hook creation, deletion,...
Definition hooks_manager.hpp:369
HOOK_ID hook_mem_read_after(MEM_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
HooksManager(std::weak_ptr< Arion > arion)
HOOK_ID hook_insn(NO_PARAM_HOOK_CALLBACK callback, uint64_t insn, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
HOOK_ID hook_mem_write_unmapped(MEM_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
HOOK_ID hook_intr(U32_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
HOOK_ID hook_mem_read_prot(MEM_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
void unhook(HOOK_ID hook_id)
HOOK_ID hook_insn_invalid(NO_PARAM_BOOL_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
HOOK_ID hook_tcg_opcode(TCG_HOOK_CALLBACK callback, uint64_t aux1, uint64_t aux2, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
HOOK_ID hook_block(ADDR_SZ_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
HOOK_ID hook_mem_fetch_unmapped(MEM_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
void trigger_arion_hook(ARION_HOOK_TYPE type, HookParams... params)
Definition hooks_manager.hpp:654
std::stack< HOOK_ID > free_hook_ids
A stack of hook IDs that got deleted and that can be reused.
Definition hooks_manager.hpp:380
HOOK_ID hook_mem_write(MEM_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
HOOK_ID hook_syscall(SYSCALL_HOOK_CALLBACK callback, void *user_data=nullptr)
HOOK_ID hook_addr(ADDR_SZ_HOOK_CALLBACK callback, ADDR addr, void *user_data=nullptr)
HOOK_ID hook_uc(ARION_HOOK_TYPE type, HOOK_CALLBACK callback, void *user_data, ADDR start=0, ADDR end=ARION_MAX_U64, UcParams... uc_params)
HOOK_ID hook_mem_write_prot(MEM_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
HOOK_ID hook_mem_fetch_prot(MEM_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
HOOK_ID hook_fork(PROCESS_HOOK_CALLBACK callback, void *user_data=nullptr)
std::map< HOOK_ID, std::shared_ptr< ARION_HOOK > > hooks
A map identifying an Arion hook given its ID.
Definition hooks_manager.hpp:378
HOOK_ID hook_mem_read_unmapped(MEM_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
HOOK_ID hook_code(ADDR_SZ_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
std::weak_ptr< Arion > arion
The Arion instance associated with this instance.
Definition hooks_manager.hpp:372
HOOK_ID hook_mem_read(MEM_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
static std::unique_ptr< HooksManager > initialize(std::weak_ptr< Arion > arion)
HOOK_ID hook_edge_generated(EDGE_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
HOOK_ID hook_execve(PROCESS_HOOK_CALLBACK callback, void *user_data=nullptr)
HOOK_ID hook_tlb_fill(TLB_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
HOOK_ID hook_arion(ARION_HOOK_TYPE type, HOOK_CALLBACK callback, void *user_data)
HOOK_ID hook_mem_fetch(MEM_HOOK_CALLBACK callback, ADDR start=0, ADDR end=ARION_MAX_U64, void *user_data=nullptr)
uc_engine * uc
The Unicorn engine associated with this instance.
Definition hooks_manager.hpp:374
Thrown when attempting to use an expired weak_ptr.
Definition global_excepts.hpp:85
Thrown when the parameters passed to a hook are invalid.
Definition global_excepts.hpp:493
#define ARION_EXPORT
Defines which symbols should be exported from the library.
Definition global_defs.hpp:13
#define ARION_MAX_U64
Maximum number for an unsigned 64-bit integer.
Definition global_defs.hpp:27
Definition arch_x86-64.hpp:11
std::function< void(std::shared_ptr< Arion > arion, uint64_t addr, uint64_t arg1, uint64_t arg2, int size, void *user_data)> TCG_HOOK_CALLBACK
Definition hooks_manager.hpp:79
std::map< ARION_HOOK_TYPE, uc_hook_type > ARION_UC_HOOK_TYPES
A map identifying a Unicorn hook type given its associated Arion hook type.
void arion_code_hook(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
std::function< void(std::shared_ptr< Arion > arion, uc_tb *cur, uc_tb *prev, void *user_data)> EDGE_HOOK_CALLBACK
Definition hooks_manager.hpp:68
bool arion_mem_read_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val, void *user_data)
std::function< void(std::shared_ptr< Arion > arion, void *user_data)> NO_PARAM_HOOK_CALLBACK
Definition hooks_manager.hpp:26
bool arion_mem_fetch_prot_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val, void *user_data)
std::function< bool(std::shared_ptr< Arion > arion, uint64_t addr, uc_mem_type type, uc_tlb_entry *result, void *user_data)> TLB_HOOK_CALLBACK
Definition hooks_manager.hpp:90
void arion_intr_hook(uc_engine *uc, uint32_t intno, void *user_data)
void arion_tcg_opcode_hook(uc_engine *uc, uint64_t addr, uint64_t arg1, uint64_t arg2, int size, void *user_data)
uint64_t ADDR
Identifies a memory address.
Definition global_defs.hpp:36
std::function< bool(std::shared_ptr< Arion > arion, void *user_data)> NO_PARAM_BOOL_HOOK_CALLBACK
Definition hooks_manager.hpp:33
std::function< void(std::shared_ptr< Arion > arion, std::shared_ptr< Arion > child, void *user_data)> PROCESS_HOOK_CALLBACK
Definition hooks_manager.hpp:98
uint64_t HOOK_ID
ID associated with a hook when created.
Definition hooks_manager.hpp:19
void arion_insn_hook(uc_engine *uc, void *user_data)
std::function< void(std::shared_ptr< Arion > arion, uint64_t sysno, std::vector< SYS_PARAM > params, bool *handled, void *user_data)> SYSCALL_HOOK_CALLBACK
Definition hooks_manager.hpp:109
bool arion_mem_read_prot_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val, void *user_data)
std::function< void(std::shared_ptr< Arion > arion, ADDR addr, size_t sz, void *user_data)> ADDR_SZ_HOOK_CALLBACK
Definition hooks_manager.hpp:48
void arion_edge_generated_hook(uc_engine *uc, uc_tb *cur, uc_tb *prev, void *user_data)
bool arion_mem_read_after_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val, void *user_data)
bool arion_mem_write_unmapped_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val, void *user_data)
bool arion_insn_invalid_hook(uc_engine *uc, void *user_data)
void arion_block_hook(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
bool arion_mem_read_unmapped_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val, void *user_data)
bool arion_mem_fetch_unmapped_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val, void *user_data)
std::map< ARION_HOOK_TYPE, void * > ARION_UC_HOOK_FUNCS
A map identifying a hook function given its associated Arion hook type.
bool arion_mem_write_prot_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val, void *user_data)
ARION_HOOK_TYPE
Types for Arion hooks.
Definition hooks_manager.hpp:117
@ SYSCALL_HOOK
Triggered on system call invocation (before or after handling).
Definition hooks_manager.hpp:138
@ TLB_FILL_HOOK
Triggered when the TLB is filled or a translation lookup occurs.
Definition hooks_manager.hpp:135
@ INSN_INVALID_HOOK
Triggered when an invalid or unimplemented instruction is encountered.
Definition hooks_manager.hpp:132
@ MEM_READ_HOOK
Triggered on every valid memory read access.
Definition hooks_manager.hpp:128
@ INTR_HOOK
Triggered when an interrupt occurs (e.g., software or hardware interrupt).
Definition hooks_manager.hpp:118
@ EXECVE_HOOK
Triggered when a process performs an execve-like operation (program replacement).
Definition hooks_manager.hpp:137
@ MEM_WRITE_HOOK
Triggered on every valid memory write access.
Definition hooks_manager.hpp:129
@ CODE_HOOK
Triggered when code execution reaches a specified address or range.
Definition hooks_manager.hpp:120
@ TCG_OPCODE_HOOK
Triggered for each TCG opcode during translation (for instrumentation or analysis).
Definition hooks_manager.hpp:134
@ MEM_FETCH_PROT_HOOK
Triggered when fetching instructions from a non-executable or protected region.
Definition hooks_manager.hpp:127
@ EDGE_GENERATED_HOOK
Triggered when a new control-flow edge (TB → TB) is generated during emulation.
Definition hooks_manager.hpp:133
@ MEM_READ_UNMAPPED_HOOK
Triggered on a memory read from an unmapped region.
Definition hooks_manager.hpp:122
@ MEM_WRITE_UNMAPPED_HOOK
Triggered on a memory write to an unmapped region.
Definition hooks_manager.hpp:123
@ MEM_FETCH_HOOK
Triggered when fetching instructions from valid mapped memory.
Definition hooks_manager.hpp:130
@ MEM_READ_AFTER_HOOK
Triggered after a memory read operation completes (e.g., for tracing or logging).
Definition hooks_manager.hpp:131
@ MEM_FETCH_UNMAPPED_HOOK
Triggered when fetching instructions from an unmapped region.
Definition hooks_manager.hpp:124
@ MEM_WRITE_PROT_HOOK
Triggered on a memory write violating protection flags (e.g., read-only region).
Definition hooks_manager.hpp:126
@ INSN_HOOK
Triggered before or after executing a specific instruction.
Definition hooks_manager.hpp:119
@ FORK_HOOK
Triggered when a process forks or clones (child Arion instance is created).
Definition hooks_manager.hpp:136
@ BLOCK_HOOK
Triggered at the start of a new basic block or translation block (TB).
Definition hooks_manager.hpp:121
@ MEM_READ_PROT_HOOK
Triggered on a memory read violating protection flags (e.g., non-readable region).
Definition hooks_manager.hpp:125
std::function< void(std::shared_ptr< Arion > arion, uint32_t val, void *user_data)> U32_HOOK_CALLBACK
Definition hooks_manager.hpp:40
bool arion_mem_fetch_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val, void *user_data)
bool arion_tlb_fill_hook(uc_engine *uc, uint64_t addr, uc_mem_type type, uc_tlb_entry *result, void *user_data)
bool arion_mem_write_hook(uc_engine *uc, uc_mem_type access, uint64_t addr, int size, int64_t val, void *user_data)
std::variant< NO_PARAM_HOOK_CALLBACK, NO_PARAM_BOOL_HOOK_CALLBACK, U32_HOOK_CALLBACK, ADDR_SZ_HOOK_CALLBACK, MEM_HOOK_CALLBACK, EDGE_HOOK_CALLBACK, TCG_HOOK_CALLBACK, TLB_HOOK_CALLBACK, PROCESS_HOOK_CALLBACK, SYSCALL_HOOK_CALLBACK > HOOK_CALLBACK
Variant type that represents any possible hook callback type supported by Arion.
Definition hooks_manager.hpp:113
std::function< bool(std::shared_ptr< Arion > arion, uc_mem_type type, uint64_t addr, int size, int64_t val, void *user_data)> MEM_HOOK_CALLBACK
Definition hooks_manager.hpp:60
This structure is placed in the Unicorn user_data parameter of hooks.
Definition hooks_manager.hpp:148
ARION_HOOK_PARAM(std::weak_ptr< Arion > arion, HOOK_CALLBACK callback, void *user_data)
Definition hooks_manager.hpp:161
void * user_data
Optional user-defined data passed to the hook.
Definition hooks_manager.hpp:154
HOOK_CALLBACK callback
A user-defined callback for the hook.
Definition hooks_manager.hpp:152
std::weak_ptr< Arion > arion
Arion instance that triggered the hook.
Definition hooks_manager.hpp:150
This structure holds information about an Arion hook.
Definition hooks_manager.hpp:167
ARION_HOOK(ARION_HOOK_TYPE type, uc_hook uc_id, ARION_HOOK_PARAM *param)
Definition hooks_manager.hpp:181
ARION_HOOK_TYPE type
Arion type for the hook.
Definition hooks_manager.hpp:169
uc_hook uc_id
Unicorn hook id associated with this Arion hook.
Definition hooks_manager.hpp:171
ARION_HOOK_PARAM * param
A structure holding data to be passed to the Arion hook when its associated Unicorn hook gets trigger...
Definition hooks_manager.hpp:173