美文网首页
GOT表与PLT表的作用

GOT表与PLT表的作用

作者: 骑猪满天飞 | 来源:发表于2020-12-10 09:23 被阅读0次

地址无关代码(Position-Independent Code)

如果共享文件(.so文件)需要加载到一个特定的地址才能运行,将造成.so文件的地址冲突问题。因此共享对象的最终装载地址在编译时是不确定的。

如下所示:

readelf --headers libc.so 
Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  [...]
  LOAD           0x000000 0x00000000 0x00000000 0x1aef0c 0x1aef0c R E 0x1000
  LOAD           0x1af23c 0x001b023c 0x001b023c 0x02c98 0x057e0 RW  0x1000

共享库的装载地址是从地址0x00000000开始的,这是一个无效地址,当使用此共享库的程序运行时,可以在进程虚拟空间分布看到最终的装载地址。

GOT表--绑定全局变量地址

让我们通过观察地址无关代码具体实现方式,来看看GOT表在其中的作用。

使用如下代码生成地址无关共享库文件:

$ cat test.c 
static int a;
extern int b;
extern void ext();

void bar()
{
  a=1;
  b=2;
}

void foo()
{
  bar();
  ext();
}
gcc -shared -fPIC -o libtest.so test.c

模块内部数据访问

上述代码中静态变量a为模块内部数据,为生成地址无关代码指令不能直接包含a的绝对地址,bar函数汇编代码如下:

0000000000000710 <bar>:
 710:   55                      push   %rbp
 711:   48 89 e5                mov    %rsp,%rbp
 714:   c7 05 16 09 20 00 01    movl   $0x1,0x200916(%rip)        # 201034 <a>
 71b:   00 00 00 
 71e:   48 8b 05 b3 08 20 00    mov    0x2008b3(%rip),%rax        # 200fd8 <_DYNAMIC+0x1c8>

访问数据a的对应指令为:

 714:   c7 05 16 09 20 00 01    movl   $0x1,0x200916(%rip)        # 201034 <a>

此时%rip指向当前指令的下一条指令地址:71e处。a的地址为0x200916+0x71e= 0x201034,然后将1赋值给a。

如果该共享库被加载到0x1000000000000000,那么a的实际地址为0x1000000000000000+0x200916+0x71e= 0x1000000000201034

模块间数据访问

变量b定义在其他模块中,跟模块装载地址有关,根据把地址相关的部分放到数据段的思想,ELF在数据段建立了一个指向这些变量的指针数组,也称为全局变量表(GOT Global Offset Table)

当指令访问变量b时先找到GOT表,再根据GOT表找到变量地址。

