.NET中对于stackalloc的缓冲区溢出保护

8

来自C# stackalloc的参考资料:

使用stackalloc会自动启用公共语言运行时(CLR)中的缓冲区溢出检测功能。如果检测到缓冲区溢出,则尽快终止进程,以最小化恶意代码执行的可能性。

具体而言,.NET实现了哪种保护机制?
它是否还会检测缓冲区欠载? 对于哪些已知攻击,保护弱一些?


例如,对于MS C ++编译器,可以在此处找到信息:
Windows ISV软件安全防御:

堆栈缓冲区溢出检测功能是在Visual Studio.NET 2002中引入的C/C ++编译器,并在随后的版本中进行了更新。/GS是一个编译器开关,指示编译器添加启动代码以及函数的程序前、后代码,以生成和检查放置在函数堆栈中的随机数。

请注意,Visual C++ 2005(及更高版本)还会重新排列堆栈上的数据,以使其更难以可预测地破坏该数据。例如:
•将缓冲区移动到高于非缓冲区的内存中。此步骤可帮助保护位于堆栈上的函数指针。
•在运行时将指针和缓冲区参数移动到较低的内存中,以减轻各种缓冲区溢出攻击。

1个回答

17

是的,.NET中的Jitter生成了类似于使用Microsoft C/C++编译器的/GS编译器选项生成的本机代码中存在的堆栈canary检查。 基本方案是在方法入口处写入顶部的随机32位值。在方法退出时,它会检查该值是否仍然存在。值的变化非常高地预示着堆栈缓冲区溢出,这是恶意软件用来控制程序的一种方式。

一些可供尝试的代码:

class Program {
    static void Main(string[] args) {
        Kaboom();
    }
    static unsafe void Kaboom() {
        byte* ptr = stackalloc byte[1];
        for (int ix = 0; ix < 42; ++ix) ptr[ix] = 0;
    }
}

运行这段代码时,即使调试器已连接,也会触发Windows错误报告对话框。您可以在输出窗口中看到崩溃原因:

程序“[3636] ConsoleApplication33.exe: Native”已以代码-1073740791(0xc0000409)退出。

异常代码在ntstatus.h SDK头文件中定义:

//
// MessageId: STATUS_STACK_BUFFER_OVERRUN
//
// MessageText:
//
// The system detected an overrun of a stack-based buffer in this application. This overrun could 
// potentially allow a malicious user to gain control of this application.
//
#define STATUS_STACK_BUFFER_OVERRUN      ((NTSTATUS)0xC0000409L)    // winnt

你可以使用调试器窗口中的“调试 + 窗口 + 反汇编”来查看执行此操作的代码。Kaboom 的关键部分如下:

00000000  push        ebp                               ; setup stack frame
00000001  mov         ebp,esp 
00000003  sub         esp,8                             ; stack space for local variables
00000006  xor         eax,eax 
00000008  mov         dword ptr [ebp-8],eax             ; zero-initialize local variables
0000000b  mov         dword ptr [ebp-4],eax 
0000000e  mov         dword ptr [ebp-4],esp
00000011  mov         dword ptr [ebp-8],0EDDB7EDFh      ; canary stored here

// For loop code omitted

0000002d  cmp         dword ptr [ebp-8],0EDDB7EDFh      ; check canary value
00000034  je          0000003B 
00000036  call        727767A8                          ; crash program
0000003b  lea         esp,[ebp]                         ; normal exit, pop stack frame
0000003e  pop         ebp 
0000003f  ret 

每次代码被JIT编译后,实际的canary值都会发生变化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接