【问题标题】:Heap Overflow Issue - Can Overwrite Chunk Header, Corrupt Free(), But Program Doesn't Crash堆溢出问题 - 可以覆盖块头,Corrupt Free(),但程序不会崩溃
【发布时间】:2012-08-06 09:40:58
【问题描述】:

我一直在研究计算机漏洞,并且已经在这个问题上工作了无数个小时。 我似乎无法让堆正确溢出。尽管 glibc 检测到内存损坏,但在禁用 MALLOC_CHECK_ 后,我的程序会正确执行并退出,就好像覆盖块头无关紧要一样。我正在运行 Kubuntu 12.04。

这个练习来自“The Shellcoder's Handbook, 2nd Edition”,也出现在 Heap Overflow 在线教程中。我已多次按照 T 的说明进行操作,并收到相同的结果。

这是我的程序的代码:

/*basicheap*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int main(int argc, char ** argv){

    char *buf;
    char *buf2;

buf=(char*)malloc(1024);
buf2=(char*)malloc(1024);
printf("buf=%p buf2=%p\n", buf, buf2);
strcpy(buf,argv[1]);
free(buf2);
free(buf);
}

当我使用 glibc 写入缓冲区时:

xxx@xxx-xxx:~/CProgs$ ./basicheap $(perl -e 'print "A"x1028')
buf=0x9356718 buf2=0x9356b20
*** glibc detected *** ./basicheap: double free or corruption (!prev): 0x09356b20 ***
======= Backtrace: =========
[0x804abff]
[0x8048f4a]
[0x80490d6]
[0x8048e29]
======= Memory map: ========
08048000-080ec000 r-xp 00000000 08:07 6816172    /home/xxx/CProgs/basicheap
080ec000-080ee000 rw-p 000a3000 08:07 6816172    /home/xxx/CProgs/basicheap
080ee000-080f0000 rw-p 00000000 00:00 0 
09355000-09377000 rw-p 00000000 00:00 0          [heap]
b772a000-b772c000 rw-p 00000000 00:00 0 
b772c000-b772d000 r-xp 00000000 00:00 0          [vdso]
bfc14000-bfc36000 rw-p 00000000 00:00 0          [stack]
Aborted (core dumped)
xxx@xxx-xxx:~/CProgs$ 

当我在关闭 glibc 的情况下写入缓冲区时:

xxx@xxx-xxx:~/CProgs$ MALLOC_CHECK_=0 ./basicheap $(perl -e 'print "A"x1028')
buf=0xa077718 buf2=0xa077b20
xxx@xxx-xxx:~/CProgs$

没有覆盖的块头的GDB:

(gdb) run $(perl -e 'print "A"x1024')
Starting program: /home/xxx/CProgs/basicheap $(perl -e 'print "A"x1024')
buf=0x80f1718 buf2=0x80f1b20

Breakpoint 1, main (argc=2, argv=0xbfffedf4) at basicheap.c:16
16      free(buf2);
(gdb) x/x buf2-4
0x80f1b1c:      0x00000409
(gdb) x/x buf2-8
0x80f1b18:      0x00000000
(gdb) x/x buf2-12
0x80f1b14:      0x41414141
(gdb) 

带有覆盖的块头的GDB:

(gdb) run $(perl -e 'print "A"x1032')
Starting program: /home/xxx/CProgs/basicheap $(perl -e 'print "A"x1032')
buf=0x80f1718 buf2=0x80f1b20

Breakpoint 1, main (argc=2, argv=0xbfffede4) at basicheap.c:16
16      free(buf2);
(gdb) x/x buf2-4
0x80f1b1c:      0x41414141
(gdb) x/x buf2-8
0x80f1b18:      0x41414141
(gdb) x/x buf2-12
0x80f1b14:      0x41414141
(gdb) 

两次程序都正常退出。 我错过了什么?他们是否改变了堆在最新版本的 Ubuntu 上的工作方式? 任何帮助将不胜感激!

更新:我在 gdb 中单步执行了程序集,发现我的程序进入了函数 free_check() 和函数 mem2chunk_check()。

在 mem2chunk_check() 函数中,我覆盖的值在 ESI 寄存器中被拾取,EDI 寄存器指向该值的地址。我看到它对我在 ESI 中的值所做的唯一一件事就是减去 1,然后转储该值。

经过多次 google 搜索,我无法找到有关 mem2chunk_check() 函数的任何文档。

这些堆溢出在现代系统上是否已过时?

【问题讨论】:

  • 对于您的更新:如果您编译带有 -g 标志的 ptmalloc 库,您将能够在调试时查看代码,而不仅仅是汇编程序。还有一件事......你不会找到任何类型的文档或审查代码本身。只是我在另一篇文章中提到的链接。

标签: c ubuntu security heap-memory


【解决方案1】:

在过去几年中,供应商默认使用任何内存操作功能的“强化”版本。例如,你得到'builtin_memset_chk'而不是memset,而不是strcpy,你得到'strcpy_chk'

要使您的简单溢出程序正常工作,您必须使用以下内容构建程序:

-fno-stack-protector -D_FORTIFY_SOURCE=0

【讨论】:

  • 感谢您的快速回复。我已经尝试过您的建议,但问题仍然存在。我四处搜索并尝试过:-fno-builtin-memset -fno-builtin 但是,这些似乎也没有什么不同。我在 gdb 中逐步检查了程序集,发现在一个名为:mem2chunk_check ESI 的函数中提取了我溢出的值,EDI 指向它。但是,我仍然遇到问题。
  • 希望我能提供更多帮助,但我没有高水平漏洞利用的经验。我确实知道,截至 2006 年,硬件和软件方面已经有了越来越多的发展,以减轻典型/已知的漏洞利用路线。您可能会发现仅进行堆溢出很难。
  • 很高兴知道。非常感谢您的时间和帮助!我真的很感激。
【解决方案2】:

首先,现在,Linux 中的堆利用非常困难。嗯,不同的缓冲区溢出很容易覆盖,但难的是执行任意代码。

如果你想了解堆利用的内部工作原理,你应该阅读我在这篇文章中提到的论文:Use a heap overflow to write arbitrary data

一旦你理解了这些概念,我会警告你说 malloc malleficarum 中使用/解释的大多数方法都(默默地)修补了。我不知道这些中的任何一个今天是否仍然有效。

另一方面,如果你真的想提高你的知识,我建议你下载 ptmalloc 实现(来自http://www.malloc.de/en/),它是基于 Linux 分配器的一个,编译它(“make shared ”,添加“-g”标志也很有用)并使用 LD_PRELOAD 加载它。这样你就可以用 gdb 一步步调试 malloc 代码了。

祝你好运!

【讨论】:

    猜你喜欢
    • 2018-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    • 2012-04-02
    相关资源
    最近更新 更多