ciscn_2019_s_1
考察了off by null
保护策略:
漏洞所在:
在edit函数中存在一个off by null漏洞。
程序分析:
在add函数中,对malloc申请的内存大小做了限制,需要小于0x100并且大于0x7f的堆块才行,然后索引我们可以使用0到31(32没法用,因为这里的len[32]和heap[0]是一个内存单元,如果用了32,那么len[32]就有数据了,到了申请索引为0号堆块的时候,heap[0]有内容,就会进入if程序退出)
edit函数中存在一个off by null,并且有个key1的限制,导致了edit函数只能执行两次。
show函数表面感觉能使用,但是key2在bss段,默认值为0,所以show函数我们无法正常使用(如下图)
delete函数可以无限次使用,但是不存在漏洞。
大致思路:
程序的libc版本为2.29,我们常规打一个off by null做一个堆块重叠,但是由于我们无法直接释放掉堆块让其进入unsorted bin(而off by null做的堆块合并需要让堆块位于unsorted bin中),所以在这之前我们需要tcachebin中填满堆块(不必担心索引的问题,我们有32个索引可以用,同时delete函数还可以清空索引中内容)
然后打一个off by null,此时的堆块布局应该如下:
这个merge chunk的prev size被修改为了0x200 (merged chunk之所以可以进入unsorted bin中是因为在这之前tcahce bin中已经装了七个chunk了)
然后我们释放掉merge chunk,触发合并,打一个堆块重叠,然后做一个double free出来。接着打tcache poisoning,我们去将堆块的fd指针去修改为0x6021d0这个地址,因为这个地址既属于我们的heap指针数组,同时加上0xf0后还可以去修改key1和key2。
(其实这道题看见key这个名字同时联想下key1和key2的作用,很容易想到去篡改这两个值,不然edit用不了,我们之后的各种手法都会失效,而修改key2还可以使用show函数),但如果仅仅是修改key值的话,就导致了我们之后还要再打一遍off by null,但是0xf0这个链已经成-1坏掉了,应该就没法利用了(我没有仔细考虑这种方法,但是我试了下,这0xf0链坏掉之后,off by null就没法再打一次了,如果最开始做三个相同的堆块地址,保证0xf0的这个链不会在第一次打个double free就坏掉,应该也可以利用(但是我没有试,这只是我的一个思路))
但是我当时看了下bss段存储的数据,发现可以同时控制key1、key2和heap指针数组里的内容,就是申请到0x6021d0这个地址,这个地址位于heap[31],我们先申请出来修改key1和key2的值,然后执行show函数拿到libc地址,再去往0x6021d0这个地址上写入free_hook的地址,最后编辑heap[31]这个块,写入system的地址即可。
EXP:
from tools import * |