首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >C++中的缓冲区溢出

C++中的缓冲区溢出
EN

Stack Overflow用户
提问于 2011-06-03 04:48:25
回答 4查看 11.3K关注 0票数 19

我正尝试在64位Mac OS X 10.6上使用C编写一个简单的缓冲区溢出。概念是这样的:

代码语言:javascript
复制
void function() {
    char buffer[64];
    buffer[offset] += 7;    // i'm not sure how large offset needs to be, or if
                            // 7 is correct.
}

int main() {

    int x = 0;
    function();
    x += 1;
    printf("%d\n", x);      // the idea is to modify the return address so that
                            // the x += 1 expression is not executed and 0 gets
                            // printed

    return 0;
}

下面是main的汇编转储的一部分:

代码语言:javascript
复制
...
0x0000000100000ebe <main+30>:   callq  0x100000e30 <function>
0x0000000100000ec3 <main+35>:   movl   $0x1,-0x8(%rbp)
0x0000000100000eca <main+42>:   mov    -0x8(%rbp),%esi
0x0000000100000ecd <main+45>:   xor    %al,%al
0x0000000100000ecf <main+47>:   lea    0x56(%rip),%rdi        # 0x100000f2c
0x0000000100000ed6 <main+54>:   callq  0x100000ef4 <dyld_stub_printf>
...

我想跳过movl指令,这意味着我需要将返回地址递增42 - 35 =7(对吗?)。现在我需要知道返回地址存储在哪里,这样我才能计算正确的偏移量。

我尝试手动搜索正确的值,但要么打印出1,要么得到abort trap --是否存在某种缓冲区溢出保护?

使用偏移量88在我的机器上工作。我使用了Nemo的方法来查找返回地址。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-06-03 05:03:16

32位示例说明了如何解决此问题,请参见下面的64位示例:

代码语言:javascript
复制
#include <stdio.h>

void function() {
    char buffer[64];
    char *p;
    asm("lea 4(%%ebp),%0" : "=r" (p));  // loads address of return address
    printf("%d\n", p - buffer);         // computes offset
    buffer[p - buffer] += 9;            // 9 from disassembling main
}

int main() {
    volatile int x = 7;
    function();
    x++;
    printf("x = %d\n", x); // prints 7, not 8
}

在我的系统上,偏移量是76。这是缓冲区的64个字节(记住,堆栈向下增长,所以缓冲区的起始位置远离返回地址)加上中间的任何其他碎片。

显然,如果你正在攻击一个现有的程序,你不能指望它为你计算出答案,但我认为这说明了原理。

(而且,幸运的是,+9没有执行到另一个字节。否则,单字节增量将不会按照我们预期的方式设置返回地址。如果main中的返回地址不走运,这个示例可能会崩溃。)

不知何故,我忽略了原问题的64位。x86-64的等价物是8(%rbp),因为指针是8字节长。在这种情况下,我的测试构建恰好产生了104的偏移量。在上面的代码中,使用双%%替换8(%%rbp),以获得输出程序集中的单个%。这在this ABI document中有描述。搜索8(%rbp)

评论中有人抱怨说,4(%ebp)76或任何其他任意数字一样神奇。实际上,寄存器%ebp (也称为“帧指针”)的含义及其与堆栈上返回地址的位置的关系是标准化的。我很快搜索到的一个例子是here。这篇文章使用了术语“基指针”。如果您想要利用其他架构上的缓冲区溢出,则需要对该CPU的调用约定有类似的详细了解。

票数 13
EN

Stack Overflow用户

发布于 2011-06-03 05:02:17

Roddy是对的,你需要对指针大小的值进行操作。

我会从读取你的exploit函数中的值(并打印它们)开始,而不是写它们。当您爬行通过数组的末尾时,您应该开始看到堆栈中的值。不久,您应该找到返回地址,并能够将其与反汇编程序转储对齐。

票数 4
EN

Stack Overflow用户

发布于 2011-06-03 04:53:29

您可以尝试在调试器中运行代码,一次单步执行每条装配线,并检查堆栈的内存空间和寄存器。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6220212

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档