hacktricks/binary-exploitation/heap/unsorted-bin-attack.md

9.3 KiB
Raw Blame History

未排序 Bin 攻击

从零开始学习 AWS 黑客技术,成为专家 htARTEHackTricks AWS 红队专家)

支持 HackTricks 的其他方式:

基本信息

有关未排序 bin 是什么的更多信息,请查看此页面:

{% content-ref url="bins-and-memory-allocations.md" %} bins-and-memory-allocations.md {% endcontent-ref %}

未排序列表能够将地址写入到块的 unsorted_chunks (av) 中的 bk 地址。因此,如果攻击者能够修改未排序 bin 中块内的 bk 指针的地址,他就能够将该地址写入到任意地址,这可能有助于泄漏 libc 地址或绕过某些防御。

因此,基本上,这种攻击允许用一个大数值覆盖一些任意地址(一个可能是堆地址或 libc 地址的地址),比如一些可能会泄漏的堆地址或一些限制,比如全局变量 global_max_fast,以允许创建更大尺寸的快速 bin 块(从未排序 bin 攻击转变为快速 bin 攻击)。

{% hint style="success" %} 查看 https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle 中提供的示例,并使用 0x4000 和 0x5000 而不是 0x400 和 0x500 作为块大小(以避免 tcaches可以看到现在触发错误 malloc(): unsorted double linked list corrupted

因此,这种未排序 bin 攻击现在(除其他检查外)还需要能够修复双重链接列表,以便绕过 victim->bck->fd == victim 或不是 victim->fd == av (arena)。这意味着我们想要写入的地址必须在其 fd 位置具有伪造块的地址,并且伪造块的 fd 指向 arena。 {% endhint %}

{% hint style="danger" %} 请注意,此攻击会破坏未排序 bin因此也会破坏小块和大块。因此我们现在只能使用快速 bin 中的分配(更复杂的程序可能会进行其他分配并崩溃),要触发此攻击,我们必须分配相同大小的块,否则程序将崩溃

请注意,使 global_max_fast 可能会在这种情况下有所帮助,相信快速 bin 将能够处理直到利用完成的所有其他分配。 {% endhint %}

来自 guyinatuxedo 的代码解释得非常清楚,尽管如果您修改 malloc 分配的内存大小足够大,以避免 tcache您会发现先前提到的错误出现阻止了这种技术malloc(): unsorted double linked list corrupted

未排序 Bin 信息泄漏攻击

这实际上是一个非常基本的概念。未排序 bin 中的块将具有双指针来创建 bin。未排序 bin 中的第一个块实际上将具有FDBK 链接指向主要 arenalibc的一部分
因此,如果您能够将一个块放入未排序 bin 中并读取它(使用后释放)或再次分配它而不覆盖至少 1 个指针,然后读取它,您就可以获得libc 信息泄漏

在这个写作中使用的攻击中,滥用了一个 4 个块结构A、B、C 和 D - D 仅用于防止与顶部块合并),因此在 B 中发生了一个空字节溢出,使 C 指示 B 未使用。此外,在 B 中修改了 prev_size 数据,使大小不再是 B 的大小,而是 A+B。
然后释放了 C并与 A+B 合并(但 B 仍在使用)。分配了一个大小为 A 的新块,然后将泄漏的 libc 地址写入 B从中泄漏。

参考资料和其他示例

  • https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap
  • 目标是用大于 4869 的值覆盖一个全局变量,以便获取标志并且未启用 PIE。
  • 可以生成任意大小的块,并且存在所需大小的堆溢出。
  • 攻击开始创建 3 个块chunk0 用于利用溢出chunk1 用于溢出chunk2 用于防止顶部块合并前两个。
  • 然后,释放 chunk1并且 chunk0 被溢出,使 chunk1 的 bk 指针指向:bk = magic - 0x10
  • 然后,分配了一个与 chunk1 大小相同的 chunk3这将触发未排序 bin 攻击,并修改全局变量的值,从而可能获取标志。
  • https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html
  • 合并函数存在漏洞,因为如果传递的两个索引相同,它将对其进行重新分配,然后释放它,但返回一个可以使用的指向该已释放区域的指针。
  • 因此,创建 2 个块chunk0 将与自身合并chunk1 用于防止与顶部块合并。然后,两次调用合并函数与 chunk0,这将导致使用后释放。
  • 然后,调用**view** 函数,使用索引 2使用后释放块的索引这将泄漏一个 libc 地址
  • 由于二进制文件只允许 malloc 大于**global_max_fast** 的大小,因此不会使用 fastbin将使用未排序 bin 攻击来覆盖全局变量 global_max_fast
  • 然后,可以使用索引 2使用后释放指针调用编辑函数并将 bk 指针覆盖为指向 p64(global_max_fast-0x10)。然后创建一个新块将使用先前受损的释放地址0x20触发未排序 bin 攻击,覆盖 global_max_fast 为一个非常大的值,现在可以在快速 bin 中创建块。
  • 现在执行快速 bin 攻击
  • 首先发现可以在 __free_hook 位置使用大小为 200 的快速
  • gef➤  p &__free_hook
    

$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook> gef➤ x/60gx 0x7ff1e9e607a8 - 0x59 0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200 0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000

  • 如果我们成功在这个位置获得一个大小为0x200的快速块就有可能覆盖一个将被执行的函数指针
  • 为此,创建一个大小为0xfc的新块,并使用该指针两次调用合并函数,这样我们就可以在快速块中获得一个大小为0xfc*2 = 0x1f8的已释放块的指针。
  • 然后,在这个块中调用编辑函数,修改这个快速块的**fd地址,使其指向前一个__free_hook**函数。
  • 然后,创建一个大小为0x1f8的块,从快速块中检索前一个无用块,然后创建一个大小为0x1f8的块,以在**__free_hook中获取一个快速块块,将其覆盖为system**函数的地址。
  • 最后,释放一个包含字符串/bin/sh\x00的块,调用删除函数,触发指向带有/bin/sh\x00参数的**__free_hook**函数。
  • CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html
  • 另一个滥用1字节溢出以合并未排序块并获取libc信息泄漏然后执行快速块攻击以用单个地址覆盖malloc挂钩的示例
从零开始学习AWS黑客技术 htARTEHackTricks AWS Red Team Expert

支持HackTricks的其他方式