hitb2018_gundam
1.常规checksec,保护全开。IDA打开找漏洞,在删除函数sub_D32()中存在Double free和UAF漏洞:
通过逆向分析,结构体重整化:
1 | #注释头 |
之后如下:
(1)Double free:可以看到在删除函数中,程序通过factory[idx]和count来判断gundam是否存在,并且只是free掉了factory[idx]->name这个chunk,并且将flag置空,但是并没有将factory[idx]这个指针置空。而且这是在Tcache机制下,没有对Double free的检查,那么就代表如果其实我们是可以连续多次free掉factory[idx]->name这个chunk的。
(2)UAF:另外factory[idx]->name这个指针也没有置空,可以通过factory[idx]再次利用,形成UAF漏洞。
2.思考利用方式:由于libc版本是2.26,从unsortedbins中申请回的chunk如果不被程序更改内容,其fd和bk仍然保存,可以泄露地址。由于build的时候,没有将name这个chunk的内容初始化为0,所以该chunk如果进入unsortedbin中之后,fd被赋值为main_arena+88,那么申请回来之后,name中的bk就带有main_arena+88的地址,可以通过visit打印出来,从而计算得到,泄露libc基地址。
(1)那么先填满tcache之后,再加个chunk,使其进入unsorted bin中,然后申请回来就可以得到libc地址了。
(2)得到libc地址后,由于libc版本是2.26,仍然存在tcache poisoning漏洞,就可以通过Double free漏洞进行类似fastbins attack攻击。
1 | #注释头 |
①先申请三个chunk,chunk0,chunk1,chunk2,chunk1存放binsh字符串,chunk2用来防止被topchunk吞并。之后释放chunk0两次,那么tcache中的chunk0的fd指针就会指向自己,形成:chunk0->chunk0。
②之后再申请一个chunk,对应索引为0,申请回第一个chunk0,修改name内容__free_hook_addr,而name内容的前八个字节就是chunk0的fd,即tcachebin中就会由之前的chunk0->chunk0变为chunk0->__free_hook_addr
③再连续申请两个chunk,对应索引为3,4,chunk4的头地址就会是__free_hook_addr-0x10,那么修改chunk4的name中的前八个字节就相当于修改_free_hook,这里使其变为system的真实地址,再free(chunk_binsh)即可getshell。
3.编写exp:
(1)前置增删改查函数:
1 | #注释头 |
(2)泄露地址:
1 | #注释头 |
(3)清空count,方便计算索引:
1 | #注释头 |
(4)利用tcache poisoning和double free漏洞,getshell:
1 | #注释头 |
▲这个泄露地址的漏洞在没有tcache机制的libc版本中都可以用,但是tcache poisoning只有libc2.26才可以用
参考资料:
ctf-all-in-one