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
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
Basic Information
有关未排序的 bin 的更多信息,请查看此页面:
未排序列表能够将地址写入 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 == victim
或 victim->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 中的第一个块实际上将具有**fd
和bk
链接指向主 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
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。