Disabling the Stack Cookie Generation in Visual Studio 2013

I wanted to write a simple program that would let me test out some basic stack exploits. Here’s a very simple example that should crash because of stack corruption.

#include <string.h>

int test_bof() {
  char buffer[10];
  strcpy(buffer, "aaaaaaaaaaaaaaaaaaaaaaaaaaa");
}

int main(int argc, char** args) {
  test_bof();
  return 0;
}

When I ran the program, instead of an access violation, I got this error:

Unhandled exception at 0x00412059 in SimpleStackBof.exe:
Stack cookie instrumentation code detected a stack-based buffer overrun.

Interesting. I enabled the Assembler Output (C++ > Output Files > Assembler Output /FAs) and looked at the generated assembly code.

_TEXT SEGMENT
_buffer$ = -16 ; size = 10
__$ArrayPad$ = -4 ; size = 4
test_bof PROC ; COMDAT

; 5 : {

push ebp
mov ebp, esp
sub esp, 80 ; 00000050H
mov eax, DWORD PTR ___security_cookie
xor eax, ebp
mov DWORD PTR __$ArrayPad$[ebp], eax
push ebx
push esi
push edi

; 6 : char buffer[10];
; 7 : strcpy(buffer, "aaaaaaaaaaaaaaaaaaaaaaaaaaa");

push OFFSET ??_C@_0BM@CINAKCFB@aaaaaaaaaaaaaaaaaaaaaaaaaaa?$AA@
lea eax, DWORD PTR _buffer$[ebp]
push eax
call _strcpy
add esp, 8

; 8 : }

pop edi
pop esi
pop ebx
mov ecx, DWORD PTR __$ArrayPad$[ebp]
xor ecx, ebp
call @__security_check_cookie@4
mov esp, ebp
pop ebp
ret 0
_test_bof ENDP

First thing to notice is that there’s a magic 4-byte stack variable called __$ArrayPad$ that wasn’t in the C code. Also notice that the buffer[10] variable has been aligned and so it actually takes up 12 bytes instead of the 10 I requested. This will be important later when crafting an exploit payload. One thing that struck me was how much stack space the compiler gave itself (sub esp, 80). It’s kind of a weird number too – doesn’t even seem aligned. I don’t know.

The next thing that’s different is that after the usual stack preamble, it’s grabbing a value from the address __security_cookie, xor’ing with the frame base pointer and then saving in __$ArrayPad$. The rest of the code looks pretty normal until just before the return. The value at __$ArrayPad$ is put into ecx and then xor’d with the current frame base pointer value. Then @__security_check_cookie@4 is called. Here’s the disassembled version of @__security_check_cookie@4.

--- f:\dd\vctools\crt\crtw32\misc\i386\secchk.c
004112D0 3B 0D 00 60 41 00 cmp ecx,dword ptr ds:[416000h]
004112D6 75 02 jne failure (04112DAh)
004112D8 F3 C3 rep ret
004112DA E9 6C FD FF FF jmp ___report_gsfailure (041104Bh)

So what’s really going on here. A secret value __security_cookie (ds:[416000h]) is read and xor’d with the value of the frame base pointer. That value is stored on the stack at __$ArrayPad$, right above the saved address of the previous frame pointer which is right above the very important saved eip (instruction pointer) value (important because that’s the address that execution will jump to when ret is executed). The function code runs as it normally would but before returning, a check is added. The value of __$ArrayPad$ is read and xor’d again with the frame base register. The result is in ecx. Then the security check routine runs and compares ecx with the original __security_cookie value. If they are the same then there was no stack frame corruption detected. If the ecx is different than __security_cookie, that means that either ebp was modified or more likely there was a stack buffer overflow that overwrote the original value of __$ArrayPad$. This canary value is checked before the postamble runs and crashes the program if the stored frame pointer or eip may have been compromised.

If you take any number A, and xor it with another number B you’ll get C.
If you then take C and xor it with B, you’ll get A.
E.g. in binary: 101 ^ 011 => 110 and 110 ^ 011 => 101, the original value.


That’s great for security but I’m trying to write an insecure program for demonstration so we need to turn off the stack cookie. In the properties for the project set C++ -> Code Generation -> Security Check to Disable Security Check /GS-. Here’s the regenerated assembly (abridged) with the Security Check disabled.

_buffer$ = -12		; size = 10
_test_bof PROC		; COMDAT

; 5    : {
push	ebp
mov	ebp, esp
sub	esp, 76		; 0000004cH
push	ebx
push	esi
push	edi
...
pop	edi
pop	esi
pop	ebx
mov	esp, ebp
pop	ebp
ret	0

Notice that the magic stack variable is gone and the preamble/postamble no longer contain the security cookie setup or check. Now it should be ready to exploit. Let’s run it.

Unhandled exception at 0x61616161 in SimpleStackBof.exe:
0xC0000005: Access violation reading location 0x61616161.

Error reading location 0x61616161 (ASCII ‘aaaa’) that’s more like it.

Leave a comment