0x5.4 浅析Linux下程序装载SO共享库机制
刚开始学PWN的时候,学习到retlibc,其实还不是很理解一些got表,plt表的东西,也就只是按照大家的payload来使用了,下面让我们深入浅出来学习一番程序是如何调用libc里面的函数的。
关于这类型的文章google一大堆,这里我简要谈下一些关键的知识点。
libc.so 是什么?
libc.so 是linux下C语言库中的运行库glibc的动态链接版, 其中包含了大量可利用的函数。
什么是动态链接(Dynamic linking)?
动态链接是指在程序装载的时通过动态链接器将程序所需的所有动态链接库(so等)装载至进程空间中。当程序运行时才将他们链接在一起形成一个完整的程序,这样就比静态链接节约内存和磁盘空间,而且具有更高的扩展性。
动态链接库: Linux系统中ELF动态链接文件被称为动态分享对象(Dynamic Shared Objects),也就是共享对象,一般以’.so’扩展名结尾,libc.so就是其中一个例子。window则是’.dll’之类的。
Linux编译共享文件命令:
gcc got_extern.c -fPIC -shared -m32 -o my.so
-fPIC 选项是生成地址无关代码的代码,gcc 中还有另一个 -fpic 选项,差别是fPIC产生的代码较大但是跨平台性较强而fpic产生的代码较小,且生成速度更快但是在不同平台中会有限制。一般会采用fPIC选项
地址无关代码的思想就是将指令分离出来放在数据部分。
-shared 选项是生成共享对象文件
-m32 选项是编译成32位程序
-o 选项是定义输出文件的名称
什么是延迟绑定(Lazy Binding)?
因为如果程序一开始就将共享库所有函数都进行链接会浪费很多资源,因此采用了延迟绑定技术,函数需要用到的时候进行绑定,否则不绑定。
那么怎么实现绑定,用动态链接器,绑定什么呢,修改got表,怎么来延迟呢,利用plt表当作一个摆设然后重定位指向GOT表中真实的地址。
首先我们了解下什么是got表、什么是plt表,什么是动态链接器,以及三者的关系。
GOT(Global offset Table) 全局偏移表
存放函数真实的地址,能被动态链接器实时修改
GOT表被ELF拆分为.got 和 .got.plt表,其中.got
表用来保存全局变量引用的地址,.got.plt
用来保存函数引用的地址,外部函数的引用全部放在.got.plt中,我们主要研究也就是这部分。
先记住got表,第一项是.dynamic
,第二项是link_map
地址,第三项是_dl_runtime_resolve()
,真正的外部函数地址是从第4项开始的也就是got[3]开始。
关于got表结构这部分,后面在高级ROP部分我会展开讲解。
PLT(Procedure Link Table ) 程序连接表
表项都是一小段代码,一一对应对应于got表中的函数。