使用堆溢出来写入任意数据

时间:2012-03-10 12:58:00

标签: c security heap exploit

我一直在努力学习堆溢出攻击的基础知识。我最感兴趣的是使用损坏或修改块元数据作为攻击的基础,但我也对其他建议持开放态度。我知道我的挖掘目标应该是用printf()函数指针覆盖challenge()函数指针,但我似乎无法弄清楚如何实现该写入。 我有以下要利用的代码,它使用malloc中的glibc 2.11.2

void challenge()
{
        puts("you win\n");
}

int main(int argc, char **argv)
{
        char *inputA, *inputB, *inputC;

        inputA = malloc(32);
        inputB = malloc(32);
        inputC = malloc(32);

        strcpy(inputA, argv[1]);
        strcpy(inputB, argv[2]);
        strcpy(inputC, argv[3]);

        free(inputC);
        free(inputB);
        free(inputA);

        printf("execute challenge to win\n");
}

显然,实现对已分配块的元数据的实际覆盖是微不足道的。但是,我还没有找到使用任何标准技术来利用此代码的方法。 我已阅读并试图实施以下技术:

  • 论文:Heap Overflows上的w00w00
    • 虽然论文很清楚,但unlink技术已经过时了一段时间。
  • Malloc Maleficarum.txt
    • 本文详细介绍了w00w00时代的漏洞利用技术,并介绍了glibc的新版本。但是,我没有发现,鉴于本文详述的5种技术,上述代码符合这些技术的任何先决条件。
  • Understanding the Heap By Breaking it(pdf)
    • pdf非常好地回顾了堆的工作原理,但重点介绍了双重免费技术。

我最初尝试通过操作inputC的块的大小值来利用此代码,以便它指向inputC块的头部。当这不起作用时,我尝试进一步指向inputB的块。那时我意识到新的glibc会对尺寸值进行健全性检查。

如果用户能够将分配的块的元数据编辑为任意值,并且用户可以覆盖GOT中的值或写入任何其他任意地址,那么用户如何利用免费利用漏洞利用?

注意:当我写'任意地址'时,我知道内存页面可能只读或受保护,我的意思是我可以假设我可以写入的地址。

3 个答案:

答案 0 :(得分:11)

注意:在我回答之前我会说这纯粹是学术上的答案,并非用于恶意目的。我知道OP正在进行的练习,它们是开源的,并不是为了鼓励任何用户在未经批准的情况下使用这些技术。

我将详细介绍下面的技术,但是为了您的参考,我会看一下Vudo malloc技巧(它在上面的一个链接中引用)因为我的概述很简短:http://www.phrack.com/issues.html?issue=57&id=8 < / p>

详细说明了malloc如何处理创建内存块,从列表和其他内容中提取内存。特别是unlink攻击对于这次攻击很有意义(注意:你是正确的,glibc现在对这个特殊原因进行大小的健全性检查,但是你应该使用较旧的libc进行此练习......遗留兄弟)。

从论文中,分配的块和空闲块使用相同的数据结构,但数据的处理方式不同。见这里:

chunk -> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         | prev_size: size of the previous chunk, in bytes (used   |
         | by dlmalloc only if this previous chunk is free)        |
         +---------------------------------------------------------+
         | size: size of the chunk (the number of bytes between    |
         | "chunk" and "nextchunk") and 2 bits status information  |
  mem -> +---------------------------------------------------------+
         | fd: not used by dlmalloc because "chunk" is allocated   |
         | (user data therefore starts here)                       |
         + - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
         | bk: not used by dlmalloc because "chunk" is allocated   |
         | (there may be user data here)                           |
         + - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
         |                                                         |
         |                                                         |
         | user data (may be 0 bytes long)                         |
         |                                                         |
         |                                                         |
 next -> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         | prev_size: not used by dlmalloc because "chunk" is      |
         | allocated (may hold user data, to decrease wastage)     |
         +---------------------------------------------------------+

