博客网址:www.shicoder.top
微信:kj11011029
欢迎加群聊天 :452380935
这一次我们来对plt
和got
进行讲解
我们都知道这两个表都是针对动态链接时候要使用的,我们看下下面这个例子
#include <stdio.h>
void print_banner()
{
printf("Welcome to World of PLT and GOT\n");
}
int main(void)
{
print_banner();
return 0;
}
我们对生成的可执行文件进行反编译看下
printf
函数因为是glibc
里面的,所以可以看到此时的printf
函数的地址并不知道,而是使用fcffffff
来代替,那么具体怎么找到printf
函数的具体地址,就需要plt
和got
表,但是比如说,现在在执行这个可执行文件,肯定编译好的可执行文件此时的地址不知道,采用一个其他东西,此时用地址other
来代替,那么假如在执行过程中知道了具体地址,也不可能把这个地址再填写到可执行文件中去,因为代码段是只读的,那么就需要把那个other
地址设置为一个特殊的值,而这个值就是printf
在plt
的地址
.text
...
call printf@plt:
...
printf@plt:
mov eax [printf@got]
jmp eax
.data
...
printf@got ; 里面存放了printf的具体地址
下面的图展示了具体过程
那么假如一个可执行文件有很多glibc
中的函数,那plt
和got
是一开始就初始化的吗,当然不是,这就是延迟绑定机制,只有动态库函数在被调用时,才会地址解析和重定位工作,先来看几张图
其中plt
的第一项是针对第一次调用函数时候,去寻找函数的具体位置
因此比如ret2libc1-2
中的两个题目,我们不知道system
的具体地址,但是我们去call system@plt
也可以知道,而针对retlibc3
,因为我们不知道system
的具体地址,我们的想法是想得到put
的具体地址,然后通过put
和system
在libc
中的相对偏移,来计算system
的具体地址,但是如果我们直接call put@plt
,虽然是达到了call put
,但是我们还是不能知道put
的具体地址,因此就需要进行泄露,因为got
表中存放的是put
的真实地址,因此我们给程序比如0x100000
(这个地址是put@got
)的地址,然后程序返回0x100000
里面存放的具体值,而这个值就是put
的真实地址
评论 (0)