开发者

Question with stack smashing protection and buffer overflows

Im doing some research on buffer overflows and I was wondering how does stack smashing protection works

i have this code:

int main( )
{ 
    char Buf[16];
    printf(“Digite o seu nome: ”);
    gets(Buf);
    printf(“%s”,Buf);
return 0;
} 

I compile it with gcc

and then i put in a bunch of chars to fill the buffer

First i put 16 chars

$ ./Exemplo1

Digite o seu nome: AAAAAAAAAAAAAAAA

Ola AAAAAAAAAAAAAAAA

This is ok because the buffer is the right size

Next i try 24 chars

$ ./Exemplo1

Digite o seu nome: AAAAAAAAAAAAAAAAAAAAAAAA

Ola AAAAAAAAAAAAAAAAAAAAAAAA

Why does it still works?

shouldn't this cause the program to terminate!?

It only terminates the program when I put 25 or more chars

./Exemplo1

Digite o seu nome: AAAAAAAAAAAAAAAAA开发者_运维技巧AAAAAAAA

Ola AAAAAAAAAAAAAAAAAAAAAAAAA

* stack smashing detected *: ./Exemplo1 terminated

Why? what's after the buffer that is not the return address? What I read about and what I think understand is that it should have a canary value, but its supposed to terminate the program if that value has changed and with 24 chars written to the buffer shouldn't it still give me a stack smashing detected even if the return address hasn't changed but the canary value did.

Thanks.


From my brief reading of the generated assembly, here is what I think happens (gcc 4.4.5 on 64-bit Ubuntu).

The canary is a double word (8 bytes). The stack -- including the canary -- grows in increments of 16 bytes. The canary is placed right at the end of the stack frame. To satisfy all three requirements at the same time, gcc may need to insert padding between your automatic variables and the canary.

Since in your code Buf is 16 bytes long, gcc places 8 bytes of padding between Buf and the canary (needed in order to make the size of the stack frame a multiple of 16 bytes). This explains why you can enter up to 24 chars without triggering the stack smashing detection.

If I change Buf to be 8 bytes long, there's no longer need for any padding, and entering 9 chars triggers the protection:

#include <stdio.h>

int main( )
{ 
    char Buf[8];
    printf("Digite o seu nome: ");
    gets(Buf);
    printf("%s",Buf);
    return 0;
 }

aix@aix:~$ ./a.out 
Digite o seu nome: AAAAAAAA
AAAAAAAA

aix@aix:~$ ./a.out 
Digite o seu nome: AAAAAAAAA
*** stack smashing detected ***: ./a.out terminated

Obviously, this is dependent on the compiler, hardware platform, compiler flags etc.

It also goes without saying that one shouldn't expect this mechanism to be bullet-proof.

If you'd like to experiment further, try compiling your code with different buffer sizes and with/without -fno-stack-protector. If you use -S to generate assembly code, you'll be able to see how the generated code changes as you tweak the settings.


The compiler makes no guarantees about how data will be organized on the stack. The buffer buf[] could be allocated right next to critical data like the canary, old stack pointer, and return address; or there could be some extra space in between. In this case, it looks as though there's probably some padding in there.


The actual size of the buffer may be larger than the size you specify, or there is more on the stack beside the buffer. By going past the buffer boundary, you either write to the extra memory in the buffer, or you overwrite other content of the stack. That is not good, since it might trash some of your local variables, but it won't overwrite the return address yet.

Only if you write past the allocated local stack frame and overwrite the return address of the function that is currently executing, bad things can happen. If you are lucky, your program just crashes. But what will exactly happen is hard to foresee.


Currently most compilers include stack cookies or another form of stack protection. Probably this is ProPolice at work http://en.wikipedia.org/wiki/Buffer_overflow_protection#GCC_Stack-Smashing_Protector_.28ProPolice.29

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