详细分析macOS 10.15.5系统中的CVE-2021-27932系统漏洞

访客3年前黑客工具598

全文详细地址:

最近,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个并列的代码块,而且,右侧有一行编码处在突显情况

image.png

原先的编码:

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如何释放线程的特殊回复端口。

相关文章

女孩子做客服的感受(千万别去电商公司上班)

女孩子做客服的感受(千万别去电商公司上班)

虽然我没有过,但是大概的感受能猜出来。 大家肯定会觉得:啊!客服妹子!你有福了,声音甜得要死,好听得不行。而且脾气绝对超级好,特别有耐心。关键长相还甜美 我只是想说,哥们你想多了,客服妹子对男朋友一定...

1位朋友关注 是谁

微信好像还没有这个功能,不过在那个宫微信圈里头看见他关注了什么东西,微信里面单你关注一个公众号的时候,你可以看见有几个朋友关注了,是公众号。而没。 点开公众号可以看到有多少个好友关注了,如果你想确定某...

美国黑客的生活(美国 黑客)

美国黑客的生活(美国 黑客)

本文导读目录: 1、真正意义上的黑客,到底可以厉害到什么程度? 2、曾经大名鼎鼎的黑客现在都在做什么? 3、黑客靠什么生活???? 4、世界第一黑客,凯文·米特尼克怎么出名的? 5、世...

黑客帝国4矩阵觉醒(黑客帝国进入矩阵)

黑客帝国4矩阵觉醒(黑客帝国进入矩阵)

本文导读目录: 1、《黑客帝国4》上映一个月倒计时,救世主究竟为什么会复活? 2、黑客帝国4为什么崔妮蒂有能力了 3、黑客帝国4讲的是什么故事 4、《黑客帝国4》夺冠,17天票房破8亿,这...

爱莎贝蒂面包坊总部在哪?加盟项目总部在大家心中

爱莎贝蒂面包坊总部在哪?加盟项目总部在大家心中

跟着美食产物的加盟品牌加盟项目不绝的增多,那么在市场上的竞争形势长短常紧要的,各人纷纷想要通过创业做加盟来钻营更多的经济好处。那么固然此刻有许多的加盟品牌,可是公共加盟商照旧无法快速的寻找到好的加盟品...

黑客改账户,黑客入侵网络图,电脑被黑客设了密码u盘买那种

atmdtrack是dtrack系列的一个变种。 虽然它们有相似之处,但它们也存在一些不同点。 StartupPacket· 英国政府也面对加密钱银相关的问题,包含英国信息专员办公室(ICO)、学生赞...