在程序返回的一条语句堆栈项目处,用新函数的起始地址覆盖,将会跳转到执行新函数。

现在系统对这个行为做了判断,已经无法实施这类攻击或技巧。

1,测试代码

#include 
void cc()
{
        printf("I am cc( )
");
}

void bb(unsigned long int * x)
{
        x[7] = (unsigned long int)cc;
        printf("I am bb(...)
");
}

void aa(int y)
{
        unsigned long int a[6] = {0,1,2,3,4,5};
        printf("I am aa(...)
");
        bb(a);
}

int main()
{
        int z=100;

        aa(z);



        printf("cc = %p
", cc);
        return 0;
}

2,运行效果

下图可见,并不是在修改堆栈时terminated,而是在返回时检测到了 stack smashing

堆栈溢出的攻击 -fno-stack-protector stack smash 检测插图

3,原理分析

3.1如何防止 stack smash

“stack smashing detected”错误通常是由于缓冲区溢出(buffer overflow)导致的。这种错误会破坏程序的堆栈结构,被系统检测到并终止程序以防止安全漏洞。

要解决这个问题,您可以考虑以下几点:

1. 检查代码中的数组边界:确保在使用数组时不会超出其边界,避免写入超出数组大小的数据。

2. 使用安全的字符串处理函数:避免使用不安全的字符串处理函数(如strcpy、strcat等),改用安全的函数(如strncpy、strncat等)来处理字符串。

3. 使用堆内存分配:考虑使用动态内存分配(如malloc、calloc、realloc等)来避免栈溢出问题。

通过检查代码中的缓冲区操作和内存访问,可以帮助您解决”stack smashing detected”错误。

3.2 系统检测 stack smash 的原理

系统通过一种叫做”Stack Protector”的机制来检测stack smashing。这个机制在编译时会向程序中插入一些额外的代码,用于保护函数的返回地址和栈帧结构不被破坏。

具体来说,Stack Protector会在栈帧中插入一个特殊的”canary value”(金丝雀值),然后在函数返回时检查这个值是否被修改。如果检测到”canary value”被修改,系统就会认为发生了stack smashing,并终止程序的执行。

这种机制可以有效防止缓冲区溢出攻击,提高程序的安全性。

3.3,如何让系统放弃检测 stack smash

要阻止系统进行stack smashing检测,您可以在编译时禁用Stack Protector机制。具体取决于您使用的编译器,以下是一些常见编译器的选项:

– 对于GCC编译器,您可以使用-fno-stack-protector选项来禁用Stack Protector机制。
– 对于Clang编译器,您可以使用-fno-stack-protector选项来禁用Stack Protector机制。
– 对于MSVC编译器,您可以使用/GS-选项来禁用堆栈保护。

通过在编译时使用这些选项,您可以阻止系统进行stack smashing检测。请注意,禁用Stack Protector可能会降低程序的安全性,因此请谨慎使用。

测试放弃检测实验:

编译方式:

$ gcc hello_func_stack.c -fno-stack-protector

堆栈溢出的攻击 -fno-stack-protector stack smash 检测插图(1)

由于修改了堆栈中返回后第一条指令的地址,所以函数 cc() 被调用,

本站无任何商业行为
个人在线分享 » 堆栈溢出的攻击 -fno-stack-protector stack smash 检测
E-->