是的,.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
00000001 mov ebp,esp
00000003 sub esp,8
00000006 xor eax,eax
00000008 mov dword ptr [ebp-8],eax
0000000b mov dword ptr [ebp-4],eax
0000000e mov dword ptr [ebp-4],esp
00000011 mov dword ptr [ebp-8],0EDDB7EDFh
// For loop code omitted
0000002d cmp dword ptr [ebp-8],0EDDB7EDFh
00000034 je 0000003B
00000036 call 727767A8
0000003b lea esp,[ebp]
0000003e pop ebp
0000003f ret
每次代码被JIT编译后,实际的canary值都会发生变化。