首页
社区
课程
招聘
[原创]2018bctf three
发表于: 2018-11-29 21:57 11569

[原创]2018bctf three

2018-11-29 21:57
11569

这道题证明了,逻辑简单的题目利用很困难(逻辑复杂的题逆向又很困难ORZ

程序的逻辑很简单,三个功能:alloc,edit和delete。没有输出。本题控制了最多能申请三个块。

alloc函数,申请一个0x40大小的块,并输入内容。

edit函数,修改块中的内容。

delete函数,存在一点问题,如果没有输入'y',就不对notes[i]置零,存在UAF/double free漏洞。

delete函数中的UAF、double free漏洞。另外,给的libc版本是2.27,也就是bins中使用了tcache。虽然有UAF但是没有输出,所以泄露地址变得困难。

释放一个块同时到unsortedbin和tcache中,释放到unsorted bin中的目的是获取libc相关的地址,释放到tcache则是为了利用类似于fastbin attack来修改FD指针。至于如何得到一个unsortedbin,稍稍有些复杂,思路就是在堆上伪造一个块,并能够操作size字段,使之size为0x91,然后释放7次该块,填满0x90大小的tcache。然后修改该块的大小为0x51,释放到tcache 0x50中,再修改块大小为0x91,释放时就能放入到unsorted bin中。这样,这个block既在unsortedbin里又在tcache里。

由于main_arena+88是libc中的地址,通过修改最后两字节能够修改tcache中FD的指向,但只有最后1.5个字节是固定的,剩下的0.5个字节就需要碰运气了。

新学到的一个思路:如果能够修改libc中stdout的_IO_write_base的值,由于puts会调用_IO_FILE_plus->vtable中的函数,从_IO_write_base中读数据。因此修改FD指向stdout,通过类似于fastbin attack的操作,将stdout这块交由用户输入,从而修改_IO_write_base

这里要补充一些关于puts函数的知识。在调用puts函数时,通过vtable调用了_IO_new_file_xsputn函数:

函数先调用_IO_OVERFLOW用于flush buffer,动态调试时可以看见对应的函数为_IO_new_file_overflow。正常情况下,IO_FILE中的_IO_read_XXX_IO_write_XXX_IO_buf_XXX指针的值比较相近,除了_IO_buf_end剩下的指针值都相同。(这个是我观察的,如果不对欢迎指正!)所以在下面的函数中,调用_IO_do_write读取从_IO_write_base_IO_write_ptr的内容并没有输出,因为二者的值是相同的。

接着会调用new_do_write函数。block_size = f->_IO_buf_end - f->_IO_buf_base=1,则do_write = to_do= n。

在new_do_write中调用_IO_SYSWRITE,向fp中输出data(上面的s)中的to_do(上面的do_write)个字符。

总结一下,也就是正常使用时,_IO_write_ptr_IO_write_base的值是相等的,调用_IO_OVERFLOW也不会输出内容,接着执行_IO_SYSWRITE输出data,也就是puts的参数。

但是如果我们能够修改_IO_write_base中的值,使它指向想要泄露的地址,那么在_IO_OVERFLOW中就能输出内容。

_IO_do_write也是通过new_do_write实现的。为了通过该方法进行泄露,对一些值进行设置,绕过new_do_write里一些不需要的流程。

参考了vigneshsrao 的思路,观察_IO_new_file_overflownew_do_write

绕过_IO_new_file_overflow中的 if (f->_flags & _IO_NO_WRITES)

防止在执行 _IO_do_write之前返回,其中_IO_NO_WRITES为0x8

绕过_IO_new_file_overflow中的if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0 || f->_IO_write_base == NULL)

防止对我们设置好的指针进行重新赋值,使(f->_flags & _IO_CURRENTLY_PUTTING)==1,_IO_CURRENTLY_PUTTING为0x800

绕过new_do_write 中的 else if (fp->_IO_read_end != fp->_IO_write_base)

防止在执行_IO_SYSWRITE之前return。vigneshsrao中给出的方法是,干脆不走这个else if,直接走上面的if (fp->_flags & _IO_IS_APPENDING),其中_IO_IS_APPENDING=0x1000。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2019-1-28 16:28 被oguri编辑 ,原因: 发现错误
上传的附件:
收藏
免费 4
支持
分享
最新回复 (3)
雪    币: 26245
活跃值: (63297)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
2
厉害
2018-11-30 08:58
0
雪    币: 763
活跃值: (323)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
3
厉害
2018-11-30 21:27
0
雪    币: 543
活跃值: (370)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
4
厉害
2019-3-16 22:10
0
游客
登录 | 注册 方可回帖
返回
//