fishhook库问题点优化

162 阅读1分钟

fishhook库问题点优化 有一处代码会奔溃 github.com/facebook/fi…

static void perform_rebinding_with_section(struct rebindings_entry *rebindings,

section_t *section,

intptr_t slide,

nlist_t *symtab,

char *strtab,

uint32_t *indirect_symtab) {

uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1;

void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr);

for (uint i = 0; i < section->size / sizeof(void *); i++) {

uint32_t symtab_index = indirect_symbol_indices[i];

if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL ||

symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) {

continue;

}

uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx;

char *symbol_name = strtab + strtab_offset;

bool symbol_name_longer_than_1 = symbol_name[0] && symbol_name[1];

struct rebindings_entry *cur = rebindings;

while (cur) {

for (uint j = 0; j < cur->rebindings_nel; j++) {

if (symbol_name_longer_than_1 &&

strcmp(&symbol_name[1], cur->rebindings[j].name) == 0) {

if (cur->rebindings[j].replaced != NULL &&

indirect_symbol_bindings[i] != cur->rebindings[j].replacement) {

*(cur->rebindings[j].replaced) = indirect_symbol_bindings[i];

}

// 写入时判断内存地址是否可写

bool is_prot_changed = false;

void **address_to_write = indirect_symbol_bindings + i;

vm_prot_t prot = get_protection(address_to_write);

if ((prot & VM_PROT_WRITE) == 0) {

is_prot_changed = true;

kern_return_t success = vm_protect(mach_task_self(), (vm_address_t)address_to_write, sizeof(void *), false, prot | VM_PROT_WRITE);

if (success != KERN_SUCCESS) {

// 添加写权限失败, 不进行 hook

goto symbol_loop;

}

}

indirect_symbol_bindings[i] = cur->rebindings[j].replacement;

// 恢复内存权限

if (is_prot_changed) {

vm_protect(mach_task_self(), (vm_address_t)address_to_write, sizeof(void *), false, prot);

}

goto symbol_loop;

}

}

cur = cur->next;

}

symbol_loop:;

}

}static void perform_rebinding_with_section(struct rebindings_entry *rebindings,

section_t *section,

intptr_t slide,

nlist_t *symtab,

char *strtab,

uint32_t *indirect_symtab) {

uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1;

void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr);

for (uint i = 0; i < section->size / sizeof(void *); i++) {

uint32_t symtab_index = indirect_symbol_indices[i];

if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL ||

symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) {

continue;

}

uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx;

char *symbol_name = strtab + strtab_offset;

bool symbol_name_longer_than_1 = symbol_name[0] && symbol_name[1];

struct rebindings_entry *cur = rebindings;

while (cur) {

for (uint j = 0; j < cur->rebindings_nel; j++) {

if (symbol_name_longer_than_1 &&

strcmp(&symbol_name[1], cur->rebindings[j].name) == 0) {

if (cur->rebindings[j].replaced != NULL &&

indirect_symbol_bindings[i] != cur->rebindings[j].replacement) {

*(cur->rebindings[j].replaced) = indirect_symbol_bindings[i];

}

// 写入时判断内存地址是否可写

bool is_prot_changed = false;

void **address_to_write = indirect_symbol_bindings + i;

vm_prot_t prot = get_protection(address_to_write);

if ((prot & VM_PROT_WRITE) == 0) {

is_prot_changed = true;

kern_return_t success = vm_protect(mach_task_self(), (vm_address_t)address_to_write, sizeof(void *), false, prot | VM_PROT_WRITE);

if (success != KERN_SUCCESS) {

// 添加写权限失败, 不进行 hook

goto symbol_loop;

}

}

indirect_symbol_bindings[i] = cur->rebindings[j].replacement;

// 恢复内存权限

if (is_prot_changed) {

vm_protect(mach_task_self(), (vm_address_t)address_to_write, sizeof(void *), false, prot);

}

goto symbol_loop;

}

}

cur = cur->next;

}

symbol_loop:;

}

}