PLT-hook技术

最近在学习apk的hook,贴一下自己的理解。

以下内容仅为个人看法,不代表100%正确,如有错误还请指出。

1.什么是hook技术

hook技术是一种拦截用户函数调用的技术。通过hook技术可以实现统计用户对某些函数的调用次数,对函数注入新的功能的目标。比如我想知道一个游戏运行时PSS的大小,那么我就可以使用hook技术来计算每一个函数调用时的开销。譬如 hook malloc,calloc,realloc 和 free,我们就能统计出各个动态库分配了多少内存,哪些内存一直被占用没有释放。

2.什么是PLT

在了解PLT技术之前需要先了解一下什么是共享库动态链接技术(linker)

大家应该听说过静态链接技术,是以一种将多个可链接目标文件链接为一个独立的可执行文件的过程。在链接的过程中,连接器会将静态库中的函数完整的复制到可执行文件的文本段中。在一个运行较多进程的系统中,这种链接方式对于内存消耗是不可小觑的。对于一个游戏来说,调用的函数个数数不胜数,所以会导致size变得很大。为了解决这个问题,共享库诞生了,共享库是一个目标模块或者说目标文件,在运行或者加载时,可以加载到内存的任意位置,并和内存中的程序链接起来,这个过程是一个叫做动态链接器的组件完成的。

3.PLT

PLT(Procedure Linkage Table)全称程序链接表,主要用于协助程序完成延迟加载的功能,假设程序调用一个动态库中的函数,因为动态库可以被加载到内存中的任意位置,因此我们无法去预测这个函数的运行时地址。正常的做法是为该函数调用生成一个重定位记录,然后动态链接器在程序加载的时候去解析它。但是这并不符合位置无关代码的做法,因为需要链接器修改调用模块的文本段。GNU使用延迟加载的技术去解决这个问题,把对函数地址的解析延迟到了对于函数的实际调用的时刻。使用这种技术,在第一次函数调用时的开销较大,但是在之后的调用中只会花费一条指令和一个间接的内存引用。

延迟调用的完成需要PLT和GOT(Global Offset Table)全局偏移量表协作完成。如果一个目标模块调用任何在共享库中的函数,那么它就有自己的GOT和PLT。GOT是数据段的一部分,PLT是代码段的一部分。下面我们来讲讲PLT和GOT表中的内容:

PLT表中的每一项是一个16字节代码。PLT[0]是一个特殊条目,它跳转到动态链接器中。PLT[1]是系统启动函数的条目。从PLT[3]开始是用户调用的动态库函数的条目。

4.GOT

GOT中每个表项是8字节的地址类型数据。和PLT类似,GOT[0]和GOT[1]也是特殊条目,包含动态链接器在解析函数地址时会使用的信息。GOT[2]是动态链接器在ld-linux.so模块中的入口点。其余的每一个条目对应一个被调用的函数,其地址在需要时进行解析。每个条目都有一个对应的PLT条目。

例子:

比如我游戏里有一个函数Attack,实际上我们打包成apk,在手机上运行时调用此函数的时候,是没有那么简单的。
在android手机上对于Attack函数的调用,实际上调用的是PLT中的Attack条目,而PLT中Attack条目中执行的是JMP(GOT4),也就是还需要跳转到GOT4中才是要执行函数Attack的基地址。PLT-hook技术

上一篇:怎样去理解Java中的volatile


下一篇:解决Django render() got an unexpected keyword argument 'renderer'问题