堆利用-Unlink

发布于 2023-04-07  617 次阅读


一: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。


穿过云层我试着努力向你奔跑