逆向-hook-plt

搬砖

PLT hook

原理: 了解了 ELF 格式和 linker 的 relocation 过程之后,PLT hook 的过程就不言自明了。
它做了和 relocation 类似的事情。即:通过符号名,先在 hash table 中找到对应的符号信息(在 .dynsym 中);
再找到对应的 PLT 信息(在 .rel.plt 或 .rela.plt 或 .rel.dyn 或 .rela.dyn 或 .rel.dyn.aps2 或 .rela.dyn.aps2 中);
最后找到绝对地址信息(在 .got.plt 或 .data 或 .data.rel.ro 中)。最后要做的就是修改这个绝对地址的值,改为我们需要的自己的“代理函数”的地址。

要注意的是,在修改这个绝对地址之前,需要先用 mprotect 设置当前地址位置所在内存页为“可写”的,因为 linker 在做完 relocation 后会把 .got.plt 和 .data.rel.ro 设置为只读的;
修改完之后,需要用 __builtin___clear_cache 来清除该内存位置的 CPU cache,以使修改能立刻生效。

xhook

1.动态链接过程

动态链接是一种将程序的可执行文件与动态链接库(Shared Libraries,在 Linux 和 Android 上通常以 .so 文件存在)关联起来的技术。当你使用 dlopen 调用一个共享库时,动态链接器(在 Android 上就是 linker 或者 ld-linux.so)会按照特定的步骤加载和准备库以供使用。

以下是动态链接的大致步骤:

1. 检查已加载的 ELF 列表:
动态链接器首先检查要加载的共享库是否已经加载过了。
如果已经加载,它只会增加共享库的引用计数,并返回一个指向库的指针。

2. 解析依赖并建立加载列表:
动态链接器从 .dynamic section 读取共享库的依赖项。
它会构建一个包括目标库及其所有未加载依赖库的加载列表。

3. 加载 ELF 到内存:
对每个还没有加载的库,动态链接器使用 mmap 预留一块内存。
然后读取库的程序头表(Program Header Table, PHT),并将所有 PT_LOAD 类型的段(segment)映射到内存中。

4. 处理 ELF 的 .dynamic section:
通过 .dynamic section 中的条目找到例如符号表、字符串表以及重定位表的虚拟地址,并保存它们的实际内存地址供后续步骤使用。

5. 执行重定位:
针对这些 .rel* 或者 .rela* sections进行重定位操作。
对每个重定位条目,动态链接器需要根据条目的类型和信息,找到正确的符号地址,并更新引用位置的地址。
例如,某个函数调用的 GOT (Global Offset Table)条目在初次加载时是空的,重定位会填上正确的函数实现地址。

6. 更新引用计数:
为刚刚加载的库增加引用计数。

7. 调用构造函数:
一旦库加载到内存并重定位完毕,动态链接器会调用库的构造函数。
构造函数在 .dynamic section 中被标记为 DT_INIT 和 DT_INIT_ARRAY 类型。
通常这些构造函数会初始化库的静态数据或进行其他的库初始化操作。

2. xhook源码分析

bhook

bhook分析

lsplt

jvmti