Hook 总结之 fishhook 源码逐行分析
2024-01-18 07:00:08
鱼钩剖析:深入探究 iOS 系统中的 Hook 技术
Hook 技术初探
在 iOS 系统的开发领域,Hook 技术可谓是一门广受推崇的秘术,其能让你随心所欲地改写函数的行为,如同在编程世界中施展魔法。它的用途可谓包罗万象,从代码调试到安全分析,再到性能优化,都能大显身手。
鱼钩鱼钩,鱼跃龙门
在 iOS 平台上,fishhook 堪称 Hook 技术的翘楚,由 Facebook 的大牛们倾情打造。它提供了一套简单易用的 Hook 接口,让你无需修改原始代码,便可尽情施展改造之术。fishhook 采用动态链接库注入的方式,巧妙地修改函数指针,从而实现 Hook 功能。
鱼钩源码,逐层解剖
fishhook 的源码由两部分组成:头文件 fishhook.h 和源文件 fishhook.c 。头文件定义了 Hook 函数接口,而源文件则负责实现 Hook 功能。
1. 鱼钩初始化
fishhook 的初始化过程在 fishhook_init 函数中展开。它首先通过 dlopen 函数加载待 Hook 的动态库,然后获取待 Hook 函数的地址。
void fishhook_init(void) {
fishhook_init_dyld();
fishhook_init_objc();
}
2. Hook 方法
fishhook 提供了两种 Hook 方法:rebind_symbols 和 replace_symbols 。
- rebind_symbols :将待 Hook 函数的指针重新绑定到新的函数,灵活性高,可随时取消 Hook。
- replace_symbols :直接替换待 Hook 函数的代码,无法取消 Hook。
3. 逐行源码分析
接下来,让我们逐行分析 fishhook.c 源码,领略 Hook 技术的精妙之处:
rebind_symbols 函数:
int rebind_symbols(struct rebinding *bindings, int count) {
void *old_addr;
void *new_addr;
for (int i = 0; i < count; i++) {
old_addr = bindings[i].orig_addr;
new_addr = bindings[i].new_addr;
struct hook_entry *entry = get_hook_entry(old_addr);
if (entry == NULL) {
return -1;
}
entry->new_addr = new_addr;
return 0;
}
}
函数解析:
rebind_symbols 函数对给定的函数列表进行 Hook,将旧函数地址替换为新函数地址。它首先获取旧函数地址和新函数地址,然后查找对应的 Hook 条目。如果 Hook 条目不存在,则返回错误。最后,修改 Hook 条目的新函数地址。
replace_symbols 函数:
int replace_symbols(struct rebinding *bindings, int count) {
void *old_addr;
void *new_addr;
for (int i = 0; i < count; i++) {
old_addr = bindings[i].orig_addr;
new_addr = bindings[i].new_addr;
void *old_ptr;
old_ptr = *(void * volatile *)old_addr;
*(void * volatile *)old_addr = new_addr;
free(old_ptr);
return 0;
}
}
函数解析:
replace_symbols 函数直接替换给定函数的代码。它首先获取旧函数地址和新函数地址,然后直接修改旧函数地址指向的新函数地址。最后,释放旧函数的内存。
4. 取消 Hook
fishhook 提供了 unwind 函数取消 Hook。该函数根据 Hook 条目中的信息恢复原始函数地址。
int unwind(struct rebinding *bindings, int count) {
void *old_addr;
void *new_addr;
for (int i = 0; i < count; i++) {
old_addr = bindings[i].orig_addr;
new_addr = bindings[i].new_addr;
struct hook_entry *entry = get_hook_entry(old_addr);
if (entry == NULL) {
return -1;
}
*(void * volatile *)old_addr = entry->orig_addr;
free(entry);
return 0;
}
}
函数解析:
unwind 函数对给定的函数列表取消 Hook。它首先获取旧函数地址和新函数地址,然后查找对应的 Hook 条目。如果 Hook 条目不存在,则返回错误。最后,修改旧函数地址指向的原始函数地址。
总结
本文对 fishhook 源码进行了深入分析,展现了 Hook 技术在 iOS 系统中的原理和实现。掌握 fishhook 的工作原理,开发者可以更深刻地理解 Hook 技术在 iOS 开发中的应用,为代码调试、安全分析和性能优化等任务提供新的思路。
常见问题解答
-
Hook 技术有哪些优点?
Hook 技术能够修改函数行为,而无需修改原始代码,提高了调试、分析和优化的灵活性。 -
fishhook 和其他 Hook 框架有什么区别?
fishhook 由 Facebook 开发,以其易用性和对 Objective-C 方法的良好支持而著称。 -
Hook 技术有哪些安全隐患?
Hook 技术可能被恶意软件利用,因此在使用时需要谨慎,防止被恶意程序劫持。 -
如何使用 fishhook?
在 iOS 项目中添加 fishhook 库,然后使用其提供的 Hook 函数进行 Hook 操作。 -
Hook 技术有哪些应用场景?
Hook 技术广泛应用于代码调试、安全分析、性能优化、测试和修改系统行为等领域。