0x0 程序保护和流程
保护:
流程:
main()
create()
delete()
free之后没有将指针置空,存在UAF。
edit()
没有对输入数据的大小作出限制,存在堆溢出。
0x1 利用过程
1.题目中的got表不可写,又没有输出函数,无法泄露地址,但是堆栈上可以执行代码,所以需要一个可执行的指针变量指向shellcode的地址,才能够执行shellcode。
2.可以使用Unsorted bin attack改写buf中指向chunk的地址为main_arena的地址,之后通过update将buf中的存储的数据改成malloc_hook的地址,之后向malloc_hook中写入shellcode的起始地址,之后再次执行malloc函数就可以完成getshell了。
3.因为要将修改malloc_hook中的数据,所以需要malloc_hook的地址。而malloc_hook的地址可以在libc中找到。
这时再看向malloc_trim函数
反汇编
源码
可以知道在main_arena-0x10就是malloc_hook的地址,而Unsorted bin在free之后的fd和bk都会指向main_arena附近的地址。并且当Unsorted bin取出的时候,会将bck->fd的位置写入Unsorted bin的链表头部的地址。
/* remove from unsorted list */
if (__glibc_unlikely (bck->fd != victim))
malloc_printerr ("malloc(): corrupted unsorted chunks 3");
unsorted_chunks (av)->bk = bck;
bck->fd = unsorted_chunks (av);
只要能够在Unsorted bin释放之后修改其bk字段,就能在下一次申请大小合适的堆块时,将*bk+0x10处的值改为Unsorted bin的链表头部的地址。又因为程序加载进内存是按页加载,页表大小为4096=212=24*24*24 (getconf PAGE_SIZE可以查看页表大小),所以低三位是不会改变的,因此只需要向*bk+0x10的位置写入’\x10’,就可以使得*bk+0x10指向malloc_hook了。
3.通过以上分析,最后只需要一个可以控制的指针即可完成整个过程,所以可以通过Unlink或者Fast bin Attack将buf中的值修改为&buf再配合程序给出的update函数就可以getshell了。
Fast bin Attack:
先介绍Fastbin中最关键的检测机制,_int_malloc 会对欲分配位置的 size 域进行验证,如果其 size 与当前 fast bin 链表应有 size 不符就会抛出异常。
if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0))
{
errstr = "malloc(): memory corruption (fast)";
errout:
malloc_printerr (check_action, errstr, chunk2mem (victim));
return NULL;
}
所以对于Fast bin的利用必须要注意size位的判断。所以在这种利用方式下需要找到一个固定的值,并且这个值的大小在需要在Fast bin中并且与索引对应的大小要一致。
要想将fast bin分配到bss段,需要一个比较固定的值,而一般libc的高位是0x7f其大小符合Fast bin,所以先利用Unsorted bin Attack给出一个高地址。
# Unsorted bin
create(0x100,'index0')
# Fastbin bin,size=0x70即可
create(0x60,'index1')
# 防止被top chunk合并
create(0x10,'index2')
delete(0)
payload=p64(0)+p64(0x601058)
update(0,payload)
create(0x100,'index3')