gun
保护全开,且沙箱限制了只能使用open,read,write,exit4个函数
总共有3个功能,买子弹,上膛,发射,购买时可以给子弹命名,发射时会输出 子弹名字
1 | 1.Shoot |
每发子弹都有一个标志位,放在全局数组0x4070
中
1 | 1 - 已购买,未上膛 |
buy
1 | int __usercall buy@<eax>(__int64 a1@<rbp>) |
read_str函数没有0截断,所以可以用来泄漏地址
load
1 | int __usercall load@<eax>(__int64 a1@<rbp>) |
子弹上膛函数,FILO,这个弹夹是一个栈结构,0x4050
放着的是最后上膛的子弹
漏洞函数 shoot
1 | int __usercall shoot@<eax>(__int64 a1@<rbp>) |
存在UAF。值得注意的是,不仅是heap指针未清空,子弹前后关系的链表也没有清空
所以需要利用这个UAF造出个double free来
先购买并发射3发子弹,上膛顺序为2,1,0,发射后再购买1发子弹并上膛,之后再发射3发子弹,即可实现doubler free
像这样的构造方式就可以double free了,但是在glibc2.31的tcache中像 A->B->A还是会触发double free报错的,所以需要将这个double free构造在fastbin中去
这里注意对于fastbin double free的构造需要使用两个没有在tcache链表中的chunk来实现,如:
1 | tcache[0x40]:1->2->3->4->5->6->7 |
因为虽然 tcache满足了,但是如果再一次free(1)的话还是会进入tcache分支进行检测,这个时候就会触发double free了
构造如下图
orw
double free实现后就可以写free_hook了,但是从glibc2.29后,setcontext函数的参数不再是rdi而是rdx,所以这里需要先找到一个gadget将参数转移到rdx
*mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20];*
接下来使用setcontext控制参数构造rop调用orw读取flag。
对于setcontext及orw heap更多的了解可以参考
exp
1 | #coding:utf-8 |
easyheap
程序的漏洞在add函数中
先输入一个非法size,这时会赋值给v2,然后再输入合法size时,并没有更新v2,因此存在一个任意地址写入一个0字节的漏洞;接下来就是堆风水的构造
1、利用任意地址写0将topchunk size改小
2、利用任意地址写0修改tcache fd指向fastbin附近 实现overlop
3、申请一个特定大小的堆块,触发malloc_consolidate,并且切割之后放入unsorted bin中,这样泄漏出libc,并且获得另一块500的堆块,为double free准备
4、利用任意地址写0字节修改tcache fd
5、double free
exp
1 | #coding:utf-8 |