About | Buy | Forum | Industry Watch | Learning Curve | Products | Search | Twitter | Xnews
Home » Learning Curve » Can't Take a Punch

Microsoft's Remedies: The Stack

Protecting that glass jaw.


Buy It

Try It

Microsoft's general remedy for attacks on the program stack is the stack cookie. To understand why stack cookies might be good one must first understand what a stack is and even more importantly how hackers exploit it.

The stack is an area of process memory where functions built into the program are running their own 'temporary' memory. The data held on the stack is not permanent (or static as it's most often called) but set up by the process when needed.

The stack also contains information on where the function being called is supposed to return control to when it is finished. Overrunning the stack with input data will of course corrupt this information and can lead to an exploit taking over a process by redirecting the return to an address under hacker control.

Microsoft now have a method of building Windows applications so they can detect attacks on the process stack: the stack cookie. The code stores a random value on the stack between the temporary variables the function will use and the return address the function will need at the end of operations. The code will check the value of this stack cookie (essentially just another memory location) and if the value has changed will then abort the process before it can be exploited.

#pragma strict_gs_check

Stack cookies can impair performance drastically. In order to minimise use of stack cookies Microsoft introduced a code directive so that only functions with character string buffers or memory allocation functions - the most likely victims - get a stack cookie.

The code (generated by using the #pragma strict_gs_check) defines the string buffer as an array of single byte or double byte (presumably Unicode) elements with a total size of at least five bytes. Only functions with such a string buffer get a stack cookie.

An additional enhancement is to add the stack cookie to all functions that use the address of a stack variable. Although this offers better protection, it also means stack cookies are used more often - and this in turn impacts performance significantly.

The strict_gs_check pragma catches declarations such as the following.

char a[5]; // single byte array of at least five bytes
short b[3]; // double byte array of at least five bytes

The strict_gs_check pragma does not catch declarations such as the following.

char e[4]; // not at least five bytes
int f[10]; // element size greater than two bytes
char *g[10]; // element size greater than two bytes

struct {
    char a; short b;
} c[9]; // element size greater than two bytes

struct {
    char a, b, c, d, e;
} f; // There's no string buffer here

Variable Reordering

Stack cookie protection only kicks in when a function is finished executing. Hackers might be able to take advantage of an overwritten stack before then. Variable reordering varies the order of variables on the stack so hackers can't count on a known static layout. Strings are put at higher addresses than all the other variables in an attempt to prevent their being overrun and certain functions are put below most of the local variables in order to prevent the same thing.

Given the following function:

void vuln(char *arg) {
    char buf[100]; int i;

    strcpy(buf, arg);
}

The normal stack frame layout is as follows.

[buf] [i] [return address] [arg]

A reordered frame (also using a stack cookie) is as follows.

[copy of arg] [i] [buf] [stack cookie] [return address] [arg]

But is that 100% protection? And how about structured exception handling?

About | Buy | Forum | Industry Watch | Learning Curve | Products | Search | Twitter | Xnews
Copyright © Rixstep. All rights reserved.