前几天把House of orange
重新学习了一下,比照着glibc
malloc
的源码好好分析了一下,希望做到真正做到知其然亦知其所以然,其中所做的笔记如下,可能描述上有点乱,大家将就着看一下吧。同时,我也发在了我个人博客上面 (http://blog.leanote.com/simp1e), 如果有错误的地方,请各位大牛多多指正。
大名鼎鼎的house_of_orange
程序逻辑还比较清晰的,一共可以build
四次,然后每次build
的话就是3次堆分配,两次malloc
,一次calloc
,其中一次malloc
是固定分配0x10
字节作为控制堆块,里面存放着name
和color
的信息,另外按输入分配name
的大小。
在upgrade
函数中,修改name
时候不顾实际chunk
的堆大小是多少,直接进行编辑,最大可编辑0x1000
大小,因而存在溢出。
这里的利用思路是4ngelboy
给出,下面就直接分析这样利用的原因。
因为程序中有堆的越界写,可以修改top_chunk
的大小。在malloc源码里面如果申请的堆块大小超过了top_chunk
的大小,将调用sysmalloc
来进行分配。
sysmalloc
里面针对这种情况有两种处理,一种是直接mmap
出来一块内存,另一种是扩展top_chunk
就是如果申请大小>=mp_.mmap_threshold
,就会mmap
。我们质只要申请不要过大,一般不会触发这个,这个mmap_threshold
的值为128*1024
。
不过下面还有两个assert
需要检查,如下
第一个assert
就是要求修改后的top_chunk_size
必须满足
top_chunk_size
小于申请分配的内存即可
满足以上四个条件之后,继续往下执行最后把原先的那个old_top
给释放掉了,如下
显然,这样的free
操作的话,我们就可以得到一个unsort_bin
,然后之后再次分配时候如果是符合unsort_bin
大小的话,就会从unsort_bin
里面切出来。
这样的话我们再次申请一个堆块分配到这块区域中就能泄露libc
地址了,但是这里又有一个trick
,如果我们分配的大小是large_chunk
的话。malloc
源码中还把old_top
的堆地址放到了堆里面(没有细究原因,但是好像是large bin没有区分大小,需要有个字段来保存大小的原因吧),源码如下
所以如果再次分配时候如果分配大小为largebin
(也就是大于512字节)的chunk
的话,就是可以既泄露libc
又可以泄露heap
。如下
而如果分配大小不到512字节时候是无法泄露堆地址的。
我们知道有rop
即retn Oriented Programming
,那么其实File Stream Oriented Programming
是一个道理的。也是一种劫持程序流程的方法,只不过方式是通过攻击File Stream
来实现罢了。
我们先要了解malloc
对错误信息的处理过程,malloc_printerr
是malloc
中用来打印错误的函数。
malloc_printerr
其实是调用__libc_message
函数之后调用abort
函数,abort
函数其中调用了_IO_flush_all_lockp
,这里面用到IO_FILE_ALL
里面的结构,采用的是虚表调用的方式。
其中使用到了IO_FILE
对象中的虚表,如果我们能够修改IO_FILE
的内容那么就可以一定程度上劫持流程。
IO_FILE_ALL
是一个指向IO_FILE_plus
的结构指针,结构如下图所示,具体结构不需要太了解清晰,大概懂一些也就行。
那么怎么劫持呢,这里又需要用到unsortbin attack
的知识。
unsortbin attack
是怎么一回事呢,其实就是在malloc
的过程中,unsortbin
会从链表上卸下来(只要分配的大小不是fastchunk
大小)
如上代码所示,就是会把bk+0x10
的地方写入本unsort_bin的地址,
我们通过内存断点来观察一下是如何进行的。
断点触发之后,发现io_file_all
被修改成了指向top_chunk
的指针时间地址位于main_arena
。
但是我们是无法控制main_arena
的内容的,至少全部控制是不行的,那么怎么处理呢?
这里还是要牵扯到io_file
的使用,IO_FILE
结构中有一个字段是chian
字段,它位于0x60偏移处,他指向的是下一个IO_FILE
结构体,我们如果可以控制这个字段,就再次指定io_file
的位置,它相当于是一个链表的结构
这样的话又联系到smallchunk
的问题,在拆卸unsort_bin时候对属于small_bin
的chunk进行了记录操作。
这个时候IO_FILE_all
指向的正是main_arena
的bins里面unsortbin
的位置,那么偏移0x60
处正好是,smallchunk
的index为6的地方,也就是满足大小为16*6
的chunk,所以upgrade
时候需要把unsortbin
设置为0x60
大小。
因为第一个分配在main_arena
的IO_FILE_plus
结构的fp->mode
等值不符合要求,就会通过chains
跳转到就下一个IO_FILE_plus
就是我们之前设置的unsortbin
,然后需要满足一下条件
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!