首页
社区
课程
招聘
[原创]hctf 2018 部分pwn writeup
发表于: 2018-12-19 11:34 13165

[原创]hctf 2018 部分pwn writeup

2018-12-19 11:34
13165

这次比赛因为有事所以比赛期间做不了pwn题,现在只能事后看着大佬们的wp把题目再学习一波。

漏洞很明显,任意地址写五字节。

需要解决的问题是如何利用已有的五字节get shell。
首先checksec检查保护:

RELRO是full,所以不能写got,然后在看到在最后返回的时候是直接掉用exit函数的,因此应该是通过exit函数里面掉用的函数指针来劫持控制流。

首先是信息泄露,得到libc地址,这一点很明显。
大佬们的wp关于劫持函数流有两种思路,一种是利用stdout的函数表,一种是_dl_fini函数中的函数指针,下面对于这两种解法进行描述。

因为glibc是2.23的,没有vtable的检查,因此修改函数表不会引起程序的错误。

查看exit函数的源码,exit中存在一条函数调用链,exit->__run_exit_handlers->_IO_cleanup->_IO_flush_all_lockp。看到最后这个_IO_flush_all_lockp就感觉应该可以利用这一点拿shell。这个函数里关键的源码是:

从源码中可以看到,如果可以控制stdinstdout或者stderr中实现fp->_mode <= 0以及fp->_IO_write_ptr > fp->_IO_write_base同时修改vtable里面的_IO_OVERFLOW为one gadget,那么就可以顺利的劫持控制流。
经过测试,五字节的修改思路为:

exp如下:

还是查看exit函数的源码,一条调用链是exit->_dl_fini,查看_dl_fini源码:

可以看到该函数调用了__rtld_lock_lock_recursive函数,再看这个函数的定义:

查看宏GL的定义:

_rtld_global是一个结构体,所以__rtld_lock_lock_recursive函数实际上是结构体中的一个函数指针,在gdb实际调试出现的指令为:

所以可以修改_rtld_global结构体的__rtld_lock_lock_recursive指针,将其修改为one gadget即可。
事实上,好像只要修改三个字节就可以实现了。

exp如下:

漏洞也很明显,格式化字符串漏洞,格式化字符串在bss段上,同时使用的是printf_chk函数。

格式化字符串的buff后面可以覆盖stdout,因此这题最后的解仍然是使用stdout来实现任意写任意读。由于是libc2.27,虚表存在检查,且在函数中也会将修改后的虚表改回去,因此无法使用函数表来做文章,但是仍然可以用stdout结构体里的数据实现任意写与任意读。
checksec查看程序开启的保护机制:

程序看起了PIE以及fullRELRO,因此无法修改got表劫持控制流。
首先贴出_IO_FILE结构体的定义,后面用的到:

里面前面的几个指针比较关键。

要实现完整的利用,首先是要实现地址泄露,可以通过stdout的任意读来实现地址的泄露。在程序中,我们已知的是程序的基址,因为一开始就打印出来了,可以利用bss段来伪造stdout结构体来实现任意读,相关涉及到的源代码如下:

以及

因此需要控制stdout结构体满足以下条件实现任意泄露:

_IO_read_end等于_IO_write_base以绕过多余的代码。
满足这三个条件,可实现任意读。当然不包含结构体里的_flags字段的伪造,该字段都从原来的结构体里面复制过来,所以就没去分析该如何构造了。

任意写功能的实现在于IO缓冲区没有满时,会先将要输出的数据复制到缓冲区中,可通过这一点来实现任意地址写的功能。相关源代码如下:

可以看到当_IO_write_end 大于_IO_write_ptr时,memcpy就会调用,因此任意写,只需要将_IO_write_ptr指向需要写的地址,_IO_write_end指向结束位置即可。
有了任意读与任意写之后,具体实现就是使用任意读泄露libc地址,然后用任意写将one gadget写到malloc_hook中,然后利用%n报错或者是较大的字符打印来触发malloc函数。

最终的exp如下:

存在一个off-by-null的漏洞,在函数sub_EE0中,会超过一字节并置0。

感谢bscause大佬的off-by-null的利用思路:

根据官方的wp,这题的主要考点在于malloc的时候只能申请大小小于等于0x38的块,只能申请fastbin,无法构造overlap chunk,所以出题人设置了scanf函数,使得可以通过scanf来触发malloc申请比较大的堆块,从而触发malloc consolidate,使得构造重叠块成为可能。

接着就按上面的思路构造了重叠块,后面利用fastbin里的数据,将top chunk覆盖成了malloc hook上面一点的地址,最后申请出来,覆盖为one gadget,得到shell。

exp如下:


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 6
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//