怎么深入理解GOT表和PLT表

0x01 前言

操作系统通常使用动态链接的方法来提高程序运行的效率。在动态链接的情况下,程序加载的时候并不会把链接库中所有函数都一起加载进来,而是程序执行的时候按需加载,如果有函数并没有被调用,那么它就不会在程序生命中被加载进来。这样的设计就能提高程序运行的流畅度,也减少了内存空间。而且现代操作系统不允许修改代码段,只能修改数据段,那么GOT表与PLT表就应运而生。

0x02 初探GOT表和PLT表

我们先简单看一个例子

怎么深入理解GOT表和PLT表

我们跟进一下scanf@plt

怎么深入理解GOT表和PLT表

会发现,有三行代码

jmp 一个地址push 一个值到栈里面jmp 一个地址

看函数的名字就可以知道这是scanf函数的plt表,先不着急去了解plt是做什么用的,我们继续往下看我们先看一下第一个jmp是什么跳到哪里。

怎么深入理解GOT表和PLT表

其实这是plt表对应函数的got表,而且我们会发现0x201020的值是压栈命令的地址,其他地方为0,此时就想问:

一、got表与plt表有什么意义,为什么要跳来跳去?

二、got表与plt表有什么联系,有木有什么对应关系?

那么带着疑问先看答案,再去印证我们要明白操作系统通常使用动态链接的方法来提高程序运行的效率,而且不能回写到代码段上。

在上面例子中我们可以看到,call scanf —> scanf的plt表 —>scanf的got表,至于got表的值暂时先不管,我们此刻可以形成这样一个思维,它能从got表中找到真实的scanf函数供程序加载运行。

我们这么认为后,那么这就变成了一个间接寻址的过程

怎么深入理解GOT表和PLT表

我们就把获取数据段存放函数地址的那一小段代码称为PLT(Procedure Linkage Table)过程链接表存放函数地址的数据段称为GOT(Global Offset Table)全局偏移表。我们形成这么一个思维后,再去仔细理解里面的细节。

0x03 再探GOT表和PLT表

已经明白了这么一个大致过程后,我们来看一下这其中是怎么一步一步调用的上面有几个疑点需要去解决:

一、got表怎么知道scanf函数的真实地址?

二、got表与plt表的结构是什么?我们先来看plt表刚才发现scanf@plt表第三行代码是 jmp 一个地址 ,跟进看一下是什么

怎么深入理解GOT表和PLT表

其实这是一个程序PLT表的开始(plt[0]),它做的事情是:

push got[1]jmp **got[2]

后面是每个函数的plt表。此时我们再看一下这个神秘的GOT表

怎么深入理解GOT表和PLT表

除了这两个(printf和scanf函数的push 0xn的地址,也就是对应的plt表的第二条代码的地址),其它的got[1], got[2] 为0,那么plt表指向为0的got表干什么呢?因为我们落下了一个条件,现代操作系统不允许修改代码段,只能修改数据段,也就是回写,更专业的称谓应该是运行时重定位。我们把程序运行起来,我们之前的地址和保存的内容就变了在这之前,我们先把链接时的内容保存一下,做一个对比

怎么深入理解GOT表和PLT表

② 寻找printf的plt表③ jmp到plt[0]④ jmp got[2] -> 0x00000⑤⑥ printf和scanf的got[3] got[4] -> plt[1] plt[2]的第二条代码的地址⑦⑧ 证实上面一点

运行程序,在scanf处下断点

怎么深入理解GOT表和PLT表

可以发现,此时scanf@plt表变了,查看got[4]里内容

怎么深入理解GOT表和PLT表

依然是push 0x1所在地址继续调试,直到这里,got[4]地址被修改

怎么深入理解GOT表和PLT表

此时想问了,这是哪里?

怎么深入理解GOT表和PLT表

怎么深入理解GOT表和PLT表

然后就是got[2]中call<_dl_fixup>从而修改got[3]中的地址;

那么问题就来了,刚才got[2]处不是0吗,怎么现在又是这个(_dl_runtime_resolve)?这就是运行时重定位。

其实got表的前三项是:

got[0]:address of .dynamic section 也就是本ELF动态段(.dynamic段)的装载地址got[1]:address of link_map object( 编译时填充0)也就是本ELF的link_map数据结构描述符地址,作用:link_map结构,结合.rel.plt段的偏移量,才能真正找到该elf的.rel.pltgot[2]:address of _dl_runtime_resolve function (编译时填充为0) 也就是_dl_runtime_resolve函数的地址,来得到真正的函数地址,回写到对应的got表位置中。

那么此刻,got表怎么知道scanf函数的真实地址?

这个问题已经解决了。我们可以看一下其中的装载过程:

怎么深入理解GOT表和PLT表

怎么深入理解GOT表和PLT表

