.all中stackalloc的缓冲区溢出保护

Rol*_*kas 6 .net c# buffer-overrun stackalloc

来自stackalloc的C#参考:

stackalloc的使用自动启用公共语言运行库(CLR)中的缓冲区溢出检测功能.如果检测到缓冲区溢出,则会尽快终止该过程,以最大程度地降低恶意代码执行的可能性.

具体来说,为.NET实现了什么样的保护机制?
它还会检测缓冲区欠载吗?对已知攻击的保护力较弱?


对于上下文,例如对于MS C++编译器,此处提供了以下信息:
Windows ISV软件安全防御:

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

请注意,Visual C++ 2005(及更高版本)也会重新排序堆栈上的数据,以便更难以预测地破坏该数据.示例包括:
•将缓冲区移动到比非缓冲区更高的内存.此步骤可以帮助保护驻留在堆栈上的函数指针.
•在运行时将指针和缓冲区参数移动到较低的内存,以缓解各种缓冲区溢出攻击.

Han*_*ant 14

是的,.NET抖动生成了一种堆栈金丝雀检查,它也存在于Microsoft C/C++编译器使用/ GS编译器选项生成的本机代码中.基本方案是在方法入口处写入堆栈顶部的随机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;
    }
}
Run Code Online (Sandbox Code Playgroud)

运行此代码会触发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
Run Code Online (Sandbox Code Playgroud)

您可以使用Debug + Windows + Disassembly查看执行此操作的代码.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 
Run Code Online (Sandbox Code Playgroud)

每次代码被jitted时,实际的金丝雀值都会改变.