detour_detach + some setters
This commit is contained in:
parent
e04585377a
commit
ade0920e54
2 changed files with 139 additions and 1 deletions
|
|
@ -26,4 +26,9 @@ mach_error_t detour_attach(detour_func_t* inout_pointer, detour_func_t detour);
|
||||||
mach_error_t detour_attach_ex(detour_func_t* inout_pointer, detour_func_t detour, detour_func_t* out_real_trampoline, detour_func_t* out_real_target, detour_func_t* out_real_detour);
|
mach_error_t detour_attach_ex(detour_func_t* inout_pointer, detour_func_t detour, detour_func_t* out_real_trampoline, detour_func_t* out_real_target, detour_func_t* out_real_detour);
|
||||||
mach_error_t detour_detach(detour_func_t* inout_pointer, detour_func_t detour);
|
mach_error_t detour_detach(detour_func_t* inout_pointer, detour_func_t detour);
|
||||||
|
|
||||||
|
bool detour_set_ignore_too_small(bool value);
|
||||||
|
bool detour_set_retain_regions(bool value);
|
||||||
|
void* detour_set_system_region_lower_bound(void* value);
|
||||||
|
void* detour_set_system_region_upper_bound(void* value);
|
||||||
|
|
||||||
#endif // MACH_DETOURS_H
|
#endif // MACH_DETOURS_H
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
#define DETOURS_ARM64
|
#define DETOURS_ARM64
|
||||||
#define DETOURS_64BIT
|
#define DETOURS_64BIT
|
||||||
#else
|
#else
|
||||||
#error Unsupported architecture (arm64)
|
#error Unsupported architecture (supported: arm64)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "detours_internal.h"
|
#include "detours_internal.h"
|
||||||
|
|
@ -640,6 +640,9 @@ mach_error_t detour_manage_thread(thread_t thread)
|
||||||
return err_none;
|
return err_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Attach/Detach
|
||||||
|
|
||||||
mach_error_t detour_attach(detour_func_t* inout_pointer, detour_func_t detour)
|
mach_error_t detour_attach(detour_func_t* inout_pointer, detour_func_t detour)
|
||||||
{
|
{
|
||||||
return detour_attach_ex(inout_pointer, detour, nullptr, nullptr, nullptr);
|
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;
|
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