https://wiki.x10sec.org/pwn/heap/use_after_free/
一个很直接的想法是修改note的put字段为magic函数的地址,从而实现在执行print note 的时候执行magic函数。 那么该怎么执行呢?
我们可以简单来看一下每一个note生成的具体流程
程序申请8字节内存用来存放note中的put以及content指针。
程序根据输入的size来申请指定大小的内存,然后用来存储content。
+-----------------+ | put | +-----------------+ | content | size +-----------------+------------------->+----------------+ | real | | content | | | +----------------+
那么,根据我们之前在堆的实现中所学到的,显然note是一个fastbin chunk(大小为16字节)。我们的目的是希望一个note的put字段为magic的函数地址,那么我们必须想办法让某个note的put指针被覆盖为magic地址。由于程序中只有唯一的地方对put进行赋值。所以我们必须利用写real content的时候来进行覆盖。具体采用的思路如下
- 申请note0,real content size为16(大小与note大小所在的bin不一样即可)
- 申请note1,real content size为16(大小与note大小所在的bin不一样即可)
- 释放note0
- 释放note1
- 此时,大小为16的fast bin chunk中链表为note1->note0
- 申请note2,并且设置real content的大小为8,那么根据堆的分配规则
- note2其实会分配note1对应的内存块。
- real content 对应的chunk其实是note0。
- 如果我们这时候向note3的chunk部分写入magic的地址,那么由于我们没有note1为NULL。当我们再次尝试输出note1的时候,程序就会调用magic函数。
程序
free了但没有设置为0,所以存在uaf
在这里,notelist[i][0]
存放的是puts函数的地址,notelist[i][1]
存放的就是指向content的地址
先申请两个0x10的空间,内容为aaaa
add(0x10,"aaaa")
add(0x10,"aaaa")
最下面的是top chunk,我们申请了的两块0x10空间,还有两块是因为下图,并且,堆块地址向上生长
所以,最先的0x826300
和0x826328
应该就是最先分配的notelist[i],里面存放着指向print_note_content的地址,0x826310
和0x826338
就是我们自己申请的堆了
然后在我们delete了这两个堆块之后,(由于重新运行程序所以地址改变
delete(0)
delete(1)
0x902e010
(我们申请的)和0x902e00
(存放puts地址的)先进入fastbins单链表
然后此时我们再add(8,p32(shell))
0x87d0028
先出来,储存print地址,然后再0x87d0000
,储存magic地址
最后,我们再print heap0时,就跳转到了magic地址上面去了
「真诚赞赏,手留余香」
真诚赞赏,手留余香
使用微信扫描二维码完成支付