说到这个,可以看到在_dl_runtimw_resolve之前和之后,会将真正的函数地址,也就是glibc运行库中的函数的地址,回写到代码段,就是got[n](n>=3)中。也就是说在函数第一次调用时,才通过连接器动态解析并加载到.got.plt中,而这个过程称之为延时加载或者惰性加载。

到这里,也要接近尾声了,当第二次调用同一个函数的时候,就不会与第一次一样那么麻烦了,因为got[n]中已经有了真实地址,直接jmp该地址即可。

上述内容就是怎么深入理解GOT表和PLT表,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。

文章标题:怎么深入理解GOT表和PLT表,发布者:亿速云,转载请注明出处:https://worktile.com/kb/p/30008

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022年9月26日 上午2:03
下一篇 2022年9月26日 上午2:05

相关推荐

  • SpringBoot怎么进行整合Druid数据源

    1.自定义方式 使用自定义方式整合Druid 1.添加依赖 在pom.xml添加相关依赖 <!–数据库相关–> <dependency> <groupId>org.springframework.boot</groupId> <artifac…

    2022年9月15日
    8900
  • vlookup函数如何使用

    vlookup函数使用方法 vlookup 的作用: vlookup 用于查找指定值所对应的另一个值。例如:查找某件产品的价格,某个同学的某科成绩等。 vlookup 函数表示: =vlookup(要查找的值,查找区域,返回值所在列号,精确匹配或近似匹配) 参数说明: 1、要查找的值:可以引用单元格…

    2022年9月21日
    7100
  • php进程通信之信号量的用途是什么

    常见进程通信方式 一些理论基础 临界资源:每次仅允许一个进程访问的资源。 临界区:每个进程中访问临界资源的那段代码叫临界区 所谓临界区(也称为临界段)就是访问和操作共享数据的代码段。 进程互斥:两个或以上的进程不能同时进入关于同一组共享变量的临界区域,即一个进程正在访问临界资源,另一个进程要想访问必…

    2022年9月2日
    6300
  • HTML的p标签可不可以不用align

    HTML中的p标签可以不用align属性;因为该属性在“HTML 4.01”中已经被废弃,在HTML5中已经不支持该属性了,可以使用css进行替代该属性,该属性用于规定段落中文本的对齐方式。 本教程操作环境:windows10系统、HTML5版本、Dell G3电脑。 HTML的p标签可以不用ali…

    2022年9月2日
    7400
  • windows steam错误代码105如何解决

    steam错误代码105解决方法: 1、首先打开steam设置,然后点击左侧的“网页浏览器”。 2、然后选择“删除网页浏览器缓存”,再点击“删除所有浏览器cookie”。 3、右击右下角网络,点击属性然后进入网络选项,双击“Internet协议版本4”。 4、随后可以进入dns修改界面,此时可以设置…

    2022年8月31日
    16200
  • mdf文件如何开启

    mdf文件打开方法: 1、下载一个SQLServer管理工具。 2、下载好开始安装。 3、完成后点击“导入连接”。 4、找到需要打开的mdf文件点击“打开”即可。 5、打开列表即可看到mdf文件。 到此,相信大家对“mdf文件如何开启”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关…

    2022年9月8日
    6200
  • Git远程仓库配置SSH怎么实现

    1. 设置本地git账户邮箱和用户名 输入命令git config –global user.name “Git账号”以及git config –global user.email “Git邮箱”。 输入命令git config –global –list,查看配置是否正确。 2. 生成新的…

    2022年9月20日
    7500
  • windows任务管理器怎么打开

    任务管理器打开的详细方法 方法一:右键点击任务栏空白处,然后点击“任务管理器”即可。 方法二:同时按下“Win+R”键,然后在弹出的对话框中输入“cmd”并按回车键。 接着在任务管理器输入“taskmgr”运行即可。 方法三:同时按下“Ctrl+Alt+Delete”键即可。 方法四、按“WIN+X…

    2022年9月5日
    5700
  • html中头部标签是什么

    html中“<head>”是头部标签。head标签用于定义文档的头部,它是所有头部元素的容器;文档的头部描述了文档的各种属性和信息,包括文档的标题、在Web中的位置以及和其他文档的关系等。head中的元素有base、link、meta、script、style、title。 本教程操作环…

    2022年9月15日
    18600
  • Word字体放大如何操作

    Word字体放大的方法 1、首先电脑打开word文档。 2、然后选中自己要放大的文字。 3、选中要放大的文字后,同时按住Ctrl+SHift+>就可以把文字无限放大, 想放多大就可以放多大。 4、选中文字按Ctrl+Shift+<就可以缩小文字 关于“Word字体放大如何操作”这篇文章的…

    2022年9月15日
    6300
联系我们
关注微信
关注微信
分享本页
返回顶部
PingCode 比 Jira 更好用的研发管理工具。免费试用         站点及SEO合作,请添加微:All-FeiFei