Yes, the .NET jitter generates the kind of stack canary checking that also exists in native code generated by the Microsoft C/C++ compiler with the /GS compiler option. The basic scheme is to store a random 32-bit value at the top of the stack, written at method entry. At method exit it checks if the value is still there. A change in the value is a very high predictor for a stack buffer overflow, the kind that malware uses to take control of a program.
Some code to play with:
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;
}
}
Running this code triggers the Windows Error Reporting dialog, even with the debugger attached. You can see the crash reason in the Output window:
The program '[3636] ConsoleApplication33.exe: Native' has exited with code -1073740791 (0xc0000409).
The exception code is defined in the ntstatus.h SDK header file:
//
// 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
You can see the code that does this with Debug + Windows + Disassembly. The essential parts of 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
The actual canary value changes every time the code is jitted.