首先,检查一下程序的保护机制

然后,我们用IDA分析一下,在edit功能里,使用strlen来更新size,因此下一次修改,可以溢出到下一个chunk的size处。

程序中没有调用free函数,并且不能完全控制chunk的size的8字节,无法利用house of force,因此,想到了house of orange的方法。

利用edit和溢出,修改将TOP chunk的size改小,然后申请一个比size大的堆,old_topchunk就会被放入unsorted bin。这个top chunk的size不能随意修改,得大于最小值,并且要求(top_chunk_addr + size) & 0xFFF = 0,即大小是页对齐的。
首先利用这个方法,得到unsorted bin,泄露地址。
1 | add(0x15000,'a'*0x18) #0 |
第1个chunk,之所以add(0x15000,’a’0x18),是为了让old_topchunk的地址靠近将来新的top chunk,要形成overlap chunk,这里的方法是*[expand unsorted bin,即扩充unsorted bin]{.mark}**,而我们只能控制size的前3字节,为了能在3字节范围内将old_topchunk形成的unsorted bin尾部扩充到我们可控的区域内,我们的事先消耗掉old_topchunk里大部分空间。这样,我们将来在new_topchunk里切割的堆块就被包含在了unsorted bin里面。
1 | add(0x18,'e'*0x18) #4 |
现在,我们就通过2来控制整个unsorted bin,由于在libc-2.27上,传统的house of orange已经失效了,但是可以有其他方法来触发,比如exit。

但是这里,我使用的是另外一种方法,即控制unsorted bin的bk指针指向bss上的name

然后我们在name里伪造一个chunk,另该chunk的fd = bk = name,然后,通过malloc与伪造的chunksize一样的堆,unsorted bin遍历时,就可以直接将name取出返回给我们,这样,我们就可以控制name下面的堆指针,进而获得任意地址读写的能力。

1 | #coding:utf8 |