首页
社区
课程
招聘
[原创]readme-revenge details
发表于: 2018-1-1 00:11 6646

[原创]readme-revenge details

2018-1-1 00:11
6646

看了这篇帖子 https://bbs.pediy.com/thread-223659.htm

前人之述备矣,然在下仍觉细节尚缺,故有此文。

看了题目名字就知道这是32c3那道readme翻版。

32c3那道题是一个栈溢出,通过stack_chk_fail去调用fortify_fail。

当时的利用方法是控制栈上的参数,也就是argv和环境变量。特别注意要控制LIBC_FATAL_STDERR_=1让fortify_fail能够把输出作为stderr给我们。否则fortify_fail下层接的是libc_message,而libc_message调用的是getenv

图片描述

getenv就是从environ指针那里去找环境变量指针数组。

getenv如果发现这环境变量没设置,libc_message会syscall调用open('/dev/tty'),输出你是看不到的。

图片描述

而34c3这道题的想法应该是源自于0ctf 2017里面的easiest printf(个人猜测)。

当时在0ctf结束后的irc里面,rpisec的人说到了一种非预期解法,就是改printf相关的两个函数指针,用自定义扩展%k调用shell。连dragon sector的人都很吃惊。

这种精巧的利用来源于printf的一个功能:https://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html#Customizing-Printf

我不知道原帖作者是否仔细看了GNU的文档或者printf的源代码

这里实际有两次RIP控制的机会,对应与printf的逻辑:首先是printf_arginfo_table,调用函数指针完成自定义spec的参数数目和类型的指定,后来才是对应的printf_function_table做真正的输出。

这里还有一点是,看完printf的代码你会知道,检查自定义spec是优先于printf自带的spec的。

于是ESPR他们应该是造了readme-revenge来结合上述两道题。

由于这道题是静态连接,又有bss段上的溢出,于是可以控制printf相关的函数指针和libc_argv。那么你就可以去构造%s对应的函数指针去控制RIP。

但是需要注意到environ指针是你覆盖不到的,他的位置在输入的上面。

所以说这种原帖作者所说的利用是存在问题的,你控制不了envivon啊?我不知道原帖作者是忘了、不知道还是故意没提(我希望是前两者)。在下第一时间就是因为这一点所以觉得这种思路不可用,去漫天找其他gadget。

实际上,217的同学也表示队友找了5个小时RCE的gadget找不到。

04:46 < david942j> _2can: yap.. it took my teammate 5hrs to try to do RCE (but fails as well)

<del> 是的,想要做这道题,需要撞大运,撞一个主办方帮你设置了环境变量LIBC_FATAL_STDERR_=1。 </del>

更新:2018年1月16日 20:41:28

发现并不是如此。似乎xinetd有一些奇怪的行为,LIBC_FATAL_STDERR并不需要设置,readme那题我自己用docker+xinetd起了之后发现不设置这个环境变量也有flag回来。

于是strace上去看了一波,发现如下操作

还是回到__libc_message这个函数:

即是说在docker xinetd的环境下,open('/dev/tty')会失败?

对比一下ncat的结果,

open成功,write也就自然喷给了/dev/tty。

于是自己也实际跑了一次xinetd,发现仍然open失败。

在网络上搜了一会儿,找不到xinetd和/dev/tty相关的资料。希望有了解的朋友可以分享告诉我,不胜感激。

目前的猜测是:xinetd有一些奇怪的操作,导致open失败,然后还是会走stderr喷flag出来。所以之前32c3那道题,设置环境变量是多余的。但是ncat是需要同时设置环境变量和2>&1的。

更新:2018年1月19日 23:02:11
今天抽空看了下xinetd的源代码,通过/dev/tty很快定位到了util.c

然后再在init.c中找到了这个函数的调用。

搜索了一番后,网络上的说法是这是一种做daemon的常规套路。

此贴至此终结 (应该没后续了吧?)

后续:实际上还不对,早上起来想起我们平时都是dontfork的,不应该走daemon,再研究了一下,发现是docker本身的问题。

https://github.com/moby/moby/issues/14

看起来不-it就不会分配tty。

发现删除线不好使了,用引用代替吧。

一个队友去撞了,于是成功get flag……真的是……哎。

如果你想要复现这个题目,要注意服务端把stderr导给stdout,并且把环境变量设好。

最后感谢原帖作者的分享。在下写这篇文章不是想批判原帖作者,只是认为有必要做一点细节的补充。因为个人认为,这些质量上乘的题目,好就好在引导我们去深入更加底层的程序运作和代码实现的细节。

希望能在pwn板块上看到更多的,经过自己辛勤探索、苦读代码、精心分析所得的干货。


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

收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 763
活跃值: (323)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
2
很强
2018-1-2 09:44
0
游客
登录 | 注册 方可回帖
返回
//