【PWN基础】动态链接和延迟绑定
动态链接和延迟绑定
静态链接
在链接时,将生成的目标文件.o 和需要引用的库文件一起打包到可执行文件中。
此时静态库可以理解为一组目标文件的集合,即很多目标文件压缩打包后形成的文件。
静态链接的特点:
- 程序运行时与函数库没有关系了,移植性更好
- 资源冗余
- 在编译的时候就发生了
动态链接
静态库的空间浪费是一个严重的问题。
程序1和2在静态编译时包含了同样的库函数,但其实不必让每个程序都包含外部连接库,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例即可。
动态库的程序在程序运行时才会被载入,规避了空间浪费的问题。
延迟绑定
提出延迟绑定的概念,是因为:动态链接太慢了。
动态链接比静态链接要慢1%~5%, 原因是:动态链接的工作在运行时完成,每次程序开始运行,动态链接器都要进行一次链接工作,而大量的重定位等复杂操作减慢了启动速度。(所谓链接工作,本质上是找到函数的地址)
为了解决这个问题,延迟绑定被提出。
延迟绑定:函数第一次被用到时,再进行绑定。
ELF使用 PLT(Procedure Linkage Table,过程链接表)技术来实现延迟绑定。
延迟绑定的实现
大方向
引入GOT表 和 PLT表两个核心概念。
首先需要了解的是:当调用外部函数时,如果是第一次调用该函数,会调用链接器,来解析该外部函数的地址,并填入got表中,再跳转到该函数。后续调用该函数,就直接从got表获取地址跳转。
.got
GOT(Global Offset Table,全局偏移表),保存所有外部符号的地址信息。(为全局变量,外部函数等保存地址信息)。
(个人理解:对于变量AAA,使用者借助于GOT表,找到其真实地址)
GOT表除了保存映射信息以外,还保存三个基本信息:
- got[0] :本ELF .dynamic 段的装载地址
- got[1] :ELF
link_map
数据结构描述符的地址 - got[2] :
_dl_runtime_resolve
函数的地址
这三个基本信息的用途,是帮助我们找到符号的真实地址。