zoukankan      html  css  js  c++  java
  • Linux_x86下NX与ASLR绕过技术(续)

    四、Stack Canaries

    首先看一下Stack Canaries演进历史:

    Stack Guard 是第一个使用 Canaries 探测的堆栈保护实现,它于 1997 年作为 GCC 的一个扩展发布。最初版本的 Stack Guard 使用 0x00000000 作为 canary word。尽管很多人建议把 Stack Guard 纳入 GCC,作为 GCC 的一部分来提供堆栈保护。但实际上,GCC 3.x 没有实现任何的堆栈保护。

    GCC4.1开始,引入了Stack-smashing Protection(SSP,又称 ProPolice),它实现了两个功能:

    1. 栈中插入Canaries,实现栈保护

    2. 变量重排机制,局部变量中的数组放到栈上高地址位置,其它类型变量放到栈上低地址位置,这使得通过溢出覆盖其它变量变得更加困难

    Canaries值的生成,一般有几种方法:

    • Terminator canaries

      由于绝大多数的溢出漏洞都是由那些不做数组越界检查的 C 字符串处理函数引起的,而这些字符串都是以 NULL 作为终结字符的。选择 NULL, CR, LF 这样的字符作为 canary word 就成了很自然的事情。例如,若 canary word 为 0x000aff0d,为了使溢出不被检测到,攻击者需要在溢出字符串中包含 0x000aff0d 并精确计算 canaries 的位置,使 canaries 看上去没有被改变。然而,0x000aff0d 中的 0x00 会使 strcpy() 结束复制从而防止返回地址被覆盖。而 0x0a 会使 gets() 结束读取。插入的 terminator canaries 给攻击者制造了很大的麻烦。

    • Random canaries

      这种 canaries 是随机产生的。并且这样的随机数通常不能被攻击者读取。这种随机数在程序初始化时产生,然后保存在一个未被隐射到虚拟地址空间的内存页中。这样当攻击者试图通过指针访问保存随机数的内存时就会引发 segment fault。但是由于这个随机数的副本最终会作为 canary word 被保存在函数栈中,攻击者仍有可能通过函数栈获得 canary word 的值。

    • Random XOR canaries

      这种 canaries 是由一个随机数和函数栈中的所有控制信息、返回地址通过异或运算得到。这样,函数栈中的 canaries 或者任何控制信息、返回地址被修改就都能被检测到了。

    一张图帮助理解:

    下面通过调试,探索一下GCC中Canaries的具体实现。依然是使用Ubuntu x86环境,gcc version 4.9.2。

    使用的程序代码如下:

    void func()
    {
         int i;
         char buffer[64];
         i = 1;
         buffer[0] = 'a';
    }
    
    int main() 
    {
         func();
         return 0;
    }

    分别编译开启栈保护和去除栈保护的程序:

    ez@ubuntu:~/workdir/Canaries$ gcc -fstack-protector -o demo_sp demo.c

    ez@ubuntu:~/workdir/Canaries$ gcc -fno-stack-protector -o demo_nosp demo.c

    分别展示func函数的反汇编代码。

    无栈保护代码:

    (gdb) disass func 
    Dump of assembler code for function func:
       0x080483eb <+0>: push   %ebp
       0x080483ec <+1>: mov    %esp,%ebp
       0x080483ee <+3>: sub    $0x50,%esp
       0x080483f1 <+6>: movl   $0x1,-0x4(%ebp)
       0x080483f8 <+13>: movb   $0x61,-0x44(%ebp)
       0x080483fc <+17>: leave  
       0x080483fd <+18>: ret    
    End of assembler dump.
    (gdb)

    观察到,使用-fno-stack-protector选项编译的程序,栈上没有任何保护措施。

    开启栈保护代码:

    (gdb) disass func
    Dump of assembler code for function func:
       0x0804843b <+0>: push   %ebp
       0x0804843c <+1>: mov    %esp,%ebp
       0x0804843e <+3>: sub    $0x58,%esp
       0x08048441 <+6>: mov    %gs:0x14,%eax     #读取gs寄存器,生成Canaries
       0x08048447 <+12>: mov    %eax,-0xc(%ebp)    #在栈底部写入Canaries
       0x0804844a <+15>: xor    %eax,%eax
       0x0804844c <+17>: movl   $0x1,-0x50(%ebp)
       0x08048453 <+24>: movb   $0x61,-0x4c(%ebp)
       0x08048457 <+28>: mov    -0xc(%ebp),%eax
       0x0804845a <+31>: xor    %gs:0x14,%eax    #函数返回前,检查Canaries值
       0x08048461 <+38>: je     0x8048468 <func+45>    #若未改变,跳到+45处正常返回
       0x08048463 <+40>: call   0x8048310 <__stack_chk_fail@plt>    #若发生栈溢出,执行__stack_chk_fail函数
       0x08048468 <+45>: leave  
       0x08048469 <+46>: ret    
    End of assembler dump.
    (gdb)

    其中,从gs寄存器中读取的值,每次函数调用都是随机的,我们使用GDB调试验证之:

    (gdb) b *0x08048447
    Breakpoint 4 at 0x8048447
    (gdb) r
    Starting program: /home/ez/workdir/Canaries/demo_sp

    Breakpoint 4, 0x08048447 in func ()
    (gdb) i r eax
    eax            0xa3850c00 -1551561728
    (gdb) r
    Starting program: /home/ez/workdir/Canaries/demo_sp

    Breakpoint 4, 0x08048447 in func ()
    (gdb) i r eax
    eax            0xcc46de00 -867770880

    通过跟踪__stack_chk_fail函数可以发现,它的实现比较复杂。大体流程是,首先调用__GI___fortify_fail函数,__GI___fortify_fail又调用__libc_message函数,__libc_message的最后调用backtrace_and_maps和__GI_abort函数,产生SIGABRT信号,并通过__GI___libc_secure_getenv根据系统环境变量决定是否产生coredump文件,__GI_abort执行到最后调用_exit,程序退出。

    关于Canary名称的由来,我搜到一则有趣的小故事,矿井中的金丝雀

    五、总结

      1. 所有具有任意代码执行能力的exp,均要绕过上述防护机制,本文只是拿缓冲区溢出举例,方法是通用的;

      2. 漏洞利用的关键是控制IP寄存器,但并不一定要直接覆盖,内核中大量的Ops结构,虚函数表,异常处理函数,GOT等都是很好的目标;

  • 相关阅读:
    Connection parameters are correct , SSL not enabled
    log4j配置文件的详解
    java.lang.IllegalArgumentException: addChild: Child name '/SSHE' is not unique
    MYSQL的三种注释
    Oracle19c 单节点ASM 存储模式数据库实例搭建过程
    [专题]中立遭质疑,提价遭反对,ARM的生存难题怎么破?
    快速排序的理解
    chrome审查元素功能,web开发强大帮手
    MyEclipse Server view报错解决方法
    把Java程序打包成jar文件包并执行
  • 原文地址:https://www.cnblogs.com/gm-201705/p/9901570.html
Copyright © 2011-2022 走看看