Check out the new USENIX Web site. next up previous
Next: Randomizing the Canary Up: StackGuard: Making the Stack Previous: StackGuard: Making the Stack

Detecting Return Address Change Before Return

  figure73
Figure 2: Canary Word Next to Return Address

To be effective, detecting that the return address has been altered must happen before a function returns. StackGuard does this by placing a ``canary''gif word next to the return address on the stack, as shown in Figure 2. When the function returns, it first checks to see that the canary word is intact before jumping to the address pointed to by the return address word.

This approach assumes that the the return address is unaltered IFF the canary word is unaltered. While this assumption is not completely true in general (stray pointers can alter any word), it is true of buffer overflow attacks. The buffer overflow attack method exploits the fact that the return address word is located very close to a byte array with weak bounds checking, so the only tool the attacker has is a linear, sequential write of bytes to memory, usually in ascending order. Under these restricted circumstances, it is very difficult to over-write the return address word without disturbing the canary word.
 

    move canary-index-constant into register[5]
    push canary-vector[register[5]]
Figure 3: Function Prologue Code: Laying Down a Canary
 
    move canary-index-constant into register[4]
    move canary-vector[register[4]] into register[4]
    exclusive-or register[4] with top-of-stack
    jump-if-not-zero to constant address .canary-death-handler
    add 4 to stack-pointer
    < normal return instructions here>
.canary-death-handler:
    ...
Figure 4: Function Epilogue Code: Checking a Canary

The StackGuard implementation is a very simple patch to gcc 2.7.2.2. The gcc function_prologue and function_epilogue functions have been altered to emit code to place and check canary words. The changes are architecture-specific (in our case, i386), but since the total changes are under 100 lines of gcc, portability is not a major concern. All the changes in the gcc calling conventions are undertaken by the callee, so code compiled with the StackGuard-enhanced gcc is completely inter-operable with generic gcc .o files and libraries. The additional instructions added to the function prologue are shown in pseudo-assembly form in Figure 3, and the additional instructions added to the instruction epilogue are shown in Figure 4. Section 4 describes testing and performance of this patch.
 



next up previous
Next: Randomizing the Canary Up: StackGuard: Making the Stack Previous: StackGuard: Making the Stack
Crispin Cowan

Tue Dec 9 16:04:30 PST 1997