从这个标题就可以看出,存在溢出漏洞,堆溢出很有意思,大多是溢出控制元数据区域(chunk的信息区),之后再通过Overlapping来泄露地址啊之类的
这道题目看反汇编的话会发现,不存在UAF漏洞,意味着无法简单的进行double free,如果无法double free,想任意地址写从而控制程序流程就需要tcache poisoning,但是能进行tcache poisoning那不就是特别简单的题目吗,这题因为没有专门的edit函数和UAF所以这是不可能的,所以就需要找新的漏洞,发现在add函数中存在off by null漏洞,这个漏洞是在你写的任意数据后加一个’\0’,导致可以溢出一个null byte,所以叫做off by null
之后的思路很简单了:利用off by null实现overlapping,获得一个逃出来的指针,用这个指针实现libc地址泄露和double free控制程序流程
思路很简单但是操作比较麻烦,想要在free时进行到合并那个操作,需要满足以下条件
- 1,能顺利的通过tcache和fastbin的检测,这需要tcache填满以及超过fastbin大小
- 2,合并时需要合并的chunk有合法的fd和bk(因为需要进行到unlink函数)
- 3,合并时需要通过size=pre_size的检测,如何通过检测请看这篇文章Off by Null的前世今生-安全客 – 安全资讯平台 (anquanke.com)
这需要对堆进行布局,我最后的布局是(每一个都是0x100大小,最后一个是0x110(在topchunk分割,使得某一个unsorted bin走过分类的路线),A是allocated chunk,S是smallbin free chunk)
S(7) A(8) A(9) A*7(0-6) A(13) →高地址
由于smallbin,使8号的pre_size=7号的size使之能通过检测(3),之后先free(8),再add(8,0xf8,b’\x00’*0xf0+p64(0x200)更改9号的pre_size和pre_inuse,欺骗ptmalloc使它认为8号是一个free chunk,大小为0x200(7大小加8大小),最后通过free(9)使得9号chunk向前合并(合并时指针先前移0x200找到7号chunk,检测7号chunk的size和8号chunk的pre_size是否一致,并进行unlink,由于fd和bk也合法,使得合并成功)
这时我就得到了一个野指针(指向8号chunk),再将7,8,9chunk合并再切割出一个合适的值,使得8号指针指向下一个remainder(unsorted bin)fd或者bk指针,再通过show(8)成功泄露地址
之后我本来想用tcache的double free,但是我发现2.27版本竟然检测出了tcache的double free,最后问了ffly学姐才知道2.27版本的一个小版本是存在检测double free的,所以最后我用了fastbin的double free,因为有tcahce所以最后写的地址可以直接malloc出来,最后在__free_hook中写入system的地址,最后成功getshell
exp如下