一:unlink的原理
要实现unlink,一:先修改堆块的使用标志位,把它从使用状态变为free状态;二:伪造fd指针和bk指针。
一:unlink的原理:
源码剖析:
unlink函数详细剖析:
二:unlink的绕过和利用
伪造的时候就是先把合并后的大堆块P的fd指针赋值0x602268,bk指针赋值0x602270。绕过的时候试FD的bk指向大堆块P,BK的fd指针也指向大堆块P,最后再进行一次FD的bk指针与BK的fd指针赋值,即可完成向chunk里写入chunk-0x18,从而实现任意地址写。
题目实践:
一:Uunlink
main函数:
menu函数:
add函数:
delete函数:
edit函数:
read函数:
offbyone,借此实现unlink的利用。由于这道题未开启pie保护,可以直接进行unlink。
先把函数定义好:
开始申请堆块并对其edit:
gdb调试看申请的四个堆块的状态:此时未编辑0号堆块
编辑后的0号堆块:
可以看到exp已经成功往0号堆块里写入内容,先写入了堆块的size:0x31,又把fd与bk指针写入,然后下一个堆块从0x16a7040开始,先伪造一个prev size 0x30,也就是上一个堆块的大小0x31,(前一个堆块大小是0x31,为什么伪造是0x30,因为1是标志位,前边文章有讲)。然后再写入0x100,为何要写入0x100呢, 因为这个堆块是申请的第二个f0大小的堆块,原始是0x101,标志位是1,也就意味着前一个堆块不是free状态,我们写入0x100就是篡改其标志位,这也就对应了为啥此时0号堆块是free状态了。
chunk里的的0号堆块(p)地址为:0x602300,可以查看堆块的管理
因为p指的堆块是0x602300中的0号堆块0x16a7010,gdb里看出,确实是这样的,刚好指向当前的这个堆块。查看堆块的管理:
如果此时我们free掉0x100大小的堆块,也就是1号堆块,那么会向前和并,也就是0号堆块与1号堆块合并,大小相加,最终效果就是往chunk0x602300里写入0x6022e8。如下图:
那么我们再次edit chunk里的0号块的时候就是edit0x6022e8
修改的时候可以直接把堆地址给改掉。把这个堆改为free holk的地址,再次edit2号堆的时候就可以任意地址写。
看下效果:
0号与1号堆块都写入了atoi got表,2号堆块写入free got表。那我们再次edit2号堆块的时候就会往里面写入内容,此题写的是puts的got表,再次free 0 号堆块的时候就是puts其真实地址。
泄露完地址后,可以再次edit 2 或1号堆块,写入system
先演示编辑2号堆块:
然后再编辑未利用过的3号堆块写入bin sh,在free掉,就可以getshell了
或者编辑1号堆块aoti
直接发送aoti一个binsh,也能get shell。
二:Stkof
与上题一个道理:
main函数:
malloc函数:
show函数:
free函数:
edit函数:
1:先定义函数:
2:获取常量,申请堆块:
再写入FD,BK
看下申请的四个堆块:
edit 2号堆块:
。由于没有开启pie,可以查看堆块的管理:
如果我们free掉3号堆块,那么此时2号堆块就会与3号堆块合并。
此时也往chunk里写入了其减0x18的值。
再往里面写got表,写完之后freegot改成put泄露地址。之后free掉任意一个got表,就能泄露出真实地址。之后再把free got改为system或者改aoti got为system,再搞一个binsh,就可以get shell。
Comments | NOTHING