首发看雪:[翻译]launchd中消息队列逻辑问题允许任意的mach message控制
来自yaren的寄语
我通常凌晨三点就起床,然后开始查收邮件,晨跑5英里达到我的办公室,开始我一天的工作。人生没有捷径,我的座右铭是do more、know more、ne more。
上文对于陆奇的介绍,我们发现天才不是来自germ cell而是来自勤奋,只要努力我们足够努力,我们一定能脱贫致富、成为陆奇一样的人,突破职场天花板,致敬埃洛普成为微软的高级木马。
正文
2016年 八月二十日 星期六
Launchd升级为10.10版本。旧版本的(10.10之前)launchd是开源的,但是新的版本是封闭源、被剥离出来的单独版本,所以甚至没有function名字
然而…
新版本的launchd与xpc的事物紧密集成,这样就给了我们一个良好的着力点去了解发生了什么。此PoC中的所有function地址均基于OS X 10.11.6装载的launchd。
10002F3A1是引导端口上的处理程序 - 当接收到消息时,它从libxpc中调用xpc_pipe_try_receive,用来检查接收的mach message的msgh_id:如果它是0x10000000,那么这是一个xpc message,它会尝试反序列化一个xpc对象;如果它是一个旧版本的MIG message,则xpc_pipe_try_receive将调用其第4个参数通过xpc_pipe_handle_mig来处理MIG消息。 10002ED33是launchd进程的旧版本的mig处理程序,它通过在100018ADE中注册的几个旧版本MIG子系统来进行检验(请注意,对10002E3EE的调用是指添加了旧版本的mig子系统到它们的数组。)(100018ADE还注册了launchd 的XPC子系统(ipc系列)的处理程序)。
这是很好的,但有趣的是,实际上存在两个调用路径,一个是到xpc_demuxer(10002EE87)/ mig处理程序(10002ED33),而另一个是10002EC25。除了不存在对xpc_pipe_try_receive的调用,此function的逻辑与10002F3A1几乎相同。稍稍回顾一下可以发现,当邮件由launchd接收时,此function不负责直接解析信息,而是用于“重新解析”“搁置”信息。
在某些情况下,当launchd无法立即服务请求时,它会将此请求排入调度队列稍后再试,并且该请求最终将在此处结束。
此function(10002EC25)只直接接受xpc dictionary,而且它会通过检查来发现该dictionary是否具有“mig-request” key/value pair。如果有,则它会在xpc_dictionary之外读取一个xpc_data_t并将其转换成一个mach_msg_header_t,并将其通过xpc_pipe_handle_mig来传递到10002ED33(旧版本MIG处理程序)。
我找不到任何可以设置一个“mig-request”值的地方,所以我猜这是一个调试功能,又或者是因为意外留下?因为xpc是一个无模式的ipc机制,我们实际上可以只设置一个具有完全受控制的xpc_data_t有效负载的“mig-request”键(其值将被视为被launchd接收的有效的mach message)。唯一的先决条件是,我们要找出如何获取一个我们发送到launchd的被搁置的XPC信息的方法——而似乎子系统 3的例程804(xpc_look_up_endpoint)有时将被搁置,这意味着如果我们修改这些请求中的一个,我们可以通过旧版本的MIG处理管道发送一个完全受控制的伪造的mach message。
这是一个惊人的野生的exploitation ——当伪造的mach message能够传递到mach_msg_destroy来摧毁它的权限和内存时,这个PoC会发送一个带有OOL数据的信息,而这会导致读取一个在0x414141410000的内核端口成为一个崩溃的尝试(这个指针稍后也会被传递到vm_deallocate)。但是一个像这样的bug可以使你做更多的事,例如扰乱launchd的端口的引用计数(因为我们可以在我们的信息中指定任意端口号,使其被看作是launchd的端口命名空间中的有效端口)。我们还可以取消映射任意页面,并将无效的事物传递给传统MIG处理程序。
就影响方面而言,launchd是系统上权限最大的进程,你可以从任何进程涉及到它:-)
这个PoC会hook目标xpc请求的发送,并注入一个“mig-request”xpc_data_t —— 如果它不工作,尝试关闭所有打开的浏览器,或使用干净的启动重新开始。
译者:赤(看雪ID:呜呼哀哉)
校对:yaren