ctfwiki堆溢出总结

堆溢出小总结

Column: Apr 12, 2021
Tags: Pwn, summary

开头的一些碎碎念:

除了fastbin大小的chunk,其余物理相邻topchunk的chunk在free之后都会合并进topchunk

利用malloc_hook通常是在main_arena-0x23-8的位置有个0x7f可以被识别为fakechunk(free_hook还不会,悲)

Uaf:

堆被free之后,指向其的指针未被置空导致fd与bk之类的关键信息可以被编辑, 还有一种就是double free之类的

Off by one:

一种特殊形式的堆溢出,常见于自定义输入函数,在循环之后将最后一位置零却因为没考虑max输入数量时会将输入范围的下一位置零,可以考虑申请0x100大小之类的chunk这样刚好改变其inuse位, 还有一种是栏杆问题, 就是n的大小允许输入n+1个字节, 这种就可以直接改高地址的chunk的size了

Unlink:

利用了ptmalloc中的unlink机制(注意不是consolidation),合并时只检查p->fd->bk所指向的地址是否与p->bk->fd一致(合法地址,00什么的肯定是不行的),常见利用形式是伪造一个chunk,其fd与bk分辨是全局指针ptr的ptr-0x18,ptr-0x10使得ptr最终指向ptr-0x18

Chunk Extend and Overlapping:

  1. inuse fastbin: 修改正在使用的fastbin的header使得其包含附近的chunk
  2. inuse smallbin: 和fastbin差不多,除了要防止与topchunk合并
  3. free unsortedbin: 修改其header中的size,就能申请到指定大小的chunk
  4. 向前extend: 就改一下chunk的size就行,不过大小要构造好
  5. 向后extend: 修改chunk的pre_size和inuse,利用unlink合并

(可以构造好几个fakechunk混着来泄露)

Fastbin attack:

  1. double free: 相同大小chunk1和2,free 1 2 1这样1就被double free了,再次malloc可以修改1的fd,再malloc三次就是自己选定的malloc地址了(注意伪造header的size),是一种uaf利用方式
  2. House of spirit: 伪造好fakechunk(注意header的一些判断)然后分配给他,感觉这玩意经常用, 只是自己感觉不出来, 还有一种好方法(alloc to stack)就是在栈上伪造, free后再分配, 就可以控制更大的栈空间
  3. Alloc to stack: house of spirit的chunk伪造在了stack上,推荐做西湖论剑2020的mmutag
  4. Arbitrary alloc:字面意思,通常是会分配到main_arena-0x23处利用malloc_hook

Unsortedbin attack:

修改unsortedbin链表中的bk, 可以在分配unsortedbin大小的chunk时分配写在bk上的地址给它, 但是用的少, 一是因为很少有题目是只让你从bk开始修改的, 因此unsortedbin链表的fd被破坏可能会导致奇奇怪怪的问题, 二是因为uaf的情况下明显fastbin attack什么的更香啊

Largebin attack:

未来可期

House Of Einherjar:

一种向后extend, 但它的方法是想把非fastbin大小的chunk修改其header中的inuse和pre_size, 但是其pre_size是等于target_fake_chunk_address - current_chunk_address这样通过unlink操作就可以直接使得放入链表的chunk地址为target_fake_chunk_address, 同时fake_chunk的fd和bk都可以设置为target_fake_chunk_address, 但注意由于有可能算出来的pre_size大的过分所以在下次分配的时候最好修改游戏fake_chunk的size

House Of Force:

通过修改topchunk的size使得下次能够分配到指定地址(next_topchunk_addr=now_topchunk_addr+nb), 首先修改size要尽可能开的足够大使得攻击能够成功(通常0xfffffffffffff), 之后虽然传入malloc的大小(nb)是负数的话会被转化为无符号数(这也就是为什么我们前面要让size足够大), 但是在源码中topchunk分配完之后的地址:

#define chunk_at_offset(p, s) ((mchunkptr)(((char *) (p)) + (s)))
remainder      = chunk_at_offset(victim, nb);
av->top        = remainder;
//nb不是无符号数

所以在当前malloc结束之后topchunk就会跑到指定地址处(now_topchunk_addr+nb), 下一次分配就会从指定地址开始了

House Of Orange:

在没有free函数的情况下, 通过修改topchunk_size, 但是为了页对齐, 所以其大小为topchunk_size&0x7, 但有的时候&0x3也可以, 之后我们再申请一个大于topchunk_size的chunk, 就会使得被修改的topchunk放入对应大小的bin中, 从而构造出free_chunk, 通常配合IO_FILE使用

House Of Rabbit:

我个人认为也是一种extend, 但是它是利用了consolidation对fastbin大小的chunk进行合并到smallbin中, 有两种利用方式:

  1. 修改前一个chunk的size, 使得相邻的chunk被包含或者被fakechunk分割
  2. 修改已经被free的一个chunk的fd使其指向一个fakecunk使得fakechunk被放入smallbin中

House Of Roman:

通过爆破修改残留在fastbin大小chunk(通过uaf, extend等构造)的fd上的main_arena+88的低两个字节为main_arena-0x23(说是爆破, 就是假设一下低两个字节, 例如假设为0x1000-0x23, 即假设低两个字节为\x0f\xdd, 然后写个脚本慢慢爆破就行了), 分配成功的话, 然后就可以直接写入onegadget来getshell了

Tcache attack:

适用于glibc2.27即以上版本, 其实我没怎么实战碰到2.27上的, 所以可能写的不是很好(呆滞)

  1. tcache poisoning: 修改被分配进tcache中的chunk的next指针就能任意写了(蛮离谱的)
  2. tcache dup: 已经噶了的方法, 至少在我电脑上已经不能用了
  3. 因为tcache_perthread_struct结构体通常就在heap_base的开头, 那么我们可以尝试partial wrtie之类来直接在结构体中写入地址, 再malloc对应大小以达到任意写的目的
  4. tcache house of spirit: 类似之前fastbin attack的hos, 但是可控大小更大, 不局限于fastbin大小了
  5. smallbin unlink: 类似之前的unlink
  6. tcache stashing unlink attack: 当程序中出现了calloc时则可以考虑这种攻击方式, 因为calloc不会从tcache中申请空间, 而是直接从bin中寻找, 同时根据tcache的LIFO与smallbin的FIFO策略, 我们可以尝试在tc分配满之后, 让相同大小的chunk进入smallbin中, 之后从tc中申请些空间, 让tc可以继续放入, 然后我们利用calloc从smallbin中分配, 由于tc有剩余, 则smallbin的链会接入tc中, tc只对链入的第一个chunk有检测, 所以我们把fake_chunk_addr放第二个就行了
  7. libc leak: 需要先填满tcache, 然后才可以放入unsortedbin中泄露出libc, 或者开个更大的chunk突破tc的size限制也可以的说

结尾杂谈:

我依稀记得自己之前学过两次堆溢出, 然后每次一个月, 都是只学了fastbin attack就不学了, 这次二十天就全学完了, 只能说以前真是太懒了, 哎

猜你喜欢

转载自blog.csdn.net/eeeeeight/article/details/115631201