介绍
stack-protector是一个安全相关的编译器选项,用于防止栈溢出攻击。当启用这个选项时,编译器会在函数的栈帧中插入一个称为"canary"的特殊值,并在函数返回之前检查这个值是否被篡改。如果"canary"值发生变化,这意味着栈被非法修改,编译器会触发一个信号(通常是SIGABRT),导致程序异常终止。这样可以防止攻击者通过栈溢出来执行任意代码。
关于stack-protector包含三个选项,分别是stack-protector、stack-protector-all、stack-protector-strong、stack-protector-explicit四种。
stack-protector:保护函数中通过alloca()分配缓存以及存在大于8字节的缓存。缺点是保护能力有限。
stack-protector-all:保护所有函数的栈。缺点是增加很多额外栈空间,增加程序体积。
stack-protector-strong:在stack-protector基础上,增加本地数组、指向本地帧栈地址空间保护。
stack-protector-explicit:在stack-protector基础上,增加程序中显式属性"stack_protect"空间。
如果要停止使用stack-protector功能,需要加上-fno-stack-protector。
stack-protector性能:stack-protector > stack-protector-strong > stack-protector-all
stack-protector覆盖范围: stack-protector-all > stack-protector-strong > stack-protector
例子
C语言代码
#include <string.h>
#include <stdio.h>
int main(void)
{
char array[2] = {0};
strcpy(array, "aaaaaaaaaa");
printf("%s\n", array);
return 0;
}
Makefile
TARGET := gcc_para_test
STRIP = $(CROSS_COMPILE)strip
CC = $(CROSS_COMPILE)gcc
AR = $(CROSS_COMPILE)ar
CFLAGS += -Wall -std=gnu99 -g
CFLAGS += -fstack-protector-all
OBJS += main.o
all: $(TARGET)
$(TARGET):$(OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
clean:
rm $(OBJS) $(TARGET) -f
运行结果
当Makefile中不使用-fstack-protecto相关参数和使用参数-fstack-protecto时,输出如下:
# ./gcc_para_test
aaaaaaaaaa
Segmentation fault (core dumped)
Segmentation fault (core dumped)
未能检查出栈溢出
当Makefile中使用-fstack-protector-all参数和时,输出如下:
# ./gcc_para_test
*** buffer overflow detected ***: terminated
Aborted (core dumped)
Aborted (core dumped)
可以看出stack-protector-strong和stack-protector-all相对于stack-protector更多的检测了栈溢出。
修改array大小超过8字节之后,重新使用stack-protector进行测试。结论:当数组大小超过8字节过后,stack-protector才能检测出栈溢出。