PLT与GOT
0x01 什么是PLT和GOT
名称:
- PLT : 程序链接表(PLT,Procedure Link Table)
- GOT : 重局偏移表(GOT, Global Offset Table)
缘由:
这缘起于动态链接,动态链接需要考虑的各种因素,但实际总结起来说两点:
- 需要存放外部函数的数据段 —— PLT
- 获取数据段存放函数地址的一小段额外代码 —— GOT
如果可执行文件中调用多个动态库函数,那每个函数都需要这两样东西,这样每样东西就形成一个表,每个函数使用中的一项。
存放函数地址的数据表,称为全局偏移表(GOT, Global Offset Table),而那个额外代码段表,称为程序链接表(PLT,Procedure Link Table)。
内容:
举个例子,对于一个函数,这里命名为common,其plt如下:
080482a0 <common@plt>:
80482a0: pushl 0x80496f0
80482a6: jmp *0x80496f4
...
第一句,pushl 0x80496f0,是将地址压到栈上,也即向最终调用的函数传递参数。
第二句,jmp *0x80496f4,这是跳到最终的函数去执行,不过猜猜就能想到,这是跳到能解析动态库函数地址的代码里面执行。
0x80496f4属于GOT表中的一项,进程还没有运行时它的值是0x00000000,当进程运行起来后,它的值变成了0xf7ff06a0。
如果做更进一步的调试会发现这个地址位于动态链接器内,对应的函数是_dl_runtime_resolve。(相应的过程图在下面贴出)
如果将PLT和GOT抽象起来描述,可以写成以下的伪代码:
plt[0]:
pushl got[1]
jmp *got[2]plt[n]: // n >= 1
jmp *got[n+2]// GOT前3项为公共项,第3项开始才是函数项,plt[1]对应的GOT[3],依次类推
push (n-1)*8
jmp plt[0]—————————————————————————————————————————
got[0] = address of .dynamic section
//本ELF动态段(.dynamic段)的装载地址
got[1] = address of link_map object( 编译时填充0)//本ELF的link_map数据结构描述符地址
got[2] = address of _dl_runtime_resolve function (编译时填充为0)//_dl_runtime_resolve函数的地址
got[n+2] = plt[n] + 6 (即plt[n]代码片段的第二条指令)
特点:
PLT表结构有以下特点:
PLT表中的第一项为公共表项,剩下的是每个动态库函数为一项(当然每项是由多条指令组成的,jmp *0xXXXXXXXX这条指令是所有plt的开始指令)
每项PLT都从对应的GOT表项中读取目标函数地址
GOT表结构有以下特点:
GOT表中前3个为特殊项,分别用于保存 .dynamic段地址、本镜像的link_map数据结构地址和_dl_runtime_resolve函数地址;
但在编译时,无法获取知道link_map地址和_dl_runtime_resolve函数地址,所以编译时填零地址,进程启动时由动态链接器进行填充3个特殊项后面依次是每个动态库函数的GOT表项
注意点:
以printf函数为例,三个问题:
- _dl_runtime_resolve是怎么知要查找printf函数的
- _dl_runtime_resolve找到printf函数地址之后,它怎么知道回填到哪个GOT表项
- 到底_dl_runtime_resolve是什么时候被写到GOT表的
printf@plt>:
jmp *0x80496f8
push $0x00
jmp common@plt
每个xxx@plt的第二条指令push的操作数都是不一样的,它就相当于函数的id,动态链接器通过它就可以知道是要解析哪个函数了。
它俩的运行关系如下:
0x02 重定位
重定位分为以下三种:
- 链接重定位:将一个或多个中间文件(.o文件)通过链接器将它们链接成一个可执行文件。其中分为两种情况:
- 如果是在其他中间文件中已经定义了的函数,链接阶段可以直接重定位到函数地址
- 如果是在动态库中定义了的函数,链接阶段无法直接重定位到函数地址,只能生成额外的小片段代码,也就是PLT表,然后重定位到该代码片段
- 运行重定位:运行后加载动态库,把动态库中的相应函数地址填入GOT表,由于PLT表是跳转到GOT表的,这就构成了运行时重定位
- 延迟重定位:只有动态库函数在被调用时,才会进行地址解析和重定位工作,这时候动态库函数的地址才会被写入到GOT表项中,过程如下图:
PLT属于代码段,在进程加载和运行过程都不会发生改变,PLT指向GOT表的关系在编译时已完全确定,唯一能发生变化的是GOT表。
示例:
重定位时:
重定位后:
0X03 在PWN中的应用 —— ret2libc
应用场景:
在一些提供单独 libc(版本号).so的pwn题中,大部分情况是要在这个so文件中寻找一些函数的偏移地址,而且大部分情况下,为了方便,只会使用已经在程序中出现的函数的got表中的实际地址,我们可以直接把这个so文件拖进IDA中进行寻找,
经典的例题如Jarvis oj上面的pwn level3,这里只给出较好的wp地址,可以看到,用read函数写入,然后return已经使用过一次的write函数的plt地址,从而调用这个函数(之后的那个padding是系统call用来跳转执行的下一个地址,可以deadbeef也可以换成想要执行的函数地址),继而是对ret的这个write函数的参数进行输入,其中第二个参数就是要输出在显示屏上的内容,因此我们填入write的got表地址,输出write的真实地址,进而基地址就可以由 基地址= 真实地址-偏移地址算出。
PLT与GOT的更多相关文章
- elf文件中的.plt .rel.dyn .rel.plt .got .got.plt的关系
.plt的作用是一个跳板,保存了某个符号在重定位表中的偏移量(用来第一次查找某个符号)和对应的.got.plt的对应的地址 .rel.dyn重定向表,在程序启动时就需要重定位完成. .rel.plt保 ...
- plt和got
最近在学习linux高级调试技术.下面就动态库连接这块做了一个实验 首先理解下plt是procedure linkage table,got是global offset table.got表中存放的是 ...
- 动态链接库中函数的地址确定---PLT和GOT [转]
前面写过动态链接库 延迟绑定的一篇博文,那篇文章我非常喜欢,但是当时刚搞清楚,自己写的比较凌乱,我最近学习了Ulrich Drepper的How to write share library,学习了几 ...
- (原)python中使用plt.show()时显示图像
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/6039667.html 参考网址: http://matplotlib.org/users/shell. ...
- 基于Android的ELF PLT/GOT符号和重定向过程ELF Hook实现(by 低端农业代码 2014.10.27)
介绍 技术原因写这篇文章,有两种: 一个是在大多数在线叙述性说明发现PLT/GOT第二十符号重定向过程定向x86的,例<Redirecting functions in shared ELF l ...
- [Q]将图纸转换为JPG、PNG、plt、DWF、DWFx,XPS等格式文件
如要将图纸打印为图片,请选择“PublishToWeb JPG.pc3”或“PublishToWeb PNG.pc3”打印机. 如要将图纸打印为plt格式文件,请选择“Windows Default ...
- PLT文件 和 DXF文件
PLT: CAM/CAD类似软件处理的图像文件的文件格式 DXF: AutoCAD(Drawing Interchange Format或者Drawing Exchange Format) 绘图交换文 ...
- 深入了解GOT,PLT和动态链接
之前几篇介绍exploit的文章, 有提到return-to-plt的技术. 当时只简单介绍了 GOT和PLT表的基本作用和他们之间的关系, 所以今天就来详细分析下其具体的工作过程. 本文所用的依然是 ...
- Linux Debugging(七): 使用反汇编理解动态库函数调用方式GOT/PLT
本文主要讲解动态库函数的地址是如何在运行时被定位的.首先介绍一下PIC和Relocatable的动态库的区别.然后讲解一下GOT和PLT的理论知识.GOT是Global Offset Table,是保 ...
- ELF 文件 动态连接 - 延迟绑定(PLT)
PLT 全称:Procedure Linkage Table ,直译:过程连接表 由于在动态连接中,程序的模块之间包含了大量的函数引用,所以在程序开始执行前,动态链接会耗费较多的时间用于模块之间函数引 ...
随机推荐
- php 二维数组相同值 相加
array(3) { [0]=> array(2) { ["sourcesid"]=> int(1) ["addusernum"]=> str ...
- 细谈unity资源管理的设计
一.概要 本文主要说说Unity是如何管理的,基于何种方式,基于这种管理方式,又该如何规划资源管理,以及构建bundle,是后面需要详细讨论的. 二.Unity的资源管理方式 2.1 资源分类 uni ...
- Win8 Metro(C#)数字图像处理--2.67图像最大值滤波器
原文:Win8 Metro(C#)数字图像处理--2.67图像最大值滤波器 [函数名称] 最大值滤波器WriteableBitmap MaxFilterProcess(WriteableBi ...
- ORACLE RAC+OGG配置
实验环境主机名 IP地址rac01 192.168.56.10rac02 192.168.56.20rac-scan 192.168.56.30 目标库:ora-ogg 192. ...
- 智能合约开发——以太坊 DApp 实现 购买通证token
合约的buy()方法用于提供购买股票的接口.注意关键字payable,有了它买股票的人才可以付钱给你. 接收钱没有比这个再简单的了! function buy() payable public ret ...
- Delphi使用android的NDK是通过JNI接口,封装好了,不用自己写本地代码,直接调用
一.Android平台编程方式: 1.基于Android SDK进行开发的第三方应用都必须使用Java语言(Android的SDK基于Java实现) 2.自从ndk r5发布以后, ...
- NPOI 超简单的导出导入
首先说说,第一次遇到过匿名导出的那个时候是在我在北京第一家公司,简单的声明一个对象就可以导出,那时候感觉高大上,自己也想研究研究,但是因为头将代码后来加密了根本看不到.好吧,研究了研究放弃了,后来 ...
- SpringBoot整合日志框架LogBack
日志可以记录我们应用程序的运行情况,我们可以通过日志信息去获取应用程序更多的信息.常用处理java日志的组件有:slf4j.log4j.logback.common-logging等.其中log4j是 ...
- 【LEETCODE】32、LeetCode的第35题,查找插入的位置
凉凉,看来想做好一个题还不容易啊... 有点难受... 1.看看题目吧 Given a sorted array and a target value, return the index if the ...
- 浅谈ASP.NET Core中IOC与DI的理解和使用
说起IOC和DI,使用过ASP.NET Core的人对这两个概念一定不陌生,早前,自己也有尝试过去了解这两个东西,但是一直觉得有点很难去理解,总觉得对其还是模糊不清,所以,趁着今天有空,就去把两个概念 ...