71e:    48 8b 05 b3 08 20 00    mov    0x2008b3(%rip),%rax        # 200fd8 <_DYNAMIC+0x1c8>
725:    c7 00 02 00 00 00       movl   $0x2,(%rax)
`

b的偏移地址为0x200fd8

 $objdump -h libtest.so
Sections:
Idx Name          Size      VMA               LMA               File off  Algn
[...]
 19 .got          00000030  0000000000200fd0  0000000000200fd0  00000fd0  2**3
                  CONTENTS, ALLOC, LOAD, DATA
[...]

0x200fd8属于got表范围,再看一下libtest.so的重定位项:

$objdump -R libtest.so 
libtest.so:     file format elf64-x86-64

DYNAMIC RELOCATION RECORDS
OFFSET           TYPE              VALUE
[...] 
0000000000200fd8 R_X86_64_GLOB_DAT  b
[...]

可以看到b的地址需要重定位,位于0x200fd8,GOT偏移8。
所以,当动态加载器加载该so文件时,会先去看它的relocations,然后找到b的值,然后把它重定位到.got部分的0×200828地址处。当访问变量b时,直接取.got中对应地址0x200fd8处,做到了地址无关。

PLT表--延迟绑定函数

在一个程序运行过程中,可能很多函数在程序执行完都不会用到,例如,错误处理函数、很少用到的功能模块等。所以ELF引入了延迟绑定概念,当函数第一次使用时才进行绑定(符号查找、重定位等)

当我们调用外部函数时按照通常做法使用GOT表进行跳转,为实现延迟绑定,在这个过程中通过PLT表又增加一层间接跳转。

模块间调用、跳转

函数通过PLT项进行跳转,还是使用上述的libtest.so进行说明。

00000000000005f0 <ext@plt>:
 5f0:   ff 25 2a 0a 20 00       jmpq   *0x200a2a(%rip)        # 201020 <_GLOBAL_OFFSET_TABLE_+0x20>
 5f6:   68 01 00 00 00          pushq  $0x1
 5fb:   e9 d0 ff ff ff          jmpq   5d0 <_init+0x20>

ext@plt的第一条指令跳转到0x201020,此地址为GOT表中保存ext函数的表项,由于延迟绑定的原因,第一次使用此函数时ext()的地址还未填入此表项:

0000000000201000 <_GLOBAL_OFFSET_TABLE_>:
  201000:   10 0e                   
  201002:   20 00                   
    ...
  201018:   e6 05                   
  20101a:   00 00                   
  20101c:   00 00                   
  20101e:   00 00                   
  201020:   f6 05 00 00 00 00 00            # 201027 <_GLOBAL_OFFSET_TABLE_+0x27>

此时0x201020的值为0x5f6,就是执行exp@plt的第二条指令:
5f6: 68 01 00 00 00 pushq $0x1
其中1代表ext这个符号在重定位表".rel.plt"中的下标。
后续指令:
5fb: e9 d0 ff ff ff jmpq 5d0 <_init+0x20>
此指令跳转到执行符号解析和重定位工作的函数.
经过一系列过程,ext()真正的地址填入到ext@plt中。

当我们再次调用ext()时第一条指令就将跳转到真正的ext()函数中,而不再执行后续指令。

ELF将GOT表分为了两个表".got" 和 ".got.plt",其中".got"用来保存全局变量引用的地址,".got.plt"用来保存函数引用地址。

参考

https://www.freebuf.com/articles/system/135685.html

《程序员的自我修养》

相关文章

  • GOT表与PLT表的作用

    地址无关代码(Position-Independent Code) 如果共享文件(.so文件)需要加载到一个特定的...

  • got表与plt表

    转自:http://blog.csdn.net/linyt/article/details/51635768 在介...

  • pwn6 介绍got plt以及libc.so

    GOT表和PLT表: GOT(Global Offset Table,全局偏移表)是Linux ELF文件中用于定...

  • GOT表和PLT表

    GOT是一个存储外部库函数的表 PLT则是由代码片段组成的,每个代码片段都跳转到GOT表中的一个具体的函数调用 重...

  • 2018-02-24

    PLT的真正实现要更复杂些,ELF将GOT拆分成两个表“.got”和”.got.plt”,前者用来保存全局变量引用...

  • GOT表 & PLT表 | Global Offset Tabl

    GOT表是程序中的一个section,负责存放动态链接的函数地址,除非被标记为Full RELRO (GCC默认采...

  • 深入理解GOT表和PLT表

    0x01 前言 操作系统通常使用动态链接的方法来提高程序运行的效率。在动态链接的情况下,程序加载的时候并不会把链接...

  • GOT表覆写技术

    GOT表:概念:每一个外部定义的符号在全局偏移表(Global offset Table)中有相应的条目,GOT位...

  • Pwnable.kr-5.passcode

    源码: 结合了网上的解释大致了解了1.首先了解got和plt表的大致意思2.进入远程登录平台3.查看源代码4.分析...

  • Android平台导入表Hook方式实现[转载]

    转自游戏安全实验室 本文会介绍Android平台下导入表Hook的实现过程,导入表(.Got表)的Hook实现有很...

网友评论

      本文标题:GOT表与PLT表的作用

      本文链接:https://www.haomeiwen.com/subject/mrrqgktx.html