Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
编译C以允许缓冲区溢出_C_Compilation_Buffer Overflow - Fatal编程技术网

编译C以允许缓冲区溢出

编译C以允许缓冲区溢出,c,compilation,buffer-overflow,C,Compilation,Buffer Overflow,我正在学习关于缓冲区溢出的知识,并尝试创建一个缓冲区溢出。我有以下代码: #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 pas

我正在学习关于缓冲区溢出的知识,并尝试创建一个缓冲区溢出。我有以下代码:

#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;
}
#包括
char*secret=“password”;
void go_shell(){
char*shell=“/bin/sh”;
char*cmd[]={/bin/sh”,0};
setreuid(0);
execve(shell,cmd,0);
}
int authorize(){
字符密码[64];
printf(“输入密码:”);
获取(密码);
如果(!strcmp(密码,机密)){
返回1;
}
否则{
返回0;
}
}
int main(){
if(authorize()){
printf(“登录成功\n”);
加油;
}否则{
printf(“不正确的密码”);
}
返回0;
}
我用gcc编译它,然后在gdb中运行它

我输入大约100个“A”作为密码,程序就会崩溃

问题是没有寄存器被覆盖到
0x4141

我在谷歌上搜索了一下,并将
-fno-stack-protector
标志添加到
gcc
,这样就可以将RBP覆盖到
0x4141
,但没有其他内容


我想知道是否有一种方法可以编译代码,这样RIP就可以被覆盖

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

x32上EIP 0×4141崩溃的原因是,当程序将先前保存的EIP值从堆栈中弹出并返回EIP时,CPU会尝试在内存地址0×4141处执行指令,从而导致segfault。(它必须在执行课程之前获取页面)

现在,在x64执行期间,当程序将先前保存的RIP值弹出回RIP寄存器时,内核将尝试在内存地址0×4141处执行指令。首先,由于标准形式寻址,任何虚拟地址的位48到63必须是位47的副本(以类似于符号扩展的方式),否则处理器将引发异常。如果这不是问题-内核在调用页面错误处理程序之前进行额外检查,因为最大用户空间地址是0x00007FFFFFFFF

综上所述,在x32体系结构中,地址在没有任何“验证”的情况下传递给页面错误处理程序,页面错误处理程序尝试加载页面,从而触发内核发送程序SEGFULT,但x64没有做到这一点


测试它,用0×00004141覆盖RIP,您将看到期望值被放置在RIP中,因为内核通过预检查,然后调用页面错误处理程序,就像x32一样(这当然会导致程序崩溃)。

您使用的是Linux吗?我认为,你还需要在那里设置一些标志。使用MacOSX。知道标志是什么吗?我不知道Mac OSX-可能与Ubuntu有很大不同(对不起,我实际上是在Ubuntu上做的,不是在Linux上)。@nhahdh Ubuntu是Linux发行版。缓冲区溢出通常不会覆盖寄存器变量。如果覆盖堆栈,返回地址可能会被覆盖,如果有帧指针(no
-fomit frame pointer
),帧指针也可能被覆盖。所以这些可能会被拉回到寄存器中,但那是因为堆栈首先被覆盖,而不是因为寄存器被直接覆盖。谢谢你的帮助,但我想知道是否有办法关闭该GPF,以便将RIP设置为
0x4141
,因为这就是我在使用的教程中发生的情况。@cabellicar123除非在该地址创建一个可执行页面,否则无法避免GPF。继续你的教程。下一步可能是提供一个特制的密码,使代码跳转到一个有效的地址。非常感谢您的帮助!