缓冲区溢出攻击

 缓冲区溢出攻击


        //在这里定义任意的合法汇编代码
        
    }
END:
    //确定代码范围
    UINT begin,end;
    __asm
    {
        mov eax,BEGIN ;
        mov begin,eax ;
        mov eax,END ;
        mov end,eax ;
    }
    //输出
    int len=end-begin;
    memcpy(buffer,(void*)begin,len);
        //四字节对齐
    int fill=(len-len%4)%4;
    while(fill--)buffer[len+fill]=0x90;
    //返回长度
    return len+fill;
}
 

因为C++是支持嵌入式汇编代码的,因此在函数内的汇编代码都会被整成编译为二进制代码。实现二进制转换的基本思想是读取编译器最终生成的二进制代码段数据,将数据导出到指定的缓冲区内。为了锁定嵌入式汇编代码的位置和长度,我们定义了两个标签BEGINEND。这两个标签在汇编语言级别会被解析为实际的线性地址,但是在高级语言级是无法直接使用这两个标签值的,只能使用goto语句跳转使用它们。但是我们可以顺水推舟,使用两个局部变量在汇编级记录这两个标签的值!

 
//确定代码范围
UINT begin,end;
__asm
{
    mov eax,BEGIN ;
    mov begin,eax ;
    mov eax,END ;
    mov end,eax ;
}
 

这样就可以得到嵌入式汇编的代码范围了,使用memcpy操作将代码数据拷贝到目标缓冲区即可(后边还用nop指令将代码按照四字节对齐)。不过我们还需要注意一个问题,嵌入式汇编在函数执行时也会执行,这显然不可以,我们只是把它当作数据而已(是数据?还是代码?),因此在函数开始的地方我们使用goto语句直接跳转到嵌入式会变语句的结尾——END标签!

七、攻击测试

按照上述内容,相信不难构造出一个简单的shellcode并攻击之前提供的漏洞函数。但是如果使用VS2010测试的话可能会碰到很多问题。经过大量的调试和资料查询,我们需要设置三处VS的项目属性。

1、配置->配置属性->C/C++->基本运行时检查=默认值,避免被检测栈帧失衡。

2、配置->配置属性->C/C++->缓冲区安全检查=否,避免识别缓冲区溢出漏洞。

3、配置->配置属性->链接器->高级->数据执行保护(DEP)=否,避免堆栈段不可执行。

从 这三处设置看来,目前的编译器已经针对缓冲区溢出攻击做了大量的保护工作(显然这会降低程序的执行性能,因此允许用户配置),使得传统的缓冲区溢出攻击变 得没那么“猖狂”了,但是在计算机安全领域,“道高一尺,魔高一丈”,总有人会找到更隐蔽的攻击方式让编译器开发者措手不及。本文除了分析缓冲区溢出攻击 的原理之外,更希望读者能从中感受到代码安全的重要性,并结合编译器提供的安全功能让自己的代码更加安全高效。

 

 

 

原文地址:https://www.cnblogs.com/Leo_wl/p/3250756.html