fishhook与共享库和PIC

  1. PIC位置无关代码的引入
    1. GOT 全局偏移表
    2. PIC函数调用 和 PLT过程链接表
  2. 补充

fishhook是不能hook同一个library内的符号调用的,在某个issus的解答如下。

People have had issues with socket and/or connect in the past. One problem is that fishhook can only hook external calls, which means function calls within the same library generally cannot be hooked. In this case, calls to socket and connect from within the same library (libSystem) cannot be hooked. With the simulator, the system libraries are broken out into many sub-libraries, including libsystem_networking. With many sub-libraries, this means function calls from one sub-library to another can be hooked on the simulator, but on device where there’s just a single libSystem, those same calls are within the same library and cannot be hooked.

这是由于fishhook利用 Macho-O dyld link 的 dynamically rebinding symbols实现所导致的。

这边文章就围绕这个话题来展开,解释一下la_symbol_ptr存在的原因。由于Mac OS 上使用 stubs, la_symbol_ptrs, stub_helper来实现延迟绑定的原理和Linux ELF差不多,这里就使用ELF的实现来解释。

PIC位置无关代码的引入

设想一个场景,因为Linux/Mac os使用的是虚拟内存系统,这意味着共享库引用的外部符号地址在不同进程的虚拟内存中是不同的,对应到物理内存中TEXT段也不同,所以必须拷贝多份。这显然是不可以接受的,内存中存在了大量拷贝,浪费RAM资源。

如果我们共享库对外部引用是位置无关的就好了,就不会存在这个问题。

GOT 全局偏移表

这时利用DATA段读写的特性,DATA段会在内存中有多份拷贝,并且DATA段和TEXT段的距离不变,在DATA段存储变化的地址,TEXT段使用指向DATA段对应位置的引用。这就解决了TEXT段共享的问题。这里我们引入了一个全局偏移量表,GOT。动态链接器会重定位GOT中的每个条目,使得它包含正确的绝对地址。

PIC函数调用 和 PLT过程链接表

使用GOT这种方式,我们每次调用函数都需要额外的三条指令

1
2
3
4
call L1
L1: popl %ebx
addl $PROCOFF, %ebx
call *(%ebx)

  1. 将PC的值移到 ebx中
  2. ebx 指向GOT中适当的条目

这样的效率未免有些低。于是引入了 延迟绑定的技术,将过程地址的绑定推迟到第一次调用该过程时。第一次调用过程的运行时开销很大,但是其后的每次调用都只会花费一条指令和一个间接地存储器引用。

过程

1
call 8048464

调用相应的PLT条目

1
2
3
jmp *0x8049684
pushl $0x8
jmp 8048444

跳转到addvec

补充

省略了很多东西,比如说 PLT第一次调用的过程,具体GOT和PLT的实现,推荐看《深入理解计算机系统》。

script>