detour_detach + some setters
This commit is contained in:
parent
e04585377a
commit
ade0920e54
2 changed files with 139 additions and 1 deletions
|
|
@ -9,7 +9,7 @@
|
|||
#define DETOURS_ARM64
|
||||
#define DETOURS_64BIT
|
||||
#else
|
||||
#error Unsupported architecture (arm64)
|
||||
#error Unsupported architecture (supported: arm64)
|
||||
#endif
|
||||
|
||||
#include "detours_internal.h"
|
||||
|
|
@ -640,6 +640,9 @@ mach_error_t detour_manage_thread(thread_t thread)
|
|||
return err_none;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Attach/Detach
|
||||
|
||||
mach_error_t detour_attach(detour_func_t* inout_pointer, detour_func_t detour)
|
||||
{
|
||||
return detour_attach_ex(inout_pointer, detour, nullptr, nullptr, nullptr);
|
||||
|
|
@ -898,3 +901,133 @@ mach_error_t detour_attach_ex(detour_func_t* inout_pointer, detour_func_t detour
|
|||
|
||||
return err_none;
|
||||
}
|
||||
|
||||
mach_error_t detour_detach(detour_func_t* inout_pointer, detour_func_t detour)
|
||||
{
|
||||
if (s_transaction_thread != mach_thread_self()) {
|
||||
return detour_err_wrong_thread;
|
||||
}
|
||||
|
||||
// If any of the pending operations failed, then we don't need to do this.
|
||||
if (s_pending_error != err_none) {
|
||||
return s_pending_error;
|
||||
}
|
||||
|
||||
if (!detour) {
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
if (!inout_pointer) {
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
if (!(*inout_pointer)) {
|
||||
s_pending_error = KERN_INVALID_ARGUMENT;
|
||||
s_pending_error_pointer = inout_pointer;
|
||||
DETOUR_BREAK();
|
||||
return s_pending_error;
|
||||
}
|
||||
|
||||
mach_error_t error = err_none;
|
||||
|
||||
detour_operation* op = calloc(1, sizeof(detour_operation));
|
||||
if (!op) {
|
||||
error = KERN_RESOURCE_SHORTAGE;
|
||||
fail:
|
||||
s_pending_error = error;
|
||||
DETOUR_BREAK();
|
||||
stop:
|
||||
free(op);
|
||||
// ReSharper disable once CppDFAUnusedValue
|
||||
op = nullptr;
|
||||
s_pending_error_pointer = inout_pointer;
|
||||
return error;
|
||||
}
|
||||
|
||||
detour_trampoline* trampoline = (detour_trampoline*)internal_detour_skip_jmp(*inout_pointer);
|
||||
detour = internal_detour_skip_jmp(detour);
|
||||
|
||||
// Verify that Trampoline is in place.
|
||||
const int32_t restore_code_size = trampoline->restore_code_size;
|
||||
uint8_t* target = trampoline->ptr_remain - restore_code_size;
|
||||
if (restore_code_size == 0 || restore_code_size > sizeof(trampoline->code)) {
|
||||
error = KERN_FAILURE;
|
||||
if (s_ignore_too_small) {
|
||||
goto stop;
|
||||
} else {
|
||||
DETOUR_BREAK();
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (trampoline->ptr_detour != detour) {
|
||||
error = KERN_FAILURE;
|
||||
if (s_ignore_too_small) {
|
||||
goto stop;
|
||||
} else {
|
||||
DETOUR_BREAK();
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
const mach_port_t port = mach_task_self();
|
||||
|
||||
vm_region_submap_short_info_data_64_t region_info;
|
||||
{
|
||||
mach_vm_address_t region_addr = (mach_vm_address_t)target;
|
||||
mach_vm_size_t region_size = 0;
|
||||
natural_t nesting_depth = 99999;
|
||||
mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
|
||||
error = mach_vm_region_recurse(port, ®ion_addr, ®ion_size, &nesting_depth, (vm_region_recurse_info_t)®ion_info, &count);
|
||||
if (error != err_none) {
|
||||
DETOUR_BREAK();
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
const vm_prot_t old_perm = region_info.protection;
|
||||
|
||||
error = mach_vm_protect(port, (mach_vm_address_t)target, PAGE_SIZE, false, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY);
|
||||
if (error != err_none) {
|
||||
DETOUR_BREAK();
|
||||
goto fail;
|
||||
}
|
||||
|
||||
op->kind = detour_operation_kind_detach;
|
||||
op->pointer = (uint8_t**)inout_pointer;
|
||||
op->trampoline = trampoline;
|
||||
op->target = target;
|
||||
op->perm = old_perm;
|
||||
op->next = s_pending_operations_head;
|
||||
s_pending_operations_head = op;
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// API Setters
|
||||
|
||||
bool detour_set_ignore_too_small(const bool value)
|
||||
{
|
||||
const bool previous = s_ignore_too_small;
|
||||
s_ignore_too_small = value;
|
||||
return previous;
|
||||
}
|
||||
|
||||
bool detour_set_retain_regions(const bool value)
|
||||
{
|
||||
const bool previous = s_retain_regions;
|
||||
s_retain_regions = value;
|
||||
return previous;
|
||||
}
|
||||
|
||||
void* detour_set_system_region_lower_bound(void* value)
|
||||
{
|
||||
void* previous = s_system_region_lower_bound;
|
||||
s_system_region_lower_bound = value;
|
||||
return previous;
|
||||
}
|
||||
|
||||
void* detour_set_system_region_upper_bound(void* value)
|
||||
{
|
||||
void* previous = s_system_region_upper_bound;
|
||||
s_system_region_upper_bound = value;
|
||||
return previous;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue