全文详细地址:
最近,macOS 11.0/iOS 14.2/iOS 12.4.9修补了一个 *** 安全问题:因host_request_notification未查验port->ip_specialreply而造成 的遮盖ip_sync_inheritor_port的 *** 安全问题。这好像能够在碰到区块链查验不正确时重新启动系统软件,但想要知道,此外,它还能做些哪些。
如同Synacktiv所详解的那般,大家还可以根据BinDiff寻找CVE-2020-27932的修补程序流程。
依照Synacktiv详细介绍的方式 ,大家发觉此次修补的涵数是ffffff0076bb370:host_request_notification。
而且,调整后的涵数仅仅提升了一项查验。
在下面的BinDiff对话框中,表明了2个并列的代码块,而且,右侧有一行编码处在突显情况
原先的编码:
if (!ip_active(port) || port->ip_tempowner || ip_kotype(port) !=IKOT_NONE){
改动后的编码:
if (!ip_active(port) || port->ip_tempowner || port->ip_specialreply || ip_kotype(port) !=IKOT_NONE){
事实上,这一段编码在老版macOS/iOS系统软件上运作时并没什么难题,但在macOS 11.0/10.5.7版本号于11月升级至/iOS 14.2/iOS 12.4.9以后后,所述编码就会发生KERN_FAILURE不正确。
mach_port_t port=thread_get_special_reply_port();
kern_return_t err=host_request_notification(mach_host_self(), HOST_NOTIFY_CALENDAR_CHANGE, port);
这一涵数用以每每macOS/iOS系统软件上的日期或時间产生变化时获得相对的通告。
启用host_request_notification会将端口加上到将接受日期/時间变更通告的端口的双向链表中。
为了更好地便于从连接列表中删掉端口,列表内容还将储存在端口的ip_kobject字段名中。
ipc_kobject_set_atomically(port, (ipc_kobject_t)entry, IKOT_HOST_NOTIFY);
它会将ip_kotype(port)设定为IKOT_HOST_NOTIFY, 并将port->ip_kobject设定为内容。
这就是内核如何把一个Mach端口与一个内核目标关系起來的 *** 。别的意味着内核目标的Mach端口,如每日任务端口或计时器端口,也应用ip_kotype和ip_kobject来储存他们关系的内核目标。
当端口被消毁时,它会启用host_notify_port_destroy,再次载入列表内容,并将其从列表中消除连接。
if (ip_kotype(port)==IKOT_HOST_NOTIFY){
entry=(host_notify_t)port->ip_kobject;
那麼,这种独特回复端口(special reply port)究竟有哪些独到之处呢?他们能做什么别的端口做不到的事儿?
在内核源码中搜索ip_specialreply,大家只找到29个引入,在其中绝大多数都和QoS和turnstile相关。
在Mach RPC中,端口是单边的,因而,当您向另一个过程推送消息时,另外必须出示一个回复端口。那样的话,远程控制过程会将它的回应推送回特定的回复端口。
下边的表明,源自OSFMK/mach/message.h:
* The msgh_remote_port field specifies the destination of the message.
* It must specify a valid send or send-once right for a port.
*
* The msgh_local_port field specifies a "reply port". Normally,
* This field carries a send-once right that the receiver will use
* to reply to the message. It may carry the values MACH_PORT_NULL,
* MACH_PORT_DEAD, a send-once right, or a send right.
下边是Mach消息的工作中电路原理图:
Me ----------------------------------->[destination port]other process
{message, reference to reply por
[reply port]ip_specialreply ||
special_reply_port->ip_sync_link_state !=PORT_SYNC_LINK_ANY ||
special_reply_port->ip_sync_inheritor_port !=IPC_PORT_NULL){
drop_turnstile_ref=TRUE;
}else{
ip_reference(dest_port);
special_reply_port->ip_sync_inheritor_port=dest_port;
special_reply_port->ip_sync_link_state=PORT_SYNC_LINK_PORT;
}
因此:假如能连接独特端口,且都还没承继端口,就可以把回复端口连接到目地端口。
当独特回复端口必须升级时(比如,在目地端口接到消息后,或是当一个旧的进程独特端口被新的端口替代时),内核就会启用ipc_port_adjust_special_reply_port_locked,依据独特回复端口的当今情况来升级其连接目标。
假如端口沒有被连接,则不容易产生一切事儿:
if (special_reply_port->ip_sync_link_state==PORT_SYNC_LINK_ANY){
not_special:
if (get_turnstile){
turnstile_complete((uintptr_t)special_reply_port,
port_rcv_turnstile_address(special_reply_port), NULL, TURNSTILE_SYNC_IPC);
}
imq_unlock(&special_reply_port->ip_messages);
ip_unlock(special_reply_port);
if (get_turnstile) {
turnstile_cleanup();
}
return;
}
否则,根据状态和新的所需链接,在端口/knote/turnstile之间进行链接交换。
据我所知,这两个函数是唯一对ip_sync_inheritor_port执行写入操作的函数。此外, ipc_port_adjust_special_reply_port_locked是唯一一个写入另外两个字段(即ip_sync_inheritor_knote和ip_sync_inheritor_ts)的函数。
为什么对这些字段的写入操作非常重要呢?
ip_kobject、ip_sync_inheritor_port、ip_sync_inheritor_knote和ip_sync_inheritor_ts是在一个共用体(union)中声明的!
union {
ipc_kobject_t kobject;
ipc_importance_task_t imp_task;
ipc_port_t sync_inheritor_port;
struct knote *sync_inheritor_knote;
struct turnstile *sync_inheritor_ts;
} kdata;
然而,这些字段中的内容并不是集中存放的:ip_kotype和ip_sync_link_state并不是一起存储的。
这意味着可以通过使用host_request_notification的链表条目来覆盖ip_sync_inheritor_port!
并且,为了实现上述目的,我们有多种 *** 可以使用,但这里将采用一个最简单的 *** ,利用这个漏洞让内核崩溃。
首先,我们需要调用thread_get_special_reply_port。
这将为这个线程创建一个新的特殊回复端口。
Reply port
- ip_sync_link_state: PORT_SYNC_LINK_ANY
- {ip_kobject, ip_sync_inheritor_*}: null
- ip_kotype: IKOT_NONE
要改变ip_sync_link_state,我们需要调用ipc_port_link_special_reply_port函数。调用这个函数的最简单的 *** ,是尝试在特殊回复端口上接收消息,并将目标端口作为通知端口(如内核的单元测试test/kevent_qos.c所示)。
之后,mach_msg_rcv_link_special_reply_port将调用ipc_port_link_special_reply_port,从而将特殊回复端口与目的端口链接起来:
Reply port
- ip_sync_link_state: PORT_SYNC_LINK_PORT
- {ip_kobject, ip_sync_inheritor_*}: destination port
- ip_kotype: IKOT_NONE
当它等待接收消息时,我们在另一个线程中调用host_request_notification,从而在不改变ip_sync_link_state的情况下写入ip_kobject和ip_kotype:
Reply port
- ip_sync_link_state: PORT_SYNC_LINK_PORT
- {ip_kobject, ip_sync_inheritor_*}: host notify link entry (overwritten!!)
- ip_kotype: IKOT_HOST_NOTIFY
当接收超时时,内核会调用ipc_port_adjust_special_reply_port_locked来解除端口的链接。
当函数得到一个链接的列表条目而不是它所期望的端口时,这应该会引起崩溃。
当然,说了这么多,但都是理论上的。
值得庆幸的是,特殊回复端口是内核中为数不多的在tests/kevent_qos.c中有单元测试的部分之一,因此,这里只需为它添加一个host_request_notification 调用。
我目前要做的事情,就是在自编译的macOS 10.15.6内核上触发崩溃。
Receiving message! object=0xffffff80237e8d48
mach_msg_rcv_link_special_reply_port port=0xffffff80237e8d48 dest=f0b
mach_msg_rcv_link_special_reply_port got dest port=0xffffff8023e48618
ipc_port_link_special_reply_port: port=0xffffff80237e8d48 dest=0xffffff8023e48618 sync=no state=0 ip_sync_inheritor_port=0
Take a reference: 0xffffff80237e8d48 -> 0xffffff8023e48618
ipc_port_recv_update_inheritor special port=0xffffff80237e8d48 state=1
host_request_notification port 0xffffff80237e8d48 old 0xffffff8023e48618 entry 0xffffff801f206390
panic(cpu 0 caller 0xffffff800630fc8a): "Address not in expected zone for zone_require check (addr: 0xffffff801f206390, zone: ipc ports)"@/
Users/zhuowei/Documents/winprogress/macos11/crashtest/xnubuild/build-xnu/xnu-6153.141.1/osfmk/kern/zalloc.c:662
Backtrace (CPU 0), Frame : Return Address
0xffffff95997758a0 : 0xffffff8006273cee
0xffffff9599775900 : 0xffffff800627349f
0xffffff9599775940 : 0xffffff80064df248
0xffffff9599775990 : 0xffffff80064c7fbe
0xffffff9599775ad0 : 0xffffff80064e7540
0xffffff9599775af0 : 0xffffff8006272d78
0xffffff9599775c40 : 0xffffff8006273916
0xffffff9599775cc0 : 0xffffff8006e7266f
0xffffff9599775d30 : 0xffffff800630fc8a
0xffffff9599775d60 : 0xffffff800623d73d
0xffffff9599775d80 : 0xffffff80062393e3
0xffffff9599775db0 : 0xffffff800624224e
0xffffff9599775df0 : 0xffffff8006242acb
0xffffff9599775e50 : 0xffffff800625b403
0xffffff9599775ea0 : 0xffffff800625ae7b
0xffffff9599775f60 : 0xffffff800625b819
0xffffff9599775f80 : 0xffffff800623abfc
0xffffff9599775fa0 : 0xffffff80064bb72e
也就是说,在我的内核中,
debugger_collect_diagnostics (in kernel.debug.unstripped) (debug.c:1008)
handle_debugger_trap (in kernel.debug.unstripped) (debug.c:0)
kdp_i386_trap (in kernel.debug.unstripped) (kdp_machdep.c:436)
kernel_trap (in kernel.debug.unstripped) (trap.c:785)
trap_from_kernel (in kernel.debug.unstripped) + 38
DebuggerTrapWithState (in kernel.debug.unstripped) (debug.c:555)
panic_trap_to_debugger (in kernel.debug.unstripped) (debug.c:877)
0xffffff8000e7266f (in kernel.debug.unstripped)
zone_require (in kernel.debug.unstripped) (zalloc.c:664)
ipc_object_validate (in kernel.debug.unstripped) (ipc_object.c:500)
imq_lock (in kernel.debug.unstripped) (ipc_mqueue.c:1872)
ipc_port_send_turnstile_complete (in kernel.debug.unstripped) (ipc_port.c:1571)
ipc_port_adjust_special_reply_port_locked (in kernel.debug.unstripped) (ipc_port.c:1867)
mach_msg_receive_results_complete (in kernel.debug.unstripped) (mach_msg.c:719)
mach_msg_receive_results (in kernel.debug.unstripped) (mach_msg.c:334)
mach_msg_receive_continue (in kernel.debug.unstripped) (mach_msg.c:492)
ipc_mqueue_receive_continue (in kernel.debug.unstripped) (ipc_mqueue.c:993)
在iOS 14.1上运行相同的代码,结果:
panic(cpu 1 caller 0xfffffff02667d3f0): Kernel data abort. at pc 0xfffffff025f59d2c, lr 0xddf82e7025f5d4d0 (saved state: 0xffffffe8157d3a40)
除此之外,我们也可以在发送消息时触发内核崩溃。但是,我不知道这样做是否会更方便一些。
相反, 用port/knote/turnstile来覆盖host_notify的链表条目, 则显得更加困难。
如前所述,对于一个带有PORT_SYNC_LINK_ANY的新端口来说, 只能通过ipc_port_link_special_reply_port建链接,而且它还会检查是否存在已有的对象。所以,一旦host_request_notification附加了一个对象,ipc_port_link_special_reply_port就不再起作用了。
不过我想,我们可以先链接一个端口,然后用host_request_notification通过一个表项来覆盖这个端口,再用ipc_port_adjust_special_reply_port_locked通过knote或turnstile来覆盖表项。但是,具体如何操作,我还不是很清楚。
……我完全不知道这怎么会引起安全问题。
实际上,只有少数几种可以使用存储在ip_kobject或ip_sync_inheritor_ *中的值的 *** 。
host_notify_all:
我们显然不能使用它,因为iOS上的应用不能改变系统时间。
host_notify_port_destroy:
因为ip_kotype被设置为通知,所以当端口被销毁时,host_notify_port_destroy会被调用。
如前所述,我们不能使用ipc_port_link_special_reply_port来覆盖链表条目,因为它在覆盖之前会检查端口是否为空。如果我们想破坏host_notify_port_destroy函数,我们需要想办法让ipc_port_adjust_special_reply_port_locked(唯一一个设置ip_sync_inheritor_*字段的函数)用knote或turnstile来覆盖对象。
即使这样,由于链表在取消链接时存在多种安全检查,导致上述 *** 仍无法奏效。
ipc_port_adjust_special_reply_port_locked或各种turnstile/QoS *** 。
您有没有好办法呢?如何使链表节点与任务端口/knote/turnstile足够接近,从而使这些 *** 不会立即崩溃?
封装是非常重要的。
随你怎么笑,但你的CS101课本是对的:面向对象的编程本可以避免这种情况。
setSyncInheritorPort *** 可以检查是否已经设置了kobject,而setKObject *** 可以为链接的端口做同样的检查。
通过把检查放在一个地方,对象的用户就不需要自己去验证对象的状态,也不会像我们这里看到的那样漏掉一个检查。
Mach回复端口的使用 ***
如何按照Scott Knight和kernelshaman的指南编译macOS内核以添加调试语句。
CVE-2020-27932如何释放线程的特殊回复端口。
一、帝国3国语在线黑客接单流程 1、帮忙追回骗款黑客阿里巴巴吴翰清年薪接单但是到了今天,黑客这个词已经被用来摧毁或入侵他人的计算机。这些人的正确名字应该是克莱克,有些人把它翻译成了可怕的顾客。帝国3国...
雪纳瑞三口之家,著名的斗鱼直播频道, 男子陪人人喂狗谈天,夫人则卖力打扫卫生做菜。 之前斗鱼还很开放的时刻,夫人经常穿紧身亵服和短裙做菜,卖了不少肉,身体确实不错,脸就差一些了。 男主把摄像头部...
前言 近期,安天CERT(安全研究与应急处理中心)接收到来自客户反映的收到自己邮件地址发送给自己的恐吓邮件,勒索比特币的事件,经分析发现这是自10月份以来新的诈骗手法。 一、概述 由于邮件信...
root@e:/rootkit# python -m SimpleHTTPServer让我经过一个例子来演示怎么查询数据库称号的榜首个字符。 咱们假定该数据库称号叫“member”。 因而,榜首个字符...
根据最新的消息,微软Windows10 2020正式版已经正式发布了,目前只有开发者用户才可以下载到通过MSDN下载到 ISO镜像文件。对于普通用户而言还无法进行Windows10的更新,只有等到5月...
版权所有:http://www.pcsec.orgBK瞬间群感谢无敌小黄瓜的投递 原始代码可见http://hi.baidu.com/tr4c3/blog/item/da1c1c30c93da89ca...