将C编译为允许缓冲区溢出的程序

9

我正在学习缓冲区溢出,并尝试制作一个。我有这段代码:

#include <stdio.h>

char *secret = "password";

void go_shell() {
    char *shell =  "/bin/sh";
    char *cmd[] = { "/bin/sh", 0 };
    setreuid(0);
    execve(shell,cmd,0);
}

int authorize() {
    char password[64];
    printf("Enter Password: ");
    gets(password);
    if (!strcmp(password,secret)) {
        return 1;
    }
    else {
        return 0;
    }
}

int main() {
    if (authorize()) {
        printf("login successful\n");
        go_shell();
    } else {
        printf("Incorrect password\n");
    }
    return 0;
}

我使用gcc编译,然后在gdb中运行它。
我输入了大约100个"A"作为密码,程序崩溃了。
问题是没有任何寄存器被覆盖为0x4141414141414141
我在谷歌上搜索了这个问题,并在gcc中添加了-fno-stack-protector标志,这使得RBP可以被覆盖为0x4141414141414141,但其他的仍然不行。
我想知道是否有一种方法可以编译代码,以便RIP可以被覆盖。

在使用Mac OSX操作系统时,你知道这个标志是什么吗? - carloabelli
Ubuntu是一种Linux发行版。 - Mahmoud Al-Qudsi
6
缓冲区溢出通常不会直接覆盖寄存器变量。如果你覆盖了堆栈,返回地址可能会被覆盖,如果启用了帧指针(没有使用-fomit-frame-pointer选项),那么帧指针也可能被覆盖。因此这些可能会被拉回到寄存器中,但这是因为堆栈先被覆盖了,而不是直接覆盖寄存器。 - Jonathan Leffler
@cabellicar123 你说IP被覆盖了...你知道IP是指令指针,也就是CPU正在执行机器代码的地址吗?而使用ret指令返回的函数只是从堆栈中弹出该寄存器的新值,希望它是早期调用时推入堆栈的值。你怎么知道这没有发生,并且是崩溃的原因呢? - hyde
你确实“覆盖”了RIP寄存器。这就是为什么它崩溃的原因。显然,你写入的值不够好,无法执行有效载荷。 - Hans Passant
显示剩余6条评论
2个回答

3

如果您使用-fno-stack-protector编译,那么您的代码已经实现了您想要的功能。在GDB中看不到RIP的值为0x4141414141414141的原因是在更新RIP之前会抛出一般保护故障。(如果发生页面故障,GPF处理程序通常会从交换中加载页面并通过从失败的指令开始恢复执行。)


谢谢您的帮助,但我想知道是否有一种方法可以关闭那个GPF,以便将RIP设置为0x4141414141414141,因为这是我正在使用的教程中发生的情况。 - carloabelli
@cabellicar123,除非您在那个地址创建一个可执行页面,否则无法避免GPF。继续进行您的教程。可能下一步是提供一个特别设计的密码,使代码跳转到有效地址。 - nwellnhof

1
在x32上,当程序从堆栈中弹出先前保存的EIP值并将其放回EIP时,您会遇到EIP 0×41414141的崩溃,因为CPU随后尝试执行内存地址0x41414141处的指令,这会导致段错误。(当然,在执行之前必须获取页面)

现在,在x64执行期间,当程序将先前保存的RIP值弹回RIP寄存器时,内核随后尝试执行内存地址0x4141414141414141处的指令。首先,由于规范形式寻址,任何虚拟地址的第48到63位必须是位47的副本(类似于符号扩展),否则处理器将引发异常。如果这不是问题-内核在调用页面故障处理程序之前进行其他检查,因为最大用户空间地址为0x00007FFFFFFFFFF。

总之,在x32架构中,地址会被传递到页面故障处理程序而没有任何“验证”,该处理程序试图加载页面,从而触发内核发送程序段错误,但x64不会到达这一步。

测试一下,将RIP覆盖为0×0000414141414141,您会发现期望的值被放置在RIP中,因为内核的预检通过,然后像x32情况一样调用了页面错误处理程序(当然,这会导致程序崩溃)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接