added test
This commit is contained in:
parent
ade0920e54
commit
aaad260259
4 changed files with 94 additions and 42 deletions
|
|
@ -14,7 +14,15 @@ add_library(mach_detours SHARED
|
||||||
src/arm64/detours_arm64.h
|
src/arm64/detours_arm64.h
|
||||||
src/arm64/detours_arm64_disasm.cpp
|
src/arm64/detours_arm64_disasm.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(mach_detours
|
target_include_directories(mach_detours
|
||||||
PUBLIC "include"
|
PUBLIC include
|
||||||
PRIVATE "src")
|
PRIVATE src
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
add_executable(mach_detours_sample
|
||||||
|
sample/main.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries(mach_detours_sample
|
||||||
|
PRIVATE mach_detours
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,10 @@
|
||||||
#ifndef MACH_DETOURS_H
|
#ifndef MACH_DETOURS_H
|
||||||
#define MACH_DETOURS_H
|
#define MACH_DETOURS_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <mach/error.h>
|
#include <mach/error.h>
|
||||||
#include <mach/mach_types.h>
|
#include <mach/mach_types.h>
|
||||||
|
|
||||||
|
|
@ -31,4 +35,8 @@ bool detour_set_retain_regions(bool value);
|
||||||
void* detour_set_system_region_lower_bound(void* value);
|
void* detour_set_system_region_lower_bound(void* value);
|
||||||
void* detour_set_system_region_upper_bound(void* value);
|
void* detour_set_system_region_upper_bound(void* value);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // MACH_DETOURS_H
|
#endif // MACH_DETOURS_H
|
||||||
|
|
|
||||||
34
sample/main.cpp
Normal file
34
sample/main.cpp
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright (c) Lysann Tranvouez. All rights reserved.
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "mach_detours.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
char* (*real_strerror)(int errno) = strerror;
|
||||||
|
|
||||||
|
static int counter = 0;
|
||||||
|
|
||||||
|
char* my_strerror(const int errno)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
return real_strerror(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[])
|
||||||
|
{
|
||||||
|
counter = 0;
|
||||||
|
strerror(0);
|
||||||
|
assert(counter == 0);
|
||||||
|
|
||||||
|
detour_transaction_begin();
|
||||||
|
detour_attach(reinterpret_cast<detour_func_t*>(&real_strerror), reinterpret_cast<detour_func_t>(my_strerror));
|
||||||
|
detour_transaction_commit();
|
||||||
|
|
||||||
|
assert(counter == 0);
|
||||||
|
strerror(0);
|
||||||
|
assert(counter == 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include "mach_detours.h"
|
#include "mach_detours.h"
|
||||||
|
|
||||||
#define DETOUR_DEBUG 1
|
#define DETOUR_DEBUG 0
|
||||||
|
|
||||||
#ifdef __arm64__
|
#ifdef __arm64__
|
||||||
#define DETOURS_ARM64
|
#define DETOURS_ARM64
|
||||||
|
|
@ -200,12 +200,11 @@ static detour_trampoline* internal_detour_alloc_trampoline(uint8_t* target)
|
||||||
// First check the default region for a valid free block.
|
// First check the default region for a valid free block.
|
||||||
if (s_default_region && s_default_region->free_list_head &&
|
if (s_default_region && s_default_region->free_list_head &&
|
||||||
s_default_region->free_list_head >= lo && s_default_region->free_list_head <= hi) {
|
s_default_region->free_list_head >= lo && s_default_region->free_list_head <= hi) {
|
||||||
|
|
||||||
found_region:
|
found_region:
|
||||||
trampoline = s_default_region->free_list_head;
|
trampoline = s_default_region->free_list_head;
|
||||||
// do a last sanity check on region.
|
// do a last sanity check on region.
|
||||||
if (trampoline < lo || trampoline > hi) {
|
if (trampoline < lo || trampoline > hi) {
|
||||||
raise(SIGTRAP);
|
DETOUR_BREAK();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
s_default_region->free_list_head = (detour_trampoline*)trampoline->ptr_remain;
|
s_default_region->free_list_head = (detour_trampoline*)trampoline->ptr_remain;
|
||||||
|
|
@ -522,9 +521,8 @@ mach_error_t detour_transaction_commit_ex(detour_func_t** out_failed_target)
|
||||||
if (pc >= targetAddr && pc < targetAddr + op->trampoline->restore_code_size) {
|
if (pc >= targetAddr && pc < targetAddr + op->trampoline->restore_code_size) {
|
||||||
uintptr_t new_pc = (uintptr_t)op->trampoline;
|
uintptr_t new_pc = (uintptr_t)op->trampoline;
|
||||||
new_pc += internal_detour_align_from_target(op->trampoline, pc - targetAddr);
|
new_pc += internal_detour_align_from_target(op->trampoline, pc - targetAddr);
|
||||||
printf("detours: thread %u was at 0x%" PRIXPTR ", moved to 0x%" PRIXPTR "\n", thread->thread,
|
DETOUR_TRACE(("detours: thread %u was at 0x%" PRIXPTR ", moved to 0x%" PRIXPTR "\n",
|
||||||
pc,
|
thread->thread, pc, new_pc));
|
||||||
new_pc);
|
|
||||||
arm_thread_state64_set_pc_fptr(threadState, new_pc);
|
arm_thread_state64_set_pc_fptr(threadState, new_pc);
|
||||||
thread_set_state(thread->thread, ARM_THREAD_STATE64, (thread_state_t)&threadState,
|
thread_set_state(thread->thread, ARM_THREAD_STATE64, (thread_state_t)&threadState,
|
||||||
ARM_THREAD_STATE64_COUNT);
|
ARM_THREAD_STATE64_COUNT);
|
||||||
|
|
@ -536,9 +534,8 @@ mach_error_t detour_transaction_commit_ex(detour_func_t** out_failed_target)
|
||||||
if (pc >= trampAddr && pc < trampAddr + sizeof(*op->trampoline)) {
|
if (pc >= trampAddr && pc < trampAddr + sizeof(*op->trampoline)) {
|
||||||
uintptr_t new_pc = (uintptr_t)op->target;
|
uintptr_t new_pc = (uintptr_t)op->target;
|
||||||
new_pc += internal_detour_align_from_trampoline(op->trampoline, pc - trampAddr);
|
new_pc += internal_detour_align_from_trampoline(op->trampoline, pc - trampAddr);
|
||||||
printf("detours: thread %u was at 0x%" PRIXPTR ", moved to 0x%" PRIXPTR "\n", thread->thread,
|
DETOUR_TRACE(("detours: thread %u was at 0x%" PRIXPTR ", moved to 0x%" PRIXPTR "\n",
|
||||||
pc,
|
thread->thread, pc, new_pc));
|
||||||
new_pc);
|
|
||||||
arm_thread_state64_set_pc_fptr(threadState, new_pc);
|
arm_thread_state64_set_pc_fptr(threadState, new_pc);
|
||||||
thread_set_state(thread->thread, ARM_THREAD_STATE64, (thread_state_t)&threadState,
|
thread_set_state(thread->thread, ARM_THREAD_STATE64, (thread_state_t)&threadState,
|
||||||
ARM_THREAD_STATE64_COUNT);
|
ARM_THREAD_STATE64_COUNT);
|
||||||
|
|
@ -648,7 +645,8 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
if (out_real_trampoline) {
|
if (out_real_trampoline) {
|
||||||
*out_real_trampoline = nullptr;
|
*out_real_trampoline = nullptr;
|
||||||
|
|
@ -844,7 +842,8 @@ mach_error_t detour_attach_ex(detour_func_t* inout_pointer, detour_func_t detour
|
||||||
|
|
||||||
trampoline_code = trampoline->code + trampoline->code_size;
|
trampoline_code = trampoline->code + trampoline->code_size;
|
||||||
|
|
||||||
trampoline_code = internal_detour_gen_jmp_immediate(trampoline_code, &trampoline_code_limit, trampoline->ptr_remain);
|
trampoline_code =
|
||||||
|
internal_detour_gen_jmp_immediate(trampoline_code, &trampoline_code_limit, trampoline->ptr_remain);
|
||||||
trampoline_code = internal_detour_gen_brk(trampoline_code, trampoline_code_limit);
|
trampoline_code = internal_detour_gen_brk(trampoline_code, trampoline_code_limit);
|
||||||
UNUSED_VARIABLE(trampoline_code);
|
UNUSED_VARIABLE(trampoline_code);
|
||||||
|
|
||||||
|
|
@ -857,7 +856,8 @@ mach_error_t detour_attach_ex(detour_func_t* inout_pointer, detour_func_t detour
|
||||||
mach_vm_size_t region_size = 0;
|
mach_vm_size_t region_size = 0;
|
||||||
natural_t nesting_depth = 99999;
|
natural_t nesting_depth = 99999;
|
||||||
mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
|
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);
|
error = mach_vm_region_recurse(port, ®ion_addr, ®ion_size, &nesting_depth,
|
||||||
|
(vm_region_recurse_info_t)®ion_info, &count);
|
||||||
if (error != err_none) {
|
if (error != err_none) {
|
||||||
DETOUR_BREAK();
|
DETOUR_BREAK();
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -976,7 +976,8 @@ mach_error_t detour_detach(detour_func_t* inout_pointer, detour_func_t detour)
|
||||||
mach_vm_size_t region_size = 0;
|
mach_vm_size_t region_size = 0;
|
||||||
natural_t nesting_depth = 99999;
|
natural_t nesting_depth = 99999;
|
||||||
mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
|
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);
|
error = mach_vm_region_recurse(port, ®ion_addr, ®ion_size, &nesting_depth,
|
||||||
|
(vm_region_recurse_info_t)®ion_info, &count);
|
||||||
if (error != err_none) {
|
if (error != err_none) {
|
||||||
DETOUR_BREAK();
|
DETOUR_BREAK();
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -984,7 +985,8 @@ mach_error_t detour_detach(detour_func_t* inout_pointer, detour_func_t detour)
|
||||||
}
|
}
|
||||||
const vm_prot_t old_perm = region_info.protection;
|
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);
|
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) {
|
if (error != err_none) {
|
||||||
DETOUR_BREAK();
|
DETOUR_BREAK();
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue