与堆栈保护有关的编译选项

GCC4.1中有三个与堆栈保护有关的编译选项:
-fstack-protector:启用堆栈保护,不过只为局部变量中含有char数组的函数插入保护代码;
-fstack-protector-all:启用堆栈保护,为所有函数插入保护代码;

-fno-stack-protector:禁用堆栈保护;

A code fragment to show how to stack protector work.

#include <stdio.h>

int fun(void)
{
        int canary = 0;
        int backed = 0;

        /*get original canary*/
    asm ("movl %%fs:0x28, %%eax\n\t"
                "movl %%eax, %0\n\t"
                :"=r"(canary)
                :
                :"%eax"
                );

        /*Pang!!!*/
        /*
    asm (
                "movl $0x0, %%eax\n\t"
                "movl %%eax, -0x8(%%rbp)\n\t"
                :
                :
                :"%eax"
                );
        */

        /*get backup canary*/
    asm ("movl -0x8(%%rbp), %%eax\n\t"
                "movl %%eax, %0\n\t"
                :"=r"(backed)
                :
                :"%eax"
                );

        printf("0x%x 0x%x\n", canary, backed);

        return 0;
}

int main(void)
{
        fun();
        return 0;
}

Compile this code with the following command and run it:

[xinkliu@hzling26 tmp]$ gcc test.c -o test -g -fstack-protector-all
[xinkliu@hzling26 tmp]$ ./test 
0x797f00 0x797f00
We can see that we had got magic number(canary) used to protect stack, and had got the backup magic number. Before function return to caller, the magic number would be checked and it is must be the same as the  backup magic number which is saved at -0x8(%rbp) when enter this function.


Let's disassemble this code and see what's happened:

[xinkliu@hzling26 tmp]$ gdb test
(gdb) disassemble fun
Dump of assembler code for function fun:
0x0000000000400508 <fun+0>:     push   %rbp
0x0000000000400509 <fun+1>:     mov    %rsp,%rbp
0x000000000040050c <fun+4>:     sub    $0x10,%rsp
0x0000000000400510 <fun+8>:     mov    %fs:0x28,%rax
0x0000000000400519 <fun+17>:    mov    %rax,-0x8(%rbp)
0x000000000040051d <fun+21>:    xor    %eax,%eax
0x000000000040051f <fun+23>:    movl   $0x0,-0x10(%rbp)
0x0000000000400526 <fun+30>:    movl   $0x0,-0xc(%rbp)
0x000000000040052d <fun+37>:    mov    %fs:0x28,%eax
0x0000000000400535 <fun+45>:    mov    %eax,%edx
0x0000000000400537 <fun+47>:    mov    %edx,-0x10(%rbp)
0x000000000040053a <fun+50>:    mov    -0x8(%rbp),%eax
0x000000000040053d <fun+53>:    mov    %eax,%edx
0x000000000040053f <fun+55>:    mov    %edx,-0xc(%rbp)
0x0000000000400542 <fun+58>:    mov    -0xc(%rbp),%edx
0x0000000000400545 <fun+61>:    mov    -0x10(%rbp),%esi
0x0000000000400548 <fun+64>:    mov    $0x4006a8,%edi
0x000000000040054d <fun+69>:    mov    $0x0,%eax
0x0000000000400552 <fun+74>:    callq  0x4003f8 <printf@plt>
0x0000000000400557 <fun+79>:    mov    $0x0,%eax
0x000000000040055c <fun+84>:    mov    -0x8(%rbp),%rdx
0x0000000000400560 <fun+88>:    xor    %fs:0x28,%rdx
0x0000000000400569 <fun+97>:    je     0x400570 <fun+104>
0x000000000040056b <fun+99>:    callq  0x400418 <__stack_chk_fail@plt>
0x0000000000400570 <fun+104>:   leaveq 
0x0000000000400571 <fun+105>:   retq   
End of assembler dump.
See line <fun+8> and <fun+17>, this two line is used to backup the magic number to function's local stack.  And the other two lines <fun+84> and <fun+88> check the backup magic number saved at local stack, if this number is not the same as original magic number saved at (%fs:0x28) , system consider the function stack has been corruption. Because the backup magic number is saved at (-0x8(%rbp)) as above we seen, this location is next to function stack and should not be change.


BTW, the previous four line of assembly code we showed is automatic added to program once we add the compile option "-fstack-protector-all". Our test code just show that the magic number used to protect stack is really exist.

There are anther code fragment encapsulated with MARCO to get original magic number and backup magic number:

#include <assert.h>
#define CHECK_CANARY(canary) do { \
        unsigned int __bk_canary = 0; \
        __asm__ ("movl -0x8(%%rbp), %%eax\n\t"\
                "movl %%eax, %0\n\t"\
                :"=r"(__bk_canary)\
                :\
                :"%eax"\
                ); \
        assert(__bk_canary == (canary));  \
} while(0)

#define GET_CANARY(canary) do { \
        unsigned int __canary = 0; \
        __asm__ ("movl %%fs:0x28, %%eax\n\t"\
                "movl %%eax, %0\n\t"\
                :"=r"(__canary)\
                :\
                :"%eax"\
                ); \
        canary = __canary;  \
} while(0)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值