网站界面设计策划书怎么做,云匠网订单多吗,潍坊市网站建设,wordpress 购物 手机站动态链接库
我们程序开发过程中都会用到系统函数#xff0c;比如read#xff0c;write#xff0c;open等等 这些系统函数不需要我们实现#xff0c;因为系统已经帮你完成这些工作#xff0c;只需要调用即可#xff0c;存放这些函数的库文件就是动态链接库。 通常情况下比如readwriteopen等等 这些系统函数不需要我们实现因为系统已经帮你完成这些工作只需要调用即可存放这些函数的库文件就是动态链接库。 通常情况下我们对于pwn题接触到的动态链接库就是libc.so文件:
静态编译与动态编译
这里我们举一个例子来类比静态编译与动态编译的概念。 小明要开一个餐馆(program)餐馆的菜单上有几百种菜肴(函数)小明的餐馆每天都会来很多顾客每个顾客点的菜都可能不一样。我们知道每道菜所需要的食材(系统函数)都不一样这些食材都存放于仓库(动态链接库)中。 那么现在问题来了小明如何保证每个顾客点的菜都能被满足呢?
第一种方式:
小明把仓库中所有的食材都搬进厨房(静态编译) 这时小明不需要挪地方(静态)只需要在厨房中就可以工作但是这会带来冗余可能厨房中的食材很多都用不上。 第二种方式:
小明每次遇到新的所需要的食材才去仓库取(动态编译) 这时小明可能挪动的比较频繁(动态)但是可以保证厨房里面没那么多可能用不到的东西。
静态编译
一个程序运行过程中可能会调用许许多多的库函数这些库函数在一次运行过程中不能保证全部被调用。 静态编译的思路就是将所有可能运行到的库函数一同编译到可执行文件中 这一方式的优点就在于在程序运行中不需要依赖动态链接库。适用的场合就是比如你本地编译的程序需要的动态链接库版本比较特殊如果在别的机器上运行可能对方动态链接库版本和你不一样会出bug这时候用静态编译。 缺点就是编译过后程序体积很大编译速度也很慢
动态编译
一个程序运行过程中会调用许许多多的库函数这些库函数在一次运行过程中不能保证全部被调用。 动态编译的思路就是逢山开路遇水架桥直到遇到需要调用库函数的时候再去动态链接库中寻找 所以其优点之一是缩小了执行文件本身的体积另一方面是加快了编译速度,节省了系统资源 缺点一是哪怕是很简单的程序只用到了链接库里的一两条命令也需要附带一个相当庞大的链接库二是如果其他计算机上没有安装对应的运行库则用动态编译的可执行文件就不能运行。
延迟绑定 我们再回去看看小明:小明说我选择第二种方式(动态编译) 但是小明餐馆开业后发现搞不赢每次都要去仓库找太麻烦了 于是乎小明想到:每次我遇到新的食材我就去仓库找但是每次找完我就在小本子(got表)上记录这个食材的地址这样下一次找就快很多了!
而存放这个地址的小本子就是got表。
这就是linux的延迟绑定机制got表全称是Global Offset Table也就是全局偏移量表。 在程序运行时got表初始并不保存库函数的地址只有在第一次调用过后程序才将这一地址保存在got表中。 PLT与GOT
GOT(Global Offset Table全局偏移表) GOT 是数据段用于地址无关代码的 Linux ELF 文件中确定全局变量和外部函数地址的表。ELF 中有 .got 和 .plt.got 两个 GOT 表.got 表用于全局变量的引用地址.got.plt 用于保存函数引用的地址。 PLT(Procedure Linkage Table程序链接表) PLT 是 Linux ELF 文件中用于延迟绑定的表
不论是第几次调用外部函数程序真正调用的其实是plt表 plt表其实是一段段汇编指令构成
在第一次调用外部函数时plt表首先会跳到对应的got表项中。 由于并没有被调用过此时的got表存储的不是目标函数地址此时的got表中存储的地址是plt表中的一段指令其作用就是准备一些参数进行动态解析。 跳转回plt表后plt表又会跳转回plt的表头表头内容就是调用动态解析函数将目标函数地址存放入got表中。 在之后第二次以上的调用后程序已经完成了延迟绑定got表中已经存储了目标函数地址直接跳转即可