Unsorted Bin Attack

Reading time: 10 minutes

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)

支持 HackTricks

Basic Information

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

Bins & Memory Allocations

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

所以,基本上,这种攻击允许在任意地址设置一个大数字。这个大数字是一个地址,可能是堆地址或 Glibc 地址。一个典型的目标是**global_max_fast**,以允许创建更大尺寸的快速 bin(并从未排序 bin 攻击转到快速 bin 攻击)。

tip

查看在 https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle 中提供的示例,并使用 0x4000 和 0x5000 代替 0x400 和 0x500 作为块大小(以避免 Tcache),可以看到如今错误**malloc(): unsorted double linked list corrupted**被触发。

因此,这种未排序 bin 攻击现在(除了其他检查)还需要能够修复双向链表,以便绕过 victim->bk->fd == victimvictim->fd == av (arena),这意味着我们想要写入的地址必须在其 fd 位置具有假块的地址,并且假块的 fd 指向 arena。

caution

请注意,这种攻击会破坏未排序 bin(因此小和大也会)。所以我们现在只能使用快速 bin 的分配(更复杂的程序可能会进行其他分配并崩溃),并且要触发这一点,我们必须分配相同的大小,否则程序将崩溃。

请注意,覆盖**global_max_fast**可能在这种情况下有所帮助,信任快速 bin 能够处理所有其他分配,直到利用完成。

来自 guyinatuxedo 的代码解释得很好,尽管如果你修改 malloc 以分配足够大的内存以避免 Tcache,你会看到之前提到的错误出现,阻止这种技术:malloc(): unsorted double linked list corrupted

Unsorted Bin Infoleak Attack

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

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

References & Other examples

  • 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 的大小,因此不使用快速 bin,将使用未排序 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 的释放块的指针,在快速 bin 中。
  • 然后,在此块中调用编辑函数以修改此快速 bin 的**fd地址,使其指向之前的__free_hook**函数。
  • 然后,创建一个大小为 0x1f8 的块,以从快速 bin 中检索之前无用的块,因此创建另一个大小为 0x1f8 的块以获取**__free_hook中的快速 bin 块,该块被覆盖为system**函数的地址。
  • 最后,释放一个包含字符串 /bin/sh\x00 的块,调用删除函数,触发**__free_hook**函数,该函数指向 system,参数为 /bin/sh\x00
  • CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html
  • 另一个利用 1B 溢出合并未排序 bin 中的块并获取 libc 信息泄露的示例,然后执行快速 bin 攻击以用一个 gadget 地址覆盖 malloc hook。
  • Robot Factory. BlackHat MEA CTF 2022
  • 我们只能分配大于 0x100 的块。
  • 使用未排序 bin 攻击覆盖 global_max_fast(由于 ASLR,成功率为 1/16,因为我们需要修改 12 位,但必须修改 16 位)。
  • 快速 bin 攻击以修改全局块数组。这提供了一个任意读/写原语,允许修改 GOT 并设置某些函数指向 system

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)

支持 HackTricks