免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 9129 | 回复: 24

利用堆空间作编译器试验以及对缓冲区溢出的措施(一) [复制链接]

论坛徽章:
0
发表于 2008-08-17 01:53 |显示全部楼层
一、以下是分配一段空间,并假设为编译器对函数的缓冲区溢出作处理的试验。
对缓冲区溢出处理之一是:微软的利用检测 cookie 值来进行处理的技术。


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


/* 函数表的全局符号表,类似 ELF 格式的 GOT 表格 */

void (*fptr[])() = {
        &strcpy,
        &printf
};


void foo()
{
        char s[4];
        (fptr[0])(s, "aksdfjalsfjaslfjaslf");      /* strcpy(),很明显会导致溢出,覆盖返回值 */

        (fptr[1])("I'm foo()\n");
}


int cookie = 0;                        /* cookie 值 */



/*****  出错出处理例程示例 *********/
void do_fault()
{
        printf("do_fault(): buffer overflow! return addres error\n");
        exit(1);
}


/*** 安插 cookie 例程 ****/
void set_cookie_value(int cookie_addr, char *pos)
{
        pos[0] = 0xff;                                /* push cookie */
        pos[1] = 0x35;
        *((int *)&pos[2]) = cookie_addr;
}


/*** 安插cookie检测例程 ***/
void set_check_fun(int cookie_addr, char *pos)
{
        pos[0] = 0x5a;                                /* pop edx */
        pos[1] = 0x39;                                /* cmp [cookie], edx */
        pos[2] = 0x15;
        *((int *)&pos[3]) = cookie_addr;        
        pos[7] = 0x74;                                /* je +9 : ret */
        pos[8] = 0x07;
        pos[9] = 0xbe;                                /* mov esi, do_fault */
        *((int *)&pos[10]) = (int)do_fault;
        pos[14] = 0xff;                                /* call esi */
        pos[15] = 0xd6;
        pos[16] = 0xc3;
}



char *get_ret(char *buf, int len)
{
        while (len-- && (*buf != (char)0xc3))
                buf++;

        if (len)
                return buf;
        else
                return 0;
}


int main()
{

        cookie = (int)time(0);                /* 随机的 cookie 值 */
       
        char *buf = malloc(200);       /* 分配空间用来作编译试验 */

        set_cookie_value((int)&cookie, buf);  /* 在函数头安插 cookie 信息 */

        memcpy(buf+6, foo, 200);
       
        char *p = get_ret(buf+6, 200);
       
        set_check_fun((int)&cookie, p);      /* 在函数尾安插检测例程 */


        ((void (*)())buf)();                 /* 测试 */

    // foo()                          /* 直接调用 foo(),将产生 segmenation fault */
}


上面的代码示例,利用分配的空间,作函数复制过去,然后假设自己为编译器,对 foo() 函数进行 cookie 安插处理,然后调用经过处理后的 foo() 函数,展示 cookie 是如何对缓冲区溢出应对措施

论坛徽章:
0
发表于 2008-08-17 01:56 |显示全部楼层
二、微软的利用 cookie 对缓冲区溢出措施的原理


1、foo() 编译器作处理原理如下:

foo:               <---------- 在此处安插 cookie 值         
        pushl        %ebp
        movl        %esp, %ebp
        subl        $24, %esp
        movl        fptr, %eax
        movl        $.LC0, 4(%esp)
        leal        -4(%ebp), %edx
        movl        %edx, (%esp)
        call        *%eax
        movl        fptr+4, %eax
        movl        $.LC1, (%esp)
        call        *%eax
        leave
        ret                         <---------- 在函数返回前安插检测代码




2、在我写的测试的安插 cookie 处理之后,如下

foo:                
        pushl    cookie                  <---------- 在此处安插 cookie 值
        pushl        %ebp
        movl        %esp, %ebp
        subl        $24, %esp
        movl        fptr, %eax
        movl        $.LC0, 4(%esp)
        leal        -4(%ebp), %edx
        movl        %edx, (%esp)
        call        *%eax
        movl        fptr+4, %eax
        movl        $.LC1, (%esp)
        call        *%eax
        leave

        pop %edx                 <---------- 在函数返回前安插检测代码
        cmpl %edx, cookie
        je 1f
        movl $do_fault, %esi
        call *%esi                /* 出错处理例程 */
1f:
        ret     

论坛徽章:
0
发表于 2008-08-17 01:58 |显示全部楼层
三、运行结果测试

1、在 foo() 函数内加入导致溢出的代码,调用经过编译器安插 cookie 处理例程的 foo()函数,
成功检测错误,显示:
I'm foo()
do_fault(): buffer overflow! return addres error


