Fishhook替换C函数的原理

Fishhook是Facebook开发的用于在iOS中Hook C函数的库。它利用了位置无关代码(PIC)原理,通过修改Segment上的符号指针实现动态Hook。文章详细介绍了Fishhook的工作原理,包括遍历Symbols的两个Section、读取Indirect和Symbol Table、查找字符串匹配,以及在dyld加载时的绑定时机。此外,还探讨了Fishhook的局限性,即无法hook内部符号。
摘要由CSDN通过智能技术生成

Fishhook

Fishhook是facebook出品的,可以用来Hook C函数的一个开源库。它的主要接口就一个:

struct rebinding {
  const char *name; //字符串名称
  void *replacement; //替换后的方法
  void **replaced; //原始的方法(通常要存储下来,在替换后的方法里调用)
};

//两个参数分别是rebinding结构体数组,以及数组的长度
int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel);

实现也就不到两百行,本文就一步步揭开这个方法背后的黑魔法。

如果读者对dyld和Mach-O两个名词感到陌生,建议先看我的上一篇文章《深入理解iOS App的启动过程

原理

在讲解具体过程之前,首先介绍一个概念:PIC(Position Indepent Code),位置无关代码。

使用PIC的Mach-O文件,在引用符号(比如printf)的时候,并不是直接去找到符号的地址(编译期并不知道运行时printf的函数地址),而是通过在__DATA Segment上创建一个指针,等到启动的时候,dyld动态的去做绑定(bind),这样__DATA Segment上的指针就指向了printf的实现。

  • 知道这一点很关键,因为这是fishhook能够工作的核心原理,finshhook就是通过rebind_symbols修改__DATASegment上的符号指针指向,来动态的hook C函数。

    __DATA段中,有两个Sections和动态符号绑定有关:

  • __nl_symbol_ptr 存储了non-lazily绑定的符号,这些符号在mach-o加载的时候绑定。

  • __la_symbol_ptr 存储了lazy绑定的符号(方法),这些方法在第一调用的时候,由dyld_stub_binder来绑定,所以你会看到,每个mach-o的non-lazily绑定符号都有dyld_stub_binder

通过dyld相关的API,我们可以很容易的访问到这些Symbols指针,但是并不知道这些指针具体代表哪种函数。

所以,要解决的问题就是找到这些指针代表的字符串,和当前的要替换的进行比较,如果一样替换当前指针的实现即可。

接下来我们就来看看,如何通过一系列操作来找到这些指针代表的字符串。

准备工作

新建一个iOS单页面工程,添加一个C函数,然后,编译生成.app文件,在.app文件中获取可执行文件,用MachOView打开,选中__la_symbol_ptr,接下来我们就看看如何找到objc_msgSend的符号。

遍历存储Symbols的两个Section

其中,表示Section Header的数据结构如下,这里我们用到的是reserved1字段。由于是遍历,所以我们知道index,比如1061

struct section { /* for 32-bit architectures */
    char        sectname[16];   /* name of this section */
    char        segname[16];    /* segment this section goes in */
    uint32_t    addr;       /* memory address of this section */
    uint32_t    size;       /* size in bytes of this section */
    uint32_t    offset;     /* file offset of this section */
    uint32_t    align;      /* section alignment (power of 2) */
    uint32_t    reloff;     /* file offset of relocation entries */
    uint32_t    nreloc;     /* number of relocation entries */
    uint32_t    flags;      /* flags (section type and attributes)*/
    uint32_t    reserved1;  /* reserved (for
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值