1
0
mirror of https://github.com/0O0o0oOoO00/Alas.git synced 2026-05-22 16:29:29 +08:00

add: migrate source code of luahook

This commit is contained in:
0O0o0oOoO00
2025-11-01 00:23:46 +08:00
parent 753e676152
commit 41505d6e91
520 changed files with 154475 additions and 0 deletions

View File

@@ -0,0 +1,172 @@
#include "dobby/dobby_internal.h"
#include "PlatformUnifiedInterface/ExecMemory/ClearCacheTool.h"
#include <unistd.h>
#include <mach/mach.h>
#include "UnifiedInterface/platform-darwin/mach_vm.h"
#if defined(__APPLE__)
#include <dlfcn.h>
#include <mach/vm_statistics.h>
#endif
#define KERN_RETURN_ERROR(kr, failure) \
do { \
if (kr != KERN_SUCCESS) { \
ERROR_LOG("mach error: %s", mach_error_string(kr)); \
return failure; \
} \
} while (0);
#include <sys/mman.h>
#if defined(TARGET_ARCH_ARM64)
#define SYS_mprotect 74
int mprotect_impl(void *addr, size_t len, int prot) {
int ret = 0;
__asm__ __volatile__("mov x16, %[_SYS_mprotect]\n"
"svc 0x80\n"
"mov %w[_ret], w0\n"
"add %w[_ret], %w[_ret], #0x0\n"
: [_ret] "=r"(ret)
: [_SYS_mprotect] "n"(SYS_mprotect)
:);
return ret;
}
#endif
PUBLIC int DobbyCodePatch(void *address, uint8_t *buffer, uint32_t buffer_size) {
if (address == nullptr || buffer == nullptr || buffer_size == 0) {
ERROR_LOG("invalid argument");
return -1;
}
size_t page_size = PAGE_SIZE;
addr_t patch_page = ALIGN_FLOOR(address, page_size);
// cross over page
if ((addr_t)address + buffer_size > patch_page + page_size) {
void *address_a = address;
uint8_t *buffer_a = buffer;
uint32_t buffer_size_a = (patch_page + page_size - (addr_t)address);
auto ret = DobbyCodePatch(address_a, buffer_a, buffer_size_a);
if (ret == -1) {
return ret;
}
void *address_b = (void *)((addr_t)address + buffer_size_a);
uint8_t *buffer_b = buffer + buffer_size_a;
uint32_t buffer_size_b = buffer_size - buffer_size_a;
ret = DobbyCodePatch(address_b, buffer_b, buffer_size_b);
return ret;
}
addr_t remap_dest_page = patch_page;
mach_vm_address_t remap_dummy_page = 0;
auto self_task = mach_task_self();
kern_return_t kr;
int orig_prot = 0;
int orig_max_prot = 0;
int share_mode = 0;
int is_enable_remap = -1;
if (is_enable_remap == -1) {
auto get_region_info = [&](addr_t region_start) -> void {
vm_region_submap_info_64 region_submap_info;
mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
mach_vm_address_t addr = region_start;
mach_vm_size_t size = 0;
natural_t depth = 0;
while (1) {
kr = mach_vm_region_recurse(mach_task_self(), (mach_vm_address_t *)&addr, (mach_vm_size_t *)&size, &depth,
(vm_region_recurse_info_t)&region_submap_info, &count);
if (region_submap_info.is_submap) {
depth++;
} else {
orig_prot = region_submap_info.protection;
orig_max_prot = region_submap_info.max_protection;
share_mode = region_submap_info.share_mode;
return;
}
}
};
get_region_info(remap_dest_page);
if (orig_max_prot != 5 && share_mode != 2) {
is_enable_remap = 1;
} else {
is_enable_remap = 0;
DEBUG_LOG("code patch %p won't use remap", address);
}
}
if (is_enable_remap == 1) {
addr_t remap_dummy_page = 0;
{
kr = mach_vm_allocate(self_task, (mach_vm_address_t *)&remap_dummy_page, page_size, VM_FLAGS_ANYWHERE);
KERN_RETURN_ERROR(kr, -1);
memcpy((void *)remap_dummy_page, (void *)patch_page, page_size);
int offset = (int)((addr_t)address - patch_page);
memcpy((void *)(remap_dummy_page + offset), buffer, buffer_size);
kr = mach_vm_protect(self_task, remap_dummy_page, page_size, false, VM_PROT_READ | VM_PROT_EXECUTE);
KERN_RETURN_ERROR(kr, -1);
}
vm_prot_t prot, max_prot;
kr = mach_vm_remap(self_task, (mach_vm_address_t *)&remap_dest_page, page_size, 0,
VM_FLAGS_OVERWRITE | VM_FLAGS_FIXED, self_task, remap_dummy_page, true, &prot, &max_prot,
VM_INHERIT_COPY);
KERN_RETURN_ERROR(kr, -1);
kr = mach_vm_deallocate(self_task, remap_dummy_page, page_size);
KERN_RETURN_ERROR(kr, -1);
} else {
if (0) {
{
auto kr = mach_vm_allocate(self_task, &remap_dummy_page, page_size, VM_FLAGS_ANYWHERE);
KERN_RETURN_ERROR(kr, -1);
kr = mach_vm_deallocate(self_task, remap_dummy_page, page_size);
KERN_RETURN_ERROR(kr, -1);
}
vm_prot_t prot, max_prot;
kr = mach_vm_remap(self_task, &remap_dummy_page, page_size, 0, VM_FLAGS_ANYWHERE, self_task, remap_dest_page,
false, &prot, &max_prot, VM_INHERIT_SHARE);
KERN_RETURN_ERROR(kr, -1);
kr = mach_vm_protect(self_task, remap_dummy_page, page_size, false, VM_PROT_READ | VM_PROT_WRITE);
// the kr always return KERN_PROTECTION_FAILURE
kr = KERN_PROTECTION_FAILURE;
memcpy((void *)(remap_dummy_page + ((uint64_t)address - remap_dest_page)), buffer, buffer_size);
}
static __typeof(vm_protect) *vm_protect_impl = nullptr;
if (vm_protect_impl == nullptr) {
vm_protect_impl = (__typeof(vm_protect) *)DobbySymbolResolver("dyld", "vm_protect");
if (vm_protect_impl == nullptr) {
vm_protect_impl = (__typeof(vm_protect) *)DobbySymbolResolver("libsystem_kernel.dylib", "_vm_protect");
}
vm_protect_impl = (__typeof(vm_protect) *)pac_sign((void *)vm_protect_impl);
}
{
kr = vm_protect_impl(self_task, remap_dest_page, page_size, false, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY);
KERN_RETURN_ERROR(kr, -1);
memcpy((void *)(patch_page + ((uint64_t)address - remap_dest_page)), buffer, buffer_size);
kr = vm_protect_impl(self_task, remap_dest_page, page_size, false, orig_prot);
KERN_RETURN_ERROR(kr, -1);
}
}
ClearCache(address, (void *)((addr_t)address + buffer_size));
return 0;
}