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

访客3年前黑客工具600

全文详细地址:

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

相关文章

24小时接单的黑客电话(24小时接单黑客的联系方

网站建设前期需注意的四大要点 一、网站主题与关键词明确 这是网站建设计划前期的必须考虑的两个部分,由于这两个部分的联络非常严密,因此这里把这两个计划模块放在一起来评论,身为站长,首先就是考虑主题,...

黑客精神定义(黑客的概述)

黑客精神定义(黑客的概述)

本文导读目录: 1、黑客精神是什么。 2、黑客是怎么定义的? 3、黑客道德、精神、信仰是什么? 4、“黑客”的科学定义是什么 5、什么是黑客精神 黑客精神是什么。 寻找系统存在的漏洞...

孕妇贫血对胎儿有什么影响(对胎儿和孕妇都有不良影响,切勿大意)

女士在怀孕期,由于人体所需血夜量的提升,再加上为考虑胚胎、胎宝宝成长发育所需,造成 孕妈妈的血夜容积会比平常提升4倍多。由于怀孕期间的反映,导致孕妈妈对铜元素的营养成分摄取不够,最后造成 孕妈妈的缺铁...

黑客kiko第几部中出现(KIKO事件)

黑客kiko第几部中出现(KIKO事件)

本文目录一览: 1、《唐人街探案3》kiko扮演者是谁? 2、唐人街探案2当中的女黑客KIKO是谁演的 3、唐人街探案2KIKO是谁演的 4、《唐人街探案3》的配角女孩,出场4分钟片酬30...

广州男士休闲spa会所

广州男士休闲spa会所 广州男士休闲spa会所 浮生若梦休眨眼,满头青丝成雪,只一瞬间,此生怎便,依旧春衫少年,一樽酒,一盏茶,月下秉烛,竟彻谈长夜。【男士SPA】 【男士SPA】高端私人...

宇宙飞船的速度大约是多少(世界上最快的宇宙飞船)

  浩瀚的宇宙无边无际,也让人类充满了一探究竟之心。随着科技的发展,人类的航天活动也越大的频繁。如果人类要探索宇宙,就需要借助宇宙飞船,那你知道现今世界上最快的飞船速度是多少呢?在过去,人类的最大速度...