分配的块不使用fd或bk指针,但是免费的指针。这在以后会变得很重要。你应该知道足够的编程来理解Doug Lea的malloc中的“块”被组织成一个双向链表;有一个用于空闲块的列表和另一个用于已分配的列表(技术上有几个免费列表,具体取决于大小,但由于代码分配了相同大小的块,因此它无关紧要)。因此,当你释放一个特定的块时,你必须修复指针以保持列表的顺利。

e.g。说你从下面的列表中释放了块y:

x <-> y <-> z

请注意,在上图中,bk和fd的斑点包含沿列表迭代的必要指针。当malloc想要从列表中取出一个块p时,它会调用一个宏来修复列表:

#define unlink( y, BK, FD ) {            
    BK = P->bk;                          
    FD = P->fd;                          
    FD->bk = BK;                         
    BK->fd = FD;                         
}

宏本身并不难理解,但在旧版本的libc中需要注意的重要一点是它不会对大小或写入的指针执行完整性检查。在您的情况下,它意味着没有任何类型的地址随机化,您可以通过以特定方式溢出堆(通过此处的strncopy)可预测并可靠地确定堆的状态并将任意指针重定向到您选择的地址

让攻击发挥作用需要一些东西:

  • 块的fd指针指向要覆盖的地址减去12个字节。偏移量与malloc在修改列表时清理对齐方式有关
  • 您的块的bk指针指向您的shellcode
  • 大小需要为-4。这完成了一些事情,即它设置块中的状态位

因此,您必须在特定示例中使用偏移量,但是您尝试使用strcpy传递的一般恶意格式的格式为:

|垃圾填满合法缓冲区| -4 | -4 |你要覆盖的addr -12(0x0C)|你要打电话的地址

注意负数将prev_size字段设置为-4,这使得空闲路由认为prev_size块实际上是在您控制/正在破坏的当前块中启动的。

是的,如果没有提到这种攻击对当前版本的glibc不起作用,那么正确的解释是不完整的。大小已完成完整性检查,unlink方法不起作用。与地址随机化等缓解措施相结合,使得这种攻击在遗留系统之外的任何事情上都不可行。但这里描述的方法就是我如何应对这一挑战;)

答案 1 :(得分:3)

请注意,Malloc Malleficarum中解释的大多数技术现在都受到保护。 glibc已经改进了很多双重免费场景。

如果您想提高您对Malloc Malleficarum技术的了解,请阅读Malloc Des-Malleficarum和House of Lore:由blackngel撰写的Reloaded。你可以在phrack中找到这些文本。

Malloc Des-Malleficarum

我也正在研究它,我可以告诉你,例如,House of Mind不再可利用,至少,正如文中所解释的那样。虽然可以绕过添加到代码中的新限制。 另外,执行代码的最简单方法是覆盖.dtors地址,因此一旦程序完成,代码将始终执行。

如果您下载glibc代码并研究malloc等的批评区域,您将找到前面提到的文档中未记录的代码检查。这些检查包括在内以阻止双重自由派对。

另一方面,你可以在youtube(BlackHat 2007)中找到的Justin N. Ferguson(通过破解它来理解堆)的介绍是完美的,以便了解所有的堆机制,但我必须承认所显示的技术远非可靠,但至少,他开辟了一个新的领域来堆积利用。

Understanding the heap by breaking it

无论如何,我也在努力,所以如果你想和我联系,我们可以分享我们的进步。你可以在overflowedminds.net域中找到我作为newlog(自己建立邮件地址^^)。

答案 2 :(得分:-2)

堆溢出很难实现,并且依赖于堆布局非常繁重,尽管看起来你正在追踪Windows CRT堆,它有很多缓解措施专门用于阻止这种类型的攻击。 / p>

如果你真的想要做这种事情,你需要快乐地跳进WinDbg并进入免费的功能,看看游戏中究竟发生了什么,以及你可以实现什么样的控制通过前一个值的堆溢出。

我不会给你任何比这更具体的帮助,原因很简单,证明堆溢出通常足以防御安全 - 防御安全专家可以报告堆溢出而无需实际充分利用它。 的唯一人需要完全利用堆溢出一直到远程代码执行的人是利用进攻的错误,如果你想这样做,你'靠你自己。