2、当去掉 foo() 函数内导致溢出的代码后,结果和没有出错一样,显示:
I'm foo()



3、调用未经过编译器安插的 cookie 例程 foo() 函数时,将导致 segmenation fault
I'm foo()
segmentation fault



下一次再来试验:直接检测返回值是否被修改,而不用插入 cookie 值!

论坛徽章:
0
发表于 2008-08-17 02:03 |显示全部楼层
在微软的 VC8 支持产生 cookie 处理的代码,貌似 gcc 没有这种技术。

偶上面写的代码,是根据 cookie 原理,在 linux 下作出一个小试验

论坛徽章:
0
发表于 2008-08-17 02:30 |显示全部楼层
好,LZ有益的探索. 顶一下.

[ 本帖最后由 system888net 于 2008-8-17 02:43 编辑 ]

论坛徽章:
0
发表于 2008-08-17 08:43 |显示全部楼层
gcc一样有,stackguard和stackshieft都可以降低栈受缓冲区溢出攻击的威胁,你上面贴的贴子的方法就是stackguard,但好像不够完整,那个cookie值应该有一个字节为'\0',这样可以防止strcpy这种字符串操作的缓冲区溢出

论坛徽章:
0
发表于 2008-08-17 08:52 |显示全部楼层
原帖由 bobozhang 于 2008-8-17 08:43 发表
gcc一样有,stackguard和stackshieft都可以降低栈受缓冲区溢出攻击的威胁,你上面贴的贴子的方法就是stackguard,但好像不够完整,那个cookie值应该有一个字节为'\0',这样可以防止strcpy这种字符串操作的缓冲区溢出


cookie值应该有一个字节为'\0',说得很正确

论坛徽章:
0
发表于 2008-08-17 09:11 |显示全部楼层
支持做有益的探索

论坛徽章:
0
发表于 2008-08-17 09:31 |显示全部楼层
原帖由 bobozhang 于 2008-8-17 08:43 发表
gcc一样有,stackguard和stackshieft都可以降低栈受缓冲区溢出攻击的威胁,你上面贴的贴子的方法就是stackguard,但好像不够完整,那个cookie值应该有一个字节为'\0',这样可以防止strcpy这种字符串操作的缓冲区溢出

stackguard 应该用什么参数来产生?
cookie 应该是一个整型值,不应是个串。cookie 本身就是为了防止缓冲区溢出,有 '\0' 是多余的。

论坛徽章:
0
发表于 2008-08-17 09:43 |显示全部楼层
gcc果然有溢出保护:
gcc -fstack-protector-all -Wstack-protector yourfile.c
写了一个最简单的测试:

  1. #include <string.h>
  2. int main()
  3. {
  4.         char str[3];
  5.         strcpy(str,"hello");
  6.         return 0;
  7. }
复制代码

执行后输出:
*** stack smashing detected ***: ./a.out terminated
======= Backtrace: =========
/lib/libc.so.6(__fortify_fail+0x48)[0xb7ef0348]
/lib/libc.so.6(__fortify_fail+0x0)[0xb7ef0300]
./a.out[0x8048425]
/lib/libc.so.6(__libc_start_main+0xe0)[0xb7e195c0]
./a.out[0x8048331]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:07 809098     /home/ruan/test/a.out
08049000-0804a000 rw-p 00000000 08:07 809098     /home/ruan/test/a.out
0804a000-0806b000 rw-p 0804a000 00:00 0          [heap]
b7df7000-b7e01000 r-xp 00000000 08:05 51         /lib/libgcc_s-4.1.2-20070821.so.1
b7e01000-b7e02000 rw-p 00009000 08:05 51         /lib/libgcc_s-4.1.2-20070821.so.1
b7e02000-b7e03000 rw-p b7e02000 00:00 0
b7e03000-b7f5a000 r-xp 00000000 08:05 163        /lib/libc-2.8.so
b7f5a000-b7f5c000 r--p 00157000 08:05 163        /lib/libc-2.8.so
b7f5c000-b7f5d000 rw-p 00159000 08:05 163        /lib/libc-2.8.so
b7f5d000-b7f61000 rw-p b7f5d000 00:00 0
b7f7a000-b7f7b000 r-xp b7f7a000 00:00 0          [vdso]
b7f7b000-b7f96000 r-xp 00000000 08:05 156        /lib/ld-2.8.so
b7f96000-b7f97000 r--p 0001a000 08:05 156        /lib/ld-2.8.so
b7f97000-b7f98000 rw-p 0001b000 08:05 156        /lib/ld-2.8.so
bff82000-bff97000 rw-p bffeb000 00:00 0          [stack]

[ 本帖最后由 jamesr 于 2008-8-17 09:46 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP