在Linux平台下,elf文件中的got节和plt节在动态链接过程中起着非常重要的作用,学习got节和plt节是在学习elf文件格式过程中必不可少的一部分。所以在此笔记中,记录一下got节和plt节的原理。
使用objdump查看生成的lib.so共享库的的foo函数的反汇编代码
可以看到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”中
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
]
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
]
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
]
396
: ff
25
54
0c
20
00
jmp QWORD PTR [rip
+
0x200c54
]
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
]
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
]
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编辑
,原因: