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

8.6 KiB
Raw Blame History

未排序 Bin 攻击

{% hint style="success" %} 学习并练习 AWS 黑客技术:HackTricks 培训 AWS 红队专家 (ARTE)
学习并练习 GCP 黑客技术:HackTricks 培训 GCP 红队专家 (GRTE)

支持 HackTricks
{% endhint %}

基本信息

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

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

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

因此,基本上,这种攻击允许在任意地址设置一个大数。这个大数是一个地址,可以是堆地址或 Glibc 地址。一个典型的目标是**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 作为块大小(以避免 Tcache可以看到现在触发了错误**malloc(): unsorted double linked list corrupted**。

因此,这种未排序 bin 攻击现在(除其他检查外)还需要能够修复双重链接列表,以便绕过 victim->bk->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 中的第一个块实际上将使 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从中泄漏出去。

参考资料和其他示例

  • 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

</strong>0x7ff1e9e6075f: 0x0000000000000000      0x0000000000000000
0x7ff1e9e6076f &#x3C;list_all_lock+15>:      0x0000000000000000      0x0000000000000000
0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000      0x0000000000000000
</code></pre>
* 如果我们成功在这个位置获得一个大小为0x200的快速块就可以覆盖一个将被执行的函数指针
* 为此,创建一个大小为`0xfc`的新块,并使用该指针两次调用合并函数,这样我们就可以获得一个指向大小为`0xfc*2 = 0x1f8`的已释放块的指针。
* 然后,在这个块中调用编辑函数,修改这个快速块的**`fd`**地址,使其指向之前的**`__free_hook`**函数。
* 然后,创建一个大小为`0x1f8`的块,从快速块中检索之前无用的块,然后创建一个大小为`0x1f8`的块,以在**`__free_hook`**中获取一个快速块块,该块被覆盖为**`system`**函数的地址。
* 最后,释放一个包含字符串`/bin/sh\x00`的块,调用删除函数,触发指向带有`/bin/sh\x00`参数的`system`的**`__free_hook`**函数。
* **CTF** [**https://guyinatuxedo.github.io/33-custom\_misc\_heap/csaw19\_traveller/index.html**](https://guyinatuxedo.github.io/33-custom\_misc\_heap/csaw19\_traveller/index.html)
* 另一个滥用1字节溢出以合并未排序块并获取libc信息泄漏然后执行快速块攻击以用单个地址覆盖malloc挂钩的示例
* [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
* 我们只能分配大于`0x100`的块大小。
* 使用未排序块攻击覆盖`global_max_fast`由于ASLR每16次有效因为我们需要修改12位但必须修改16位。
* 快速块攻击以修改全局块数组。这提供了一个任意读/写原语允许修改GOT并将某些函数指向`system`。