首页
社区
课程
招聘
理解elf文件的got和plt
发表于: 2020-9-23 21:21 7327

理解elf文件的got和plt

2020-9-23 21:21
7327

在Linux平台下,elf文件中的got节和plt节在动态链接过程中起着非常重要的作用,学习got节和plt节是在学习elf文件格式过程中必不可少的一部分。所以在此笔记中,记录一下got节和plt节的原理。

使用objdump查看生成的lib.so共享库的的foo函数的反汇编代码

Alt text

可以看到foo函数对test变量的查找是通过当前的rip+0x200a33(需要配合重定位表实现)来获取的,也就是0x200fe8,使用readelf查看lib.so的节信息,0x200fe8位于got表中,以上是全局变量在got表中的解析过程。

可以看到_start函数在调用foo函数时,call的地址为0x3a0,在foo@plt(0x3a0)处呢,jmp到当前rip偏移0x0x200c52出指向的地址,也就是0x360处的地址,紧接着执行push 0 ,jmp390,也就是plt表中,最后在plt表中跳转到rip+0x200c54=0x200ff0(存储foo函数的实际地址) 的指向地址,查看elf信息,也可以看到0x200ff0的地址位于got表中。以上是函数在got表在函数调用过程中的解析过程。
这里需要注意两个问题
1.地址0x3a0处的的指令jmp QWORD PTR [rip+0x200c52],跳转到200ff8 (got中的条目)地址指向的地址,当前指向的数据是0x3a0下一条指令指向的地址,也就是push 0 ,然后跳转到plt中。
2.在plt中,执行了push QWORD PTR [rip+0x200c52] # 200fe8 <_GLOBAL_OFFSET_TABLE_+0x8>,也就是将got表的第二个条目数据压栈,然后jmp QWORD PTR [rip+0x200c54] # 200ff0 <_GLOBAL_OFFSET_TABLE_+0x10>,也就是跳转到got表的第三个条目指向的地址。在got中,前三个数据保存如下的数据

为什么要这样做?
动态链接器默认采用延迟链接方式时,动态链接器不会在程序加载时解析每一个函数,而是在调用时通过plt和got来对函数进行解析,然后会将解析获得函数地址存放在got中,下一次调用时会直接使用got中的函数地址对函数进行调用。在ELF将GOT拆分成两个表“.got”和".got.plt",前者用来保存全局变量引用的地址,后者用来保存函数引用的地址。也就是说,所有对于外部函数的引用被分离出来放到了“.got.plt”中

Alt text

PLT and GOT - the key to code sharing and dynamic libraries
浅析ELF中的GOT与PLT
《linux二进制分析》

//foo.c
//使用如下的编译命令编译生成foo.so
//gcc -shared -fPIC foo.c foo.so
 
extern int foo();
extern int test;
int foo()
{
    return test;
}
 
//main.c
//使用如下的命令,链接foo.so
//gcc -g -nostdlib  -o a.out main.c lib.so
int test;
_start()
{
    foo(test);
    return 0;
}
//foo.c
//使用如下的编译命令编译生成foo.so
//gcc -shared -fPIC foo.c foo.so
 
extern int foo();
extern int test;
int foo()
{
    return test;
}
 
//main.c
//使用如下的命令,链接foo.so
//gcc -g -nostdlib  -o a.out main.c lib.so
int test;
_start()
{
    foo(test);
    return 0;
}
00000000000005aa <foo>:
 5aa:    55                       push   rbp
 5ab:    48 89 e5                 mov    rbp,rsp
 5ae:    48 8b 05 33 0a 20 00     mov    rax,QWORD PTR [rip+0x200a33]        # 200fe8 <test>
 5b5:    8b 00                    mov    eax,DWORD PTR [rax]
 5b7:    5d                       pop    rbp
 5b8:    c3                       ret   
 
 
readelf -S lib.so
[16] .got              PROGBITS         0000000000200fd8  00000fd8
       0000000000000028  0000000000000008  WA       0     0     8
00000000000005aa <foo>:
 5aa:    55                       push   rbp
 5ab:    48 89 e5                 mov    rbp,rsp
 5ae:    48 8b 05 33 0a 20 00     mov    rax,QWORD PTR [rip+0x200a33]        # 200fe8 <test>
 5b5:    8b 00                    mov    eax,DWORD PTR [rax]
 5b7:    5d                       pop    rbp
 5b8:    c3                       ret   
 
 
readelf -S lib.so
[16] .got              PROGBITS         0000000000200fd8  00000fd8
       0000000000000028  0000000000000008  WA       0     0     8
 
remnux@remnux:~/Desktop/Deam$ objdump -d a.out
a.out:     文件格式 elf64-x86-64
 
Disassembly of section .plt:
 
0000000000000390 <.plt>:
 390:    ff 35 52 0c 20 00        push   QWORD PTR [rip+0x200c52]        # 200fe8 <_GLOBAL_OFFSET_TABLE_+0x8>
 396:    ff 25 54 0c 20 00        jmp    QWORD PTR [rip+0x200c54]        # 200ff0 <_GLOBAL_OFFSET_TABLE_+0x10>
 39c:    0f 1f 40 00              nop    DWORD PTR [rax+0x0]
 
00000000000003a0 <foo@plt>:
 3a0:    ff 25 52 0c 20 00        jmp    QWORD PTR [rip+0x200c52]        # 200ff8 <foo>
 3a6:    68 00 00 00 00           push   0x0
 3ab:    e9 e0 ff ff ff           jmp    390 <.plt>
 
Disassembly of section .text:
 
00000000000003b0 <_start>:
 3b0:    55                       push   rbp
 3b1:    48 89 e5                 mov    rbp,rsp
 3b4:    8b 05 46 0c 20 00        mov    eax,DWORD PTR [rip+0x200c46]        # 201000 <test>
 3ba:    89 c7                    mov    edi,eax
 3bc:    b8 00 00 00 00           mov    eax,0x0
 3c1:    e8 da ff ff ff           call   3a0 <foo@plt>
 3c6:    b8 00 00 00 00           mov    eax,0x0
 3cb:    5d                       pop    rbp
 3cc:    c3                       ret  
//readelf -D a.out
[12] .got              PROGBITS         0000000000200fe0  00000fe0
       0000000000000020  0000000000000008  WA       0     0     8

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2020-9-23 21:21 被Heavenml编辑 ,原因:
收藏
免费 2
支持
分享
最新回复 (1)
雪    币: 19
活跃值: (1086)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
不错,简单明了
2020-9-24 10:24
0
游客
登录 | 注册 方可回帖
返回
//