其他分享
首页 > 其他分享> > 禁用GCC中的堆栈保护不起作用

禁用GCC中的堆栈保护不起作用

作者:互联网

我正在尝试使用带有strcpy的经典溢出使用此函数重新创建堆栈缓冲区溢出:

#include <stdio.h>
#include <string.h>
void main(int argc, char **argv) {
    char buf[100];
    strcpy(buf,argv[1]);
    printf("Done!\n");
}

我已经尝试使用所有各种标志进行编译,以便删除堆栈保护gcc -o vuln vuln.c -fno-stack-protector -g -z execstack以及使用sudo echo 0>删除ASLR.的/ proc / SYS /内核/ randomize_va_space.

我可以让我的nop-shellcode-address覆盖保存的EIP,但它会在RET上崩溃.我想通过HANDLE SIGSEGV忽略等来禁用gdb中的SIGSEGV,但是在GDB外运行我继续得到Segmentation Fault,无论我在哪里设置返回地址.

除了获得旧版gcc之外的任何想法?目前使用gcc版本6.1.1.

解决方法:

Linux遵循W^X原则:它将内存页标记为不可执行,除非它们是代码部分的一部分.这超出了编译应用程序的范围,并且有充分的理由.操作系统承担此责任,以防止系统上执行的任何程序的缓冲区溢出攻击;尤其是那些主动尝试执行缓冲区溢出攻击的程序,就像你的程序一样.

您正尝试通过buf在堆栈上编写代码并覆盖函数的返回地址以将执行跳转到新注入的代码中.当函数返回时,程序计数器被设置为重写的返回地址,现在指向堆栈内存.由于堆栈内存页面上的已撤销执行权限,程序计数器尝试执行下一条指令时抛出SIGSEGV.

要从堆栈执行,必须禁用OS堆栈保护.

幸运的是,Linux提供了execstack用于由用户自行决定使用的这种情况.

this Unix& Linux Stack Exchange发布更多一般信息.

调试注入数据

如果您在gdb中获得SIGSEGV,则可能意味着缓冲区溢出尝试中存在一些错误.为了避免在main结束时搞乱清理,我建议你创建一个从main调用的函数来执行缓冲区溢出:

#include <stdio.h>
#include <string.h>

char injection_code[] = ""; // buffer overrun data here


void foo () {
    char buf[100];

    // memcpy used to copy the full injection string, including any nested 0s
    memcpy(buf, injection_code, 108); // +8 here to handle 64-bit system RAs
}

int main (int argc, char** argv) {
    foo();
    printf("Done!\n");
    return 0;
}

使用GDB进行调试.我建议在foo结尾处设置一个断点,并检查寄存器是否符合您对信息寄存器的期望.您可能最感兴趣的是指令指针,您可以使用信息寄存器rip(64位)或info寄存器eip(32位)进行检查.

您可以通过在GDB中使用print或x/x来探索堆栈的外观.例如,您可以检查$rbp 8以查看堆栈上的返回地址(RA).

如果RA指向无效位置,GDB将对ret指令进行SIGSEGV:

Program received signal SIGSEGV, Segmentation fault.
0x00000000004005bc in foo () at bufferoverflow.c:27

您可以通过检查故障时的指令指针地址(在上面的例子中,它将是0x00000000004005bc)对程序的程序集(在GDB中使用disassemble function_name)来检查它是否在ret指令上出现故障.

如果返回地址指向堆栈中,它可能会抛出一个非法指令的SIGILL,这意味着您的返回地址可能无法正确对齐,或者您注入的指令格式不正确:

Program received signal SIGILL, Illegal instruction.
0x00007fffffffdc13 in ?? ()

同样,您可以使用GDB来探索堆栈以了解原因.

GDB对于使缓冲区溢出的结构正确非常有用.
但是,一旦按预期工作,请记住在GDB外部执行时可能会移位内存地址,尤其是在没有调试标志(-g)的情况下进行编译时.您将不得不稍微使用返回地址,以便在“实时”环境中将其放置到您想要的位置.

一个旁白

通常,直接运行注入代码的缓冲区溢出攻击通常不适用于当今的堆栈保护机制.通常需要存在额外的漏洞才能执行任意代码.

标签:c-3,buffer-overflow,linux,gcc,stack-overflow
来源: https://codeday.me/bug/20190828/1755935.html