之前知道scanf输入过多时会触发malloc,这次进行系统地记录。
1.setbuf(stdin,0)
大部分程序都会有这样地初始化,这使得一开始heap中不会有为scanf预留的缓冲区。
但是预留的缓冲区终是有限的,例如输入0x400以上时,scanf就会触发malloc分配0x400以上的空间,用完后free。
现在,我们开始演示:
for i in range(8):add(i,0x300)
add(8,0x30)
for i in range(8):delete(i)
io.recvuntil(b">>")
io.sendline(b'1'*0x400)
gdb.attach(io)
pause()
这是代码,版本是libc 2.35,熟悉的应该可以看出delete完,应该有一个chunk在unsortedbin中,如果scanf触发了malloc,并且分配内存>0x400,那么unsortedbin中的chunk就会被赶回smallbin中,由于分配完会free掉,在heap中我们看不到踪迹,但由于是scanf缓冲,所以b'\x31'会保留下来,可以查看topchunk顶部内容验证。
这是程序运行后bin中的情况。
这是topchunk顶部的情况 ,可以看到缓冲区确实曾建立过,并且大小至少是0x400,可以用来触发malloc_consolidate。
2.没有setbuf
如果没有setbuf(stdin,0)会怎么样呢,继续用gdb调试。
可以看到,会先分配0x1000的空间当作缓冲区。
为了演示方便,我们可以这样:
让topchunk<0x1000,这样可以触发house of orange。
io.sendline(b'0'*0x700+b'1')
我们先这样,就不贴gdb图片了,因为和上面一样,显然,原来的0x1000可以应付。
继续:
io.sendline(b'0'*0x800+b'1')
这样,原来的0x1000也能应付。
那正好0x1000呢?
io.sendline(b'0'*0xfff+b'1')
这就触发house of orange了。
其实根据收集到的信息:
scanf分配内存是用realloc,大小不断x2的。因为数据是不断流入缓冲区的,malloc(0x400),realloc(0x800),realloc(0x1000),realloc(0x2000)这样的,如果你正好输入0x1000的数据,但是它 原本realloc(0x1000)的空间装满后,它并不知道还有没有数据,所以会继续realloc(0x2000),所以上述题目中输入0x1000个字节,原本的0x1000的chunk其实是可以装下的,但是它会realloc(0x2000),所以触发了house of orange。