2013-08-29 60 views
0

我已经安装了一个名为DVL的Linux发行版(该死脆弱的Linux),以及我与缓冲区溢出攻击锻炼。 我写了其中两个很容易受到BOF几乎相同的程序:缓冲区溢出怪异的行为

//bof_n.c 
#include <stdio.h> 
void bof() { 
    printf("BOF"); 
} 

void foo(char* argv) { 
    char buf[10]; 
    strcpy(buf, argv); 
    prinf("foo"); 
} 

int main(int argc, char* argv[]) { 
    if (argc >= 1) { 
    foo(argv[1]); 
    } 
    return 0; 
} 

//bof.c 
#include <stdio.h> 
void bof() { 
    printf("BOF!\n");//this is the only change 
} 

void foo(char* argv) { 
    char buf[10]; 
    strcpy(buf, argv); 
    prinf("foo"); 
} 

int main(int argc, char* argv[]) { 
    if (argc >= 1) { 
    foo(argv[1]); 
    } 
    return 0; 
} 

,我编译他们两人之后,我获得了这两种情况下,BOF()函数的地址(例如,objdump -d bof.o | grep bof)。我们来命名一个4字节的地址ADDR。

我还发现,如果我写在BUF变量32字节,EIP寄存器是完全覆盖(因为它是在虚拟机上我不能在这里复制的gdb的输出)。现在

,如果我这样做:

./bof `perl -e 'print "\x90"x28 . "ADDR"'` 

我得到:

fooBOF! 
Segmentation fault 

相反,如果我尝试同样的方法,但使用bof_n,我只得到了 “段错误” 的消息。 因此我尝试增加ADDR值重复的次数,并且我发现如果重复至少350次,我会得到想要的结果。但是,如果没有上面的输出,我会一个接一个地看到一大串“BOF”消息。我试图获得只有一个“BOF”的信息,但显然我不能这样做(我得到或者是零,或者是一长串)。 这是为什么发生?任何想法?

我使用DVL用gcc 3.4.6

+1

大小'的perl -e“打印 “\ X90” X28的。 “ADDR”''> buf的大小[** 10 **]。 30+> 10. – someuser

+1

同样大小的perl'-e“打印 “\ X90” X28的结果。 “ADDR”“'可能超过10. – someuser

+0

@mbratch:软件所做的一切当然是完全确定性的。 – arul

回答

1

什么是你的目标是什么?

你应该真的使用调试器,尝试GDB Debuggergdb。有了它,你可以看到内存/寄存器/堆栈和反汇编系统当前正在进行的操作。

我猜想,在第一个函数中,字符串只有3个字符的长度,优化到\x42\x4f\x46\x00,所以反汇编可能会略有不同。

C源代码几乎无关紧要,您需要反汇编这两个二进制文件,或者需要fuzz来找到两个NOP雪橇的合适大小。

+0

好的,也许我不是很精确。我实际上使用GDB,并且在bof_n示例中,我最终发现问题出现在何时必须打印消息“BOF”。 eip被正确覆盖,执行跳转到bof()函数,唯一的问题是(我不知道为什么)printf在这种情况下不起作用。也许是由于flyshing,我会尝试使用fprintf和STDERR。 – badnack

0

我找到了解决方案。这个问题是关于消息的打印,而不是缓冲区溢出利用本身。 实际上,在bof_n示例中,注册eip也被正确覆盖,并且程序流正在bof()函数中正确重定向。问题在于,显然,在分段错误之前stdout没有被刷新,因此没有显示消息。

相反,使用fprintf(stderr, "BOF");,我终于得到了 “BOF” 的消息。