.plt/.got.plt及延迟绑定重定位技术详解

之前做的一个验证实验,直观了解下延迟绑定重定位技术。

.plt/.got.plt

.plt存储的是过程连接表 (Procedure Linkege Table,PLT) 。包含了共享库函数地址解析的代码。每个 PLT entry 对应一个function的解析。

.got.plt存储着全局偏移表。每个 entry 存储着一个函数的实际地址,其中前3个 entry 是特殊的。

  • GOT[0]:存放了指向可执行文件动态段的地址
  • GOT[1]:存放link_map结构的地址
  • GOT[2]:存放了指向动态链接器_dl_runtime_resolve()函数的地址

示例分析

.plt和.got.plt共同构成了共享库重定位延迟绑定技术,实现了对共享库的动态解析。这里以调用write()函数为例

1
2
3
4
5
6
7
...
write(STDOUT_FILENO,"Hello,World\n",13);
write(STDOUT_FILENO,"Second run\n",12);
...

#compiler
gcc -z norelro -no-pie -fno-stack-protector -g -o test_plt_got test_plt_got.c

这个程序会连续两次调用write()函数。

查看 .plt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$objdump -d -j .plt ./test_plt_got

Disassembly of section .plt:

080482d0 <.plt>:
80482d0: ff 35 a8 97 04 08 pushl 0x80497a8
80482d6: ff 25 ac 97 04 08 jmp *0x80497ac
80482dc: 00 00 add %al,(%eax)
...

08048300 <write@plt>:
8048300: ff 25 b8 97 04 08 jmp *0x80497b8
8048306: 68 10 00 00 00 push $0x10
804830b: e9 c0 ff ff ff jmp 80482d0 <.plt>

查看 .got.plt

*0x80497b8存储的就是write()的.got.plt entry 地址。

1
2
3
4
5
6
7
8
9
10
$objdump -R ./test_plt_got

./test_plt_got: file format elf32-i386

DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
080497a0 R_386_GLOB_DAT __gmon_start__
080497b0 R_386_JUMP_SLOT read@GLIBC_2.0
080497b4 R_386_JUMP_SLOT __libc_start_main@GLIBC_2.0
080497b8 R_386_JUMP_SLOT write@GLIBC_2.0

运行过程解析

peda-gdb 调试,b write@plt 下断点,r运行,解析过程如下:

1.程序运行,第一次调用write()函数,调用write@plt() \ref{fig:plt1_PNG}

调用write@plt

2.PLT 代码做一次到 GOT 中地址的间接跳转:jmp *0x80497b8 , 即 write@got 地址为0x80497b8

x 0x80497b8,可以发现存储的数据为0x8048306,也就是write@plt的第二行指令
0x80497b8存储的数据

3.这样就又回到了 PLT 代码,执行push 0x10

4.执行 PLT 第三行代码:jmp 0x80482d0,跳转到 PLT[0]

查看 PLT[0] 前两行涉及到的指针,查看其存储的数据分别为:0xb7fff920;0xb7fee2f0
PLT[0]

5.PLT[0] 第一行指令 push GOT[1] 的地址,该地址中存放了指向link_map的偏移地址

6.PLT[0] 第二行指令跳转到 GOT[2] 存放的地址,该地址指向了动态链接器的 _dl_runtime_resolve() 函数

_dl_runtime_resolve() 会将write()函数真正的内存地址加到 GOT entry 中
重定位write()

7.第二次调用write()函数时,可以发现 write@plt 将直接跳转到 glibc 中的 write() 函数地址0xb7ead760

重定位write()

参考

  • Learning Linux Binary Analysis.Ryan O’Neill