Stack Smashing尝试给出段错误

时间:2009-01-29 08:14:22

标签: c buffer-overflow shellcode

我试图从C中的Smashing the Stack for Fun and Profit做一个例子,但是有点卡在某一点上, 以下是代码(我有一个64位的Ubuntu 64位机器):

int main()
{
    int x;

    x = 0;
    func(1,2,3);
    x = 1;
    printf("x is : %d\n", x);
}

void func(int a, int b, int c)
{
    char buffer[1];
    int *ret;

    ret = buffer + 17;
    (*ret) += 7;
}

上面的代码工作正常,返回时x=1行没有执行,但是我无法理解ret = buffer + 17;背后的逻辑,不应该是ret = buffer + 16;,即8字节缓冲区为8,堆栈上保存的基指针为8。

其次,我的理解是char buffer[1]占用8个字节(由于64位拱) 如果我将此缓冲区增加到buffer[2],仍然相同的代码应该正常工作,但这不会发生并且它开始给出seg错误。

此致 努曼

5 个答案:

答案 0 :(得分:13)

我使用的每个架构上的'char'都是8位宽,无论它是8位微,16位微,32位PC还是64位新PC。另一方面,Int往往是单词大小。

本地人放在堆栈上的顺序可以是特定于实现的。我的猜测是你的编译器在“char buffer 1”之前将“int * ret”放在堆栈上。因此,要获得返回地址,我们必须通过“char buffer 1”(1字节),“int * ret”(8字节)和保存的基本指针(8字节)总计17字节。

这是x86 64位上堆栈帧的描述: http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-035-computer-language-engineering-spring-2010/projects/x86-64

答案 1 :(得分:9)

逐步完成gdb中的反汇编(反汇编,stepi,nexti),并查看每一步的寄存器(信息寄存器)。

您可以在此处逐步进行反汇编:

gdb ./myprogram
break main
run
display/4i $eip
stepi
stepi
...
info registers
...

你应该也知道(你可能已经知道你已经完成了部分工作)在许多发行版中,默认情况下在gcc中启用堆栈保护程序。您可以使用-fno-stack-protector手动禁用它。

答案 2 :(得分:3)

有很多这个堆栈粉碎的东西,你最好的朋友是gdb。既然你已经分段了,那么你已经在写记忆了,你不应该这样做(一个好兆头)。一种更有效的方法是将返回地址更改为有效地址的其他地方(例如,更改为func的地址或您已获得的某些shellcode)。我推荐的一个很好的资源是Shellcoder's Handbook,但是由于你使用的是64位架构,很多例子都需要一些工作才能开始。

答案 3 :(得分:0)

除了运行调试器(或者更好)之外,您还可以使用printf“%p”结构来打印变量的地址,例如:

printf("buf: %p\n", buffer); //&buffer[0] works too; &buffer works for an array
printf("ret: %p\n", &ret):
printf("a:   %p\n", &a);

打印各种地址可以深入了解编译器/实现如何在后台安排事情。你也可以直接从C代码中完成它!

答案 4 :(得分:0)

如果您对x64缓冲区溢出漏洞感兴趣,请考虑查看stealth's borrowed code chunk technique