Dies ist eine alte Version des Dokuments!


Stack Protection

The gcc compiler provides a stack protection mechanism that can be compiled into a binary. Right after the stack frame is created, a random value provided by the Linux kernel1) is pushed to the stack. This so-called „stack canary“ is located between the local variables and the return address. If no overflow occurred during the execution of the function, the value of the stack canary is unchanged. In case the value changed, execution is aborted.

Using the -fstack-protector flag during compilation makes gcc supply every function with a buffer of at least 8 bytes. -fstack-protector-strong or -fstack-protector-all can be used to weaken this constraint2).

The behavior of the stack protector is tested with a simple strcpy().

canary/canary.c
// gcc -g -O0 -m32 -fstack-protector canary.c
#include <stdio.h>
#include <string.h>
 
int main(int argc, char *argv[])
{
    char buffer[8] = {0};
 
    if(argc != 2)
    {
        printf("A single argument is required.\n");
        return 1;
    }
 
    strcpy(buffer, argv[1]);
    return 0;
}

Trying to overflow the buffer causes the execution to terminate.

$ ./a.out AAAAAAAAAAAAAAAAAAAAAAAA
*** stack smashing detected ***: <unknown> terminated
[1]    13372 abort (core dumped)  ./a.out AAAAAAAAAAAAAAAAAAAAAAAA

Decompiling the generated binary reveals implementation details of the gcc stack protector. First, a random value is read from gs:0x14. This is a special read-only memory region providing a fixed random number per execution which is saved on the stack.

 5d1:   65 8b 1d 14 00 00 00    mov    ebx,DWORD PTR gs:0x14
 5d8:   89 5d f4                mov    DWORD PTR [ebp-0xc],ebx

After the actual function body, the random value is read again and compared to the saved one. If the values are not equal, an error is raised.

 62d:   65 33 0d 14 00 00 00    xor    ecx,DWORD PTR gs:0x14
 634:   74 05                   je     63b <main+0x8e>
 636:   e8 85 00 00 00          call   6c0 <__stack_chk_fail_local>

As the canary is located between local variables and the return address, overflows targeting the variables can not be detected by this mechanism.



← Back to ASCII-armored addresses Overview Continue with Address Space Layout Randomization (ASLR) →