Unsorted Bin Attack
Last updated
Last updated
学习和实践 AWS 黑客技术:HackTricks 培训 AWS 红队专家 (ARTE) 学习和实践 GCP 黑客技术:HackTricks 培训 GCP 红队专家 (GRTE)
有关什么是未排序的 bin 的更多信息,请查看此页面:
未排序列表能够将地址写入 unsorted_chunks (av)
的 bk
地址。因此,如果攻击者能够修改未排序 bin 中一个 chunk 的 bk
指针的地址,他就能够将该地址写入任意地址,这可能有助于泄露 Glibc 地址或绕过某些防御。
所以,基本上,这种攻击允许在任意地址设置一个大数字。这个大数字是一个地址,可以是堆地址或 Glibc 地址。一个典型的目标是**global_max_fast
**,以允许创建更大尺寸的快速 bin(并从未排序 bin 攻击转到快速 bin 攻击)。
查看 https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle 中提供的示例,并使用 0x4000 和 0x5000 代替 0x400 和 0x500 作为 chunk 大小(以避免 Tcache),可以看到如今错误 malloc(): unsorted double linked list corrupted
被触发。
因此,这种未排序 bin 攻击现在(除了其他检查)还需要能够修复双向链表,以便绕过 victim->bk->fd == victim
或 victim->fd == av (arena)
,这意味着我们想要写入的地址必须在其 fd
位置具有假 chunk 的地址,并且假 chunk 的 fd
指向 arena。
请注意,这种攻击会破坏未排序的 bin(因此小和大也会)。所以我们现在只能使用快速 bin 的分配(更复杂的程序可能会进行其他分配并崩溃),并且要触发这一点,我们必须分配相同的大小,否则程序将崩溃。
请注意,覆盖 global_max_fast
可能在这种情况下有所帮助,前提是快速 bin 能够处理所有其他分配,直到利用完成。
来自 guyinatuxedo 的代码解释得很好,尽管如果你修改 malloc 以分配足够大的内存以避免 Tcache,你会看到之前提到的错误出现,阻止这种技术:malloc(): unsorted double linked list corrupted
这实际上是一个非常基本的概念。未排序 bin 中的 chunks 将具有指针。未排序 bin 中的第一个 chunk 实际上将具有**fd
** 和 bk
链接指向主 arena 的一部分 (Glibc)。
因此,如果你能够将一个 chunk 放入未排序 bin 并读取它(使用后释放)或在不覆盖至少 1 个指针的情况下再次分配它,然后读取它,你就可以获得Glibc 信息泄露。
在这个 写作中使用的类似攻击中,利用了一个 4 个 chunk 结构(A、B、C 和 D - D 仅用于防止与顶部 chunk 合并),因此在 B 中使用了一个空字节溢出,使 C 表示 B 未使用。此外,在 B 中修改了 prev_size
数据,因此大小不再是 B 的大小,而是 A+B。
然后 C 被释放,并与 A+B 合并(但 B 仍在使用中)。分配了一个大小为 A 的新 chunk,然后将泄露的 libc 地址写入 B,从而泄露了它们。
目标是用大于 4869 的值覆盖一个全局变量,以便能够获取标志,并且未启用 PIE。
可以生成任意大小的 chunks,并且存在所需大小的堆溢出。
攻击开始创建 3 个 chunks:chunk0 用于利用溢出,chunk1 被溢出,chunk2 以防止顶部 chunk 合并之前的 chunks。
然后,chunk1 被释放,chunk0 被溢出到 chunk1 的 bk
指针指向:bk = magic - 0x10
然后,分配一个与 chunk1 相同大小的 chunk3,这将触发未排序 bin 攻击并修改全局变量的值,从而使获取标志成为可能。
合并函数是脆弱的,因为如果传入的两个索引相同,它将对其进行重新分配,然后释放它,但返回一个指向该释放区域的指针,可以使用。
因此,创建了 2 个 chunks:chunk0 将与自身合并,chunk1 以防止与顶部 chunk 合并。然后,合并函数被调用两次与 chunk0,这将导致使用后释放。
然后,view
函数被调用,索引为 2(即使用后释放 chunk 的索引),这将泄露一个 libc 地址。
由于二进制文件具有保护措施,仅允许 malloc 大于 global_max_fast
的大小,因此不使用快速 bin,将使用未排序 bin 攻击来覆盖全局变量 global_max_fast
。
然后,可以调用编辑函数,索引为 2(使用后释放指针),并覆盖 bk
指针以指向 p64(global_max_fast-0x10)
。然后,创建一个新 chunk 将使用之前被破坏的释放地址 (0x20) 将触发未排序 bin 攻击,覆盖 global_max_fast
,这是一个非常大的值,现在允许在快速 bins 中创建 chunks。
现在执行 快速 bin 攻击:
首先发现可以在 __free_hook
位置处理大小为 200 的快速 chunks:
$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 的快速 chunk,将能够覆盖将被执行的函数指针。
为此,创建一个大小为 0xfc
的新 chunk,并调用合并函数两次使用该指针,这样我们就获得了一个指向大小为 0xfc*2 = 0x1f8
的释放 chunk 的指针。
然后,在此 chunk 中调用编辑函数以修改此快速 bin 的 fd
地址,使其指向之前的 __free_hook
函数。
然后,创建一个大小为 0x1f8
的 chunk,以从快速 bin 中检索之前无用的 chunk,因此创建另一个大小为 0x1f8
的 chunk 以获取 __free_hook
中的快速 bin chunk,该 chunk 被覆盖为 system
函数的地址。
最后,释放一个包含字符串 /bin/sh\x00
的 chunk,调用删除函数,触发 __free_hook
函数,该函数指向 system,参数为 /bin/sh\x00
。
另一个利用 1B 溢出合并未排序 bin 中的 chunks 并获取 libc 信息泄露的示例,然后执行快速 bin 攻击以用一个 gadget 地址覆盖 malloc hook。
我们只能分配大于 0x100
的 chunks。
使用未排序 bin 攻击覆盖 global_max_fast
(由于 ASLR,成功率为 1/16,因为我们需要修改 12 位,但必须修改 16 位)。
快速 bin 攻击以修改全局 chunk 数组。这提供了一个任意读/写原语,允许修改 GOT 并设置某些函数指向 system
。
学习和实践 AWS 黑客技术:HackTricks 培训 AWS 红队专家 (ARTE) 学习和实践 GCP 黑客技术:HackTricks 培训 GCP 红队专家 (GRTE)