其中除第一个表项以外,plt 表的第一条都是跳转到对应的 got 表项,而 got 表项的内容我们可以通过 gdb 来看一下 , 如果函数还没有执行的时候,这里的地址是对应 plt 表项的下一条命令,即 push 0x0(作为参数传入-- 相应函数在 rel.plt
中的偏移)
在想要调用的函数没有被调用过 , 想要调用他的时候,是按照这个过程来调用的
xxx@plt -> xxx@got -> xxx@plt -> 公共@plt -> _dl_runtime_resolve(通过这个函数找到运行时函数的地址)
到这里我们还需要知道
- _dl_runtime_resolve 是怎么知道要查找 printf 函数的
- _dl_runtime_resolve 找到 printf 函数地址之后,它怎么知道回填到哪个 GOT 表项
第二个问题,看 .rel.plt 的位置就对应着 xxx@plt 里 jmp 的地址 , 该位置就是偏移量,使用
readelf -r plt
读取elf
文件中重定位节信息文章插图
在 i386 架构下,除了每个函数占用一个 GOT 表项外,GOT 表项还保留了3个公共表项,也即 got 的前3项,分别保存:动态链接器在加载完 ELF 之后,都会将这3地址写到 GOT 表的前3项
- got [0]: 本 ELF 动态段 (.dynamic 段)的装载地址
- got [1]:本 ELF 的 link_map 数据结构描述符地址,包含了进行符号解析需要的当前 ELF 对象的信息 。每个 link_map 都是一条双向链表的一个节点 , 而这个链表保存了所有加载的 ELF 对象的信息 。
- got [2]:指向动态装载器中 _dl_runtime_resolve 函数的指针 。
文章插图
文章插图
通过编写如下所示的代码来帮助理解
plt
和got
这两个表// gcc -m32 -no-pie -g -o plt plt.c#include <stdio.h>#include <stdlib.h>int main(int argc, char **argv){puts("hello,world");exit(0);}
使用objdump -h plt
, 查看该文件编译后的所有节的信息plt:file format elf32-i386Sections:Idx NameSizeVMALMAFile offAlgn 10 .rel.plt000000180804832c0804832c0000032c2**2CONTENTS, ALLOC, LOAD, READONLY, DATA 12 .plt000000400804903008049030000010302**4CONTENTS, ALLOC, LOAD, READONLY, CODE 13 .plt.sec000000300804907008049070000010702**4CONTENTS, ALLOC, LOAD, READONLY, CODE 22 .got000000040804bffc0804bffc00002ffc2**2CONTENTS, ALLOC, LOAD, DATA 23 .got.plt000000180804c0000804c000000030002**2CONTENTS, ALLOC, LOAD, DATA
然后打开gdb
进行分析,可以看到调用函数puts
的地址为0x80491de
,在该地址处下一个断点文章插图
然后使用
si
进入puts
函数内部文章插图
可以看到在 puts@plt 中第一条指令是跳转,
0x804c00c
其实就是[_GLOBAL_OFFSET_TABLE_ + 12],这个地址刚好位于.got.plt
表中,也就是说 , puts@plt 的第一步是去 .got.plt 找地址 23 .got.plt000000180804c0000804c000000030002**2CONTENTS, ALLOC, LOAD, DATA
文章插图
这时候我们如果再按一次
si
,可以看到会直接执行到下面的那一行的指令,原因就是:我们之前没有调用过 puts@plt 函数,.got.plt 里面存储的puts
的地址就是下一条指令的地址而非真正的地址 , 所以按照之前说的 , 现在要触发链接器找到 puts 函数的地址了下面的[_GLOBAL_OFFSET_TABLE_ + 4] 处的指令,这个地址
0x804c004
也是位于.got.plt
节中的,查看该地址存储的内容文章插图
其中
0xf7ffd990
指向ld.so
的数据段,0xf7fe7b10
指向可执行区域 , 简而言之,触发了链接器/加载器,在加载器处理之前,查看之前的.got.plt
节中的地址0x804c00c
所存储的值为推荐阅读
- 四十一 增删查改分页 Java开发学习----MyBatisPlus标准数据层开发
- 中 学习ASP.NET Core Blazor编程系列十——路由
- CC1,3,6回顾
- 图学习【参考资料2】-知识补充与node2vec代码注解
- 二十四 设计模式学习:Spring 中使用到的设计模式
- Java安全之CC3
- TensorFlow深度学习!构建神经网络预测股票价格!?
- JUC学习笔记——共享模型之管程
- Seata Server 1.5.2 源码学习
- 2022极端高温!机器学习如何预测森林火灾?? 万物AI