mirror of
https://github.com/NohamR/RMHook.git
synced 2026-01-11 06:58:11 +00:00
Switch to static zstd library and update build config
Replaces dynamic libzstd.1.dylib with static libzstd.a in CMakeLists.txt and updates architecture to support arm64. Adds zstd headers and static library, updates documentation and credits to reflect zstd usage, and removes unused tinyhook source files after moving headers and libraries.
This commit is contained in:
@@ -1,51 +0,0 @@
|
||||
#ifndef tinyhook_h
|
||||
#define tinyhook_h
|
||||
|
||||
#include <objc/objc-runtime.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CLASS_METHOD 0
|
||||
#define INSTANCE_METHOD 1
|
||||
|
||||
/* inline hook */
|
||||
int tiny_hook(void *function, void *destination, void **origin);
|
||||
|
||||
int tiny_insert(void *address, void *destination, bool link);
|
||||
|
||||
int tiny_insert_far(void *address, void *destination, bool link);
|
||||
|
||||
/* objective-c runtime */
|
||||
int ocrt_hook(const char *cls, const char *sel, void *destination, void **origin);
|
||||
|
||||
int ocrt_swap(const char *cls1, const char *sel1, const char *cls2, const char *sel2);
|
||||
|
||||
void *ocrt_impl(const char *cls, const char *sel, bool type);
|
||||
|
||||
Method ocrt_method(const char *cls, const char *sel, bool type);
|
||||
|
||||
/* memory access */
|
||||
int read_mem(void *destination, const void *source, size_t len);
|
||||
|
||||
int write_mem(void *destination, const void *source, size_t len);
|
||||
|
||||
/* solve symbol */
|
||||
void *symtbl_solve(uint32_t image_index, const char *symbol_name);
|
||||
|
||||
void *symexp_solve(uint32_t image_index, const char *symbol_name);
|
||||
|
||||
/* find in memory */
|
||||
// int find_code(uint32_t image_index, const unsigned char *code, size_t len, int count, void **out);
|
||||
|
||||
int find_data(void *start, void *end, const unsigned char *data, size_t len, int count, void **out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,39 +0,0 @@
|
||||
#include <mach/mach_init.h> // mach_task_self()
|
||||
#include <mach/mach_vm.h> // mach_vm_*
|
||||
#include <string.h> // memcpy()
|
||||
|
||||
#ifndef COMPACT
|
||||
#include <mach/mach_error.h> // mach_error_string()
|
||||
#include <printf.h> // fprintf()
|
||||
#endif
|
||||
|
||||
#include "../include/tinyhook.h"
|
||||
|
||||
int read_mem(void *destination, const void *source, size_t len) {
|
||||
int kr = 0;
|
||||
vm_offset_t data;
|
||||
mach_msg_type_number_t dataCnt;
|
||||
kr |= mach_vm_read(mach_task_self(), (mach_vm_address_t)source, len, &data, &dataCnt);
|
||||
memcpy((unsigned char *)destination, (unsigned char *)data, dataCnt);
|
||||
kr |= mach_vm_deallocate(mach_task_self(), data, dataCnt);
|
||||
#ifndef COMPACT
|
||||
if (kr != 0) {
|
||||
fprintf(stderr, "read_mem: %s\n", mach_error_string(kr));
|
||||
}
|
||||
#endif
|
||||
return kr;
|
||||
}
|
||||
|
||||
int write_mem(void *destination, const void *source, size_t len) {
|
||||
int kr = 0;
|
||||
kr |= mach_vm_protect(mach_task_self(), (mach_vm_address_t)destination, len, FALSE,
|
||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY);
|
||||
kr |= mach_vm_write(mach_task_self(), (mach_vm_address_t)destination, (vm_offset_t)source, len);
|
||||
kr |= mach_vm_protect(mach_task_self(), (mach_vm_address_t)destination, len, FALSE, VM_PROT_READ | VM_PROT_EXECUTE);
|
||||
#ifndef COMPACT
|
||||
if (kr != 0) {
|
||||
fprintf(stderr, "write_mem: %s\n", mach_error_string(kr));
|
||||
}
|
||||
#endif
|
||||
return kr;
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
#include <objc/runtime.h> // objc_*, ...
|
||||
|
||||
#ifndef COMPACT
|
||||
#include <mach/mach_error.h> // mach_error_string()
|
||||
#include <printf.h> // fprintf()
|
||||
#endif
|
||||
|
||||
#include "../include/tinyhook.h"
|
||||
|
||||
Method ocrt_method(const char *cls, const char *sel, bool type) {
|
||||
Method oc_method = NULL;
|
||||
Class oc_class = objc_getClass(cls);
|
||||
SEL oc_selector = sel_registerName(sel);
|
||||
if (type == CLASS_METHOD) {
|
||||
oc_method = class_getClassMethod(oc_class, oc_selector);
|
||||
} else if (type == INSTANCE_METHOD) {
|
||||
oc_method = class_getInstanceMethod(oc_class, oc_selector);
|
||||
}
|
||||
#ifndef COMPACT
|
||||
else {
|
||||
fprintf(stderr, "ocrt_method: invalid method type: %d\n", type);
|
||||
}
|
||||
#endif
|
||||
return oc_method;
|
||||
}
|
||||
|
||||
void *ocrt_impl(const char *cls, const char *sel, bool type) {
|
||||
return method_getImplementation(ocrt_method(cls, sel, type));
|
||||
}
|
||||
|
||||
static Method ensure_method(const char *cls, const char *sel);
|
||||
|
||||
int ocrt_swap(const char *cls1, const char *sel1, const char *cls2, const char *sel2) {
|
||||
Method oc_method1 = ensure_method(cls1, sel1);
|
||||
Method oc_method2 = ensure_method(cls2, sel2);
|
||||
if (oc_method1 == NULL || oc_method2 == NULL) {
|
||||
return 1;
|
||||
}
|
||||
method_exchangeImplementations(oc_method1, oc_method2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ocrt_hook(const char *cls, const char *sel, void *destination, void **origin) {
|
||||
Method oc_method = ensure_method(cls, sel);
|
||||
if (oc_method == NULL) {
|
||||
return 1;
|
||||
}
|
||||
void *origin_imp = method_setImplementation(oc_method, destination);
|
||||
if (origin != NULL) {
|
||||
*origin = origin_imp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Method ensure_method(const char *cls, const char *sel) {
|
||||
Method oc_method = ocrt_method(cls, sel, CLASS_METHOD);
|
||||
if (oc_method == NULL) {
|
||||
oc_method = ocrt_method(cls, sel, INSTANCE_METHOD);
|
||||
}
|
||||
#ifndef COMPACT
|
||||
if (oc_method == NULL) {
|
||||
fprintf(stderr, "ensure_method: method not found!\n");
|
||||
}
|
||||
#endif
|
||||
return oc_method;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
#ifndef COMPACT
|
||||
#include <printf.h> // fprintf()
|
||||
#endif
|
||||
|
||||
#include "skip/skip.h"
|
||||
|
||||
#include "../include/tinyhook.h"
|
||||
|
||||
int find_data(void *start, void *end, const unsigned char *data, size_t len, int count, void **out) {
|
||||
int matched;
|
||||
skipidx_t idx;
|
||||
skip_init(&idx, len, data);
|
||||
matched = skip_match(&idx, start, end, count, (offset_t *)out);
|
||||
skip_release(&idx);
|
||||
#ifndef COMPACT
|
||||
if (matched == 0) {
|
||||
fprintf(stderr, "find_data: data not found!\n");
|
||||
}
|
||||
#endif
|
||||
return matched;
|
||||
}
|
||||
|
||||
// int find_code(uint32_t image_index, const unsigned char *code, size_t len, int count, void **out);
|
||||
@@ -1,121 +0,0 @@
|
||||
#include <mach-o/dyld.h> // _dyld_*
|
||||
#include <mach-o/loader.h> // mach_header_64, load_command...
|
||||
#include <mach-o/nlist.h> // nlist_64
|
||||
#include <string.h> // strcmp()
|
||||
|
||||
#ifndef COMPACT
|
||||
#include <printf.h> // fprintf()
|
||||
#endif
|
||||
|
||||
#include "../../include/tinyhook.h"
|
||||
|
||||
static void *trie_query(const uint8_t *export, const char *name);
|
||||
|
||||
void *symexp_solve(uint32_t image_index, const char *symbol_name) {
|
||||
void *symbol_address = NULL;
|
||||
intptr_t image_slide = _dyld_get_image_vmaddr_slide(image_index);
|
||||
struct mach_header_64 *mh_header = (struct mach_header_64 *)_dyld_get_image_header(image_index);
|
||||
struct load_command *ld_command = (void *)mh_header + sizeof(struct mach_header_64);
|
||||
#ifndef COMPACT
|
||||
if (mh_header == NULL) {
|
||||
fprintf(stderr, "symexp_solve: image_index out of range!\n");
|
||||
}
|
||||
#endif
|
||||
struct dyld_info_command *dyldinfo_cmd = NULL;
|
||||
struct segment_command_64 *linkedit_cmd = NULL;
|
||||
for (int i = 0; i < mh_header->ncmds; i++) {
|
||||
if (ld_command->cmd == LC_SEGMENT_64) {
|
||||
const struct segment_command_64 *segment = (struct segment_command_64 *)ld_command;
|
||||
if (strcmp(segment->segname, "__LINKEDIT") == 0) {
|
||||
linkedit_cmd = (struct segment_command_64 *)ld_command;
|
||||
}
|
||||
} else if (ld_command->cmd == LC_DYLD_INFO_ONLY || ld_command->cmd == LC_DYLD_INFO) {
|
||||
dyldinfo_cmd = (struct dyld_info_command *)ld_command;
|
||||
if (linkedit_cmd != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ld_command = (void *)ld_command + ld_command->cmdsize;
|
||||
}
|
||||
if (dyldinfo_cmd == NULL) {
|
||||
#ifndef COMPACT
|
||||
fprintf(stderr, "symexp_solve: LC_DYLD_INFO_ONLY segment not found!\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
// stroff and strtbl are in the __LINKEDIT segment
|
||||
// Its offset will change when loaded into the memory, so we need to add this slide
|
||||
intptr_t linkedit_slide = linkedit_cmd->vmaddr - linkedit_cmd->fileoff;
|
||||
uint8_t *export_offset = (uint8_t *)image_slide + linkedit_slide + dyldinfo_cmd->export_off;
|
||||
symbol_address = trie_query(export_offset, symbol_name);
|
||||
|
||||
if (symbol_address != NULL) {
|
||||
symbol_address += image_slide;
|
||||
}
|
||||
#ifndef COMPACT
|
||||
else {
|
||||
fprintf(stderr, "symexp_solve: symbol not found!\n");
|
||||
}
|
||||
#endif
|
||||
return symbol_address;
|
||||
}
|
||||
|
||||
inline uint64_t read_uleb128(const uint8_t **p) {
|
||||
int bit = 0;
|
||||
uint64_t result = 0;
|
||||
do {
|
||||
uint64_t slice = **p & 0x7f;
|
||||
result |= (slice << bit);
|
||||
bit += 7;
|
||||
} while (*(*p)++ & 0x80);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void *trie_query(const uint8_t *export, const char *name) {
|
||||
// most comments below are copied from <mach-o/loader.h>, not AI generated :P
|
||||
// a trie node starts with a uleb128 stored the lenth of the exported symbol information
|
||||
uint64_t node_off = 0;
|
||||
const char *rest_name = name;
|
||||
void *symbol_address = NULL;
|
||||
bool go_child = true;
|
||||
while (go_child) {
|
||||
const uint8_t *cur_pos = export + node_off;
|
||||
uint64_t info_len = read_uleb128(&cur_pos);
|
||||
// the exported symbol information is followed by the child edges
|
||||
const uint8_t *child_off = cur_pos + info_len;
|
||||
|
||||
if (rest_name[0] == '\0') {
|
||||
if (info_len != 0) {
|
||||
// first is a uleb128 containing flags
|
||||
uint64_t flag = read_uleb128(&cur_pos);
|
||||
if (flag == EXPORT_SYMBOL_FLAGS_KIND_REGULAR) {
|
||||
// normally, it is followed by a uleb128 encoded function offset
|
||||
uint64_t symbol_off = read_uleb128(&cur_pos);
|
||||
symbol_address = (void *)symbol_off;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
go_child = false;
|
||||
cur_pos = child_off;
|
||||
// child edges start with a byte of how many edges (0-255) this node has
|
||||
uint8_t child_count = *(uint8_t *)cur_pos++;
|
||||
// then followed by each edge.
|
||||
for (int i = 0; i < child_count; i++) {
|
||||
// each edge is a zero terminated UTF8 of the addition chars
|
||||
char *cur_str = (char *)cur_pos;
|
||||
size_t cur_len = strlen(cur_str);
|
||||
cur_pos += cur_len + 1;
|
||||
// then followed by a uleb128 offset for the node that edge points to
|
||||
uint64_t next_off = read_uleb128(&cur_pos);
|
||||
if (strncmp(rest_name, cur_str, cur_len) == 0) {
|
||||
go_child = true;
|
||||
rest_name += cur_len;
|
||||
node_off = next_off;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return symbol_address;
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
#include <mach-o/dyld.h> // _dyld_*
|
||||
#include <mach-o/loader.h> // mach_header_64, load_command...
|
||||
#include <mach-o/nlist.h> // nlist_64
|
||||
#include <string.h> // strcmp()
|
||||
|
||||
#ifndef COMPACT
|
||||
#include <printf.h> // fprintf()
|
||||
#endif
|
||||
|
||||
#include "../../include/tinyhook.h"
|
||||
|
||||
void *symtbl_solve(uint32_t image_index, const char *symbol_name) {
|
||||
void *symbol_address = NULL;
|
||||
intptr_t image_slide = _dyld_get_image_vmaddr_slide(image_index);
|
||||
struct mach_header_64 *mh_header = (struct mach_header_64 *)_dyld_get_image_header(image_index);
|
||||
struct load_command *ld_command = (void *)mh_header + sizeof(struct mach_header_64);
|
||||
#ifndef COMPACT
|
||||
if (mh_header == NULL) {
|
||||
fprintf(stderr, "symtbl_solve: image_index out of range!\n");
|
||||
}
|
||||
#endif
|
||||
struct symtab_command *symtab_cmd = NULL;
|
||||
struct segment_command_64 *linkedit_cmd = NULL;
|
||||
for (int i = 0; i < mh_header->ncmds; i++) {
|
||||
if (ld_command->cmd == LC_SEGMENT_64) {
|
||||
const struct segment_command_64 *segment = (struct segment_command_64 *)ld_command;
|
||||
if (strcmp(segment->segname, "__LINKEDIT") == 0) {
|
||||
linkedit_cmd = (struct segment_command_64 *)ld_command;
|
||||
}
|
||||
} else if (ld_command->cmd == LC_SYMTAB) {
|
||||
symtab_cmd = (struct symtab_command *)ld_command;
|
||||
if (linkedit_cmd != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ld_command = (void *)ld_command + ld_command->cmdsize;
|
||||
}
|
||||
// stroff and strtbl are in the __LINKEDIT segment
|
||||
// Its offset will change when loaded into the memory, so we need to add this slide
|
||||
intptr_t linkedit_slide = linkedit_cmd->vmaddr - linkedit_cmd->fileoff;
|
||||
struct nlist_64 *nl_tbl = (void *)image_slide + linkedit_slide + symtab_cmd->symoff;
|
||||
char *str_tbl = (void *)image_slide + linkedit_slide + symtab_cmd->stroff;
|
||||
for (int j = 0; j < symtab_cmd->nsyms; j++) {
|
||||
if ((nl_tbl[j].n_type & N_TYPE) == N_SECT) {
|
||||
if (strcmp(symbol_name, str_tbl + nl_tbl[j].n_un.n_strx) == 0) {
|
||||
symbol_address = (void *)nl_tbl[j].n_value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (symbol_address != NULL) {
|
||||
symbol_address += image_slide;
|
||||
}
|
||||
#ifndef COMPACT
|
||||
else {
|
||||
fprintf(stderr, "symtbl_solve: symbol not found!\n");
|
||||
}
|
||||
#endif
|
||||
return symbol_address;
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
#include <mach/mach_init.h> // mach_task_self()
|
||||
#include <mach/mach_vm.h> // mach_vm_*
|
||||
#include <stdlib.h> // atexit()
|
||||
#include <string.h> // memcpy()
|
||||
|
||||
#ifndef COMPACT
|
||||
#include <mach/mach_error.h> // mach_error_string()
|
||||
#include <printf.h> // fprintf()
|
||||
#endif
|
||||
|
||||
#ifdef __x86_64__
|
||||
#include "fde64/fde64.h"
|
||||
#endif
|
||||
|
||||
#include "../include/tinyhook.h"
|
||||
|
||||
#define MB (1ll << 20)
|
||||
#define GB (1ll << 30)
|
||||
|
||||
#ifdef __aarch64__
|
||||
#define AARCH64_B 0x14000000 // b +0
|
||||
#define AARCH64_BL 0x94000000 // bl +0
|
||||
#define AARCH64_ADRP 0x90000011 // adrp x17, 0
|
||||
#define AARCH64_BR 0xd61f0220 // br x17
|
||||
#define AARCH64_BLR 0xd63f0220 // blr x17
|
||||
#define AARCH64_ADD 0x91000231 // add x17, x17, 0
|
||||
#define AARCH64_SUB 0xd1000231 // sub x17, x17, 0
|
||||
|
||||
#define MAX_JUMP_SIZE 12
|
||||
|
||||
#elif __x86_64__
|
||||
#define X86_64_CALL 0xe8 // call
|
||||
#define X86_64_JMP 0xe9 // jmp
|
||||
#define X86_64_JMP_RIP 0x000025ff // jmp [rip]
|
||||
#define X86_64_CALL_RIP 0x000015ff // call [rip]
|
||||
#define X86_64_MOV_RI64 0xb848 // mov r64, m64
|
||||
#define X86_64_MOV_RM64 0x8b48 // mov r64, [r64]
|
||||
|
||||
#define MAX_JUMP_SIZE 14
|
||||
#endif
|
||||
|
||||
int tiny_insert(void *address, void *destination, bool link) {
|
||||
size_t jump_size;
|
||||
int assembly;
|
||||
unsigned char bytes[MAX_JUMP_SIZE];
|
||||
#ifdef __aarch64__
|
||||
// b/bl imm ; go to destination
|
||||
jump_size = 4;
|
||||
assembly = (destination - address) >> 2 & 0x3ffffff;
|
||||
assembly |= link ? AARCH64_BL : AARCH64_B;
|
||||
*(int *)bytes = assembly;
|
||||
#elif __x86_64__
|
||||
// jmp/call imm ; go to destination
|
||||
jump_size = 5;
|
||||
*bytes = link ? X86_64_CALL : X86_64_JMP;
|
||||
assembly = (long)destination - (long)address - 5;
|
||||
*(int *)(bytes + 1) = assembly;
|
||||
#endif
|
||||
write_mem(address, bytes, jump_size);
|
||||
return jump_size;
|
||||
}
|
||||
|
||||
int tiny_insert_far(void *address, void *destination, bool link) {
|
||||
size_t jump_size;
|
||||
unsigned char bytes[MAX_JUMP_SIZE];
|
||||
#ifdef __aarch64__
|
||||
// adrp x17, imm
|
||||
// add x17, x17, imm ; x17 -> destination
|
||||
// br/blr x17
|
||||
jump_size = 12;
|
||||
int assembly;
|
||||
assembly = (((long)destination >> 12) - ((long)address >> 12)) & 0x1fffff;
|
||||
assembly = ((assembly & 0x3) << 29) | (assembly >> 2 << 5) | AARCH64_ADRP;
|
||||
*(int *)bytes = assembly;
|
||||
assembly = ((long)destination & 0xfff) << 10 | AARCH64_ADD;
|
||||
*(int *)(bytes + 4) = assembly;
|
||||
*(int *)(bytes + 8) = link ? AARCH64_BLR : AARCH64_BR;
|
||||
#elif __x86_64__
|
||||
jump_size = 14;
|
||||
// jmp [rip] ; rip stored destination
|
||||
*(int *)bytes = link ? X86_64_CALL_RIP : X86_64_JMP_RIP;
|
||||
bytes[5] = bytes[6] = 0;
|
||||
*(long long *)(bytes + 6) = (long long)destination;
|
||||
#endif
|
||||
write_mem(address, bytes, jump_size);
|
||||
return jump_size;
|
||||
}
|
||||
|
||||
int position = 0;
|
||||
mach_vm_address_t vm;
|
||||
|
||||
static int get_jump_size(void *address, void *destination);
|
||||
static int insert_jump(void *address, void *destination);
|
||||
static int save_header(void *address, void *destination, int *skip_len);
|
||||
|
||||
int tiny_hook(void *function, void *destination, void **origin) {
|
||||
int kr = 0;
|
||||
if (origin == NULL)
|
||||
insert_jump(function, destination);
|
||||
else {
|
||||
if (!position) {
|
||||
// alloc a vm to store headers and jumps
|
||||
kr = mach_vm_allocate(mach_task_self(), &vm, PAGE_SIZE, VM_FLAGS_ANYWHERE);
|
||||
#ifndef COMPACT
|
||||
if (kr != 0) {
|
||||
fprintf(stderr, "mach_vm_allocate: %s\n", mach_error_string(kr));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
int skip_len;
|
||||
*origin = (void *)(vm + position);
|
||||
position += save_header(function, (void *)(vm + position), &skip_len);
|
||||
position += insert_jump((void *)(vm + position), function + skip_len);
|
||||
insert_jump(function, destination);
|
||||
}
|
||||
return kr;
|
||||
}
|
||||
|
||||
static int get_jump_size(void *address, void *destination) {
|
||||
long long distance = destination > address ? destination - address : address - destination;
|
||||
#ifdef __aarch64__
|
||||
return distance < 128 * MB ? 4 : 12;
|
||||
#elif __x86_64__
|
||||
return distance < 2 * GB ? 5 : 14;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int insert_jump(void *address, void *destination) {
|
||||
if (get_jump_size(address, destination) <= 5)
|
||||
return tiny_insert(address, destination, false);
|
||||
else
|
||||
return tiny_insert_far(address, destination, false);
|
||||
}
|
||||
|
||||
static int save_header(void *address, void *destination, int *skip_len) {
|
||||
int header_len = 0;
|
||||
#ifdef __aarch64__
|
||||
header_len = *skip_len = get_jump_size(address, destination);
|
||||
unsigned char bytes_out[MAX_JUMP_SIZE];
|
||||
read_mem(bytes_out, address, MAX_JUMP_SIZE);
|
||||
for (int i = 0; i < header_len; i += 4) {
|
||||
int cur_asm = *(int *)(bytes_out + i);
|
||||
long cur_addr = (long)address + i, cur_dst = (long)destination + i;
|
||||
if (((cur_asm ^ 0x90000000) & 0x9f000000) == 0) {
|
||||
// adrp
|
||||
// modify the immediate
|
||||
int len = (cur_asm >> 29 & 0x3) | ((cur_asm >> 3) & 0x1ffffc);
|
||||
len += (cur_addr >> 12) - (cur_dst >> 12);
|
||||
cur_asm &= 0x9f00001f;
|
||||
cur_asm = ((len & 0x3) << 29) | (len >> 2 << 5) | cur_asm;
|
||||
*(int *)(bytes_out + i) = cur_asm;
|
||||
}
|
||||
}
|
||||
#elif __x86_64__
|
||||
int min_len;
|
||||
struct fde64s assembly;
|
||||
unsigned char bytes_in[MAX_JUMP_SIZE * 2], bytes_out[MAX_JUMP_SIZE * 4];
|
||||
read_mem(bytes_in, address, MAX_JUMP_SIZE * 2);
|
||||
min_len = get_jump_size(address, destination);
|
||||
for (*skip_len = 0; *skip_len < min_len; *skip_len += assembly.len) {
|
||||
long long cur_addr = (long long)address + *skip_len;
|
||||
decode(bytes_in + *skip_len, &assembly);
|
||||
if (assembly.opcode == 0x8B && assembly.modrm_rm == 0b101) {
|
||||
// mov r64, [rip+]
|
||||
// split it into 2 instructions
|
||||
// mov r64 $rip+(immediate)
|
||||
// mov r64 [r64]
|
||||
*(short *)(bytes_out + header_len) = X86_64_MOV_RI64;
|
||||
bytes_out[header_len + 1] += assembly.modrm_reg;
|
||||
*(long long *)(bytes_out + header_len + 2) = assembly.disp32 + cur_addr + assembly.len;
|
||||
header_len += 10;
|
||||
*(short *)(bytes_out + header_len) = X86_64_MOV_RM64;
|
||||
bytes_out[header_len + 2] = assembly.modrm_reg << 3 | assembly.modrm_reg;
|
||||
header_len += 3;
|
||||
} else {
|
||||
memcpy(bytes_out + header_len, bytes_in + *skip_len, assembly.len);
|
||||
header_len += assembly.len;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
write_mem(destination, bytes_out, header_len);
|
||||
return header_len;
|
||||
}
|
||||
Reference in New Issue
Block a user