这是 CVE-2023-41992 的概念验证。首先,这与 越狱 无关!并且它仍在开发中。
感谢到目前为止帮助过我的每个人。出于隐私考虑,我可能不在此列出你们。如果想让我列出,请私信我!
据我所知,补丁位于 ipc_right_destroy 中。也有人曾在 X(或 Twitter)上指出这一点。
diff --git a/osfmk/ipc/ipc_right.c b/osfmk/ipc/ipc_right.c
index a81ac21..32a9a3e 100644
--- a/osfmk/ipc/ipc_right.c
+++ b/osfmk/ipc/ipc_right.c
@@ -912,7 +912,6 @@ ipc_right_destroy(
mach_port_type_t type;
bits = entry->ie_bits;
- entry->ie_bits &= ~IE_BITS_TYPE_MASK;
type = IE_BITS_TYPE(bits);
assert(is_active(space));
使用 ipc_right_destroy 在 ipc 空间中留下一个无类型的 ipc 条目会触发异常。请查看下面的 [0] 和 [1]。
kern_return_t
ipc_right_destroy(
ipc_space_t space,
mach_port_name_t name,
ipc_entry_t entry,
boolean_t check_guard,
uint64_t guard)
{
...
if (type == MACH_PORT_TYPE_SEND) {
if (ip_is_pinned(port)) {
assert(ip_active(port));
is_write_unlock(space);
mach_port_guard_exception_pinned(space, // <---- [0]
name, port, MPG_FLAGS_MOD_REFS_PINNED_DESTROY);
return KERN_INVALID_CAPABILITY;
}
ipc_hash_delete(space, ip_to_object(port), name, entry);
}
...
if ((type & MACH_PORT_TYPE_RECEIVE) &&
(check_guard) && (port->ip_guarded) &&
(guard != port->ip_context)) {
/* Guard Violation */
uint64_t portguard = port->ip_context;
ip_mq_unlock(port);
is_write_unlock(space);
/* Raise mach port guard exception */
mach_port_guard_exception(name, // <---- [1]
0, portguard, kGUARD_EXC_DESTROY);
return KERN_INVALID_RIGHT;
}
[0] 不会在第三方应用沙盒中杀死任务。我之前选择 mach_thread_self(),因为那是我能找到的唯一固定的发送权限。
但如果不避免 ReportCrash 或 SIGKILL,这个漏洞在 WebContent 沙盒中就没有用处。所以我进一步深入挖掘。
void
mach_port_guard_ast(thread_t t,
mach_exception_data_type_t code, mach_exception_data_type_t subcode)
{
...
if (reason <= MAX_FATAL_kGUARD_EXC_CODE) {
/*
* Fatal Mach port guards - always delivered synchronously.
* Check if anyone has registered for Synchronous EXC_GUARD, if yes then,
* deliver it synchronously and then kill the process, else kill the process
* and deliver the exception via EXC_CORPSE_NOTIFY.
*/
if (task_exception_notify(EXC_GUARD, code, subcode) == KERN_SUCCESS) {
task_bsdtask_kill(task);
} else {
exit_with_guard_exception(get_bsdtask_info(task), code, subcode);
}
...
内核中的 mach_port_guard_ast 处理 mach 端口保护异常。对于致命异常,它首先查找异常端口。如果异常通知返回 KERN_SUCCESS,则执行 SIGKILL。看起来很有希望,每个触发致命 mach 端口保护异常的任务都会被杀死。然而...
致命的 Mach 端口保护——始终同步传递。
我只需为触发漏洞的线程设置一个线程异常端口,并且不处理异常通知。内核会在这里等待回复,不会发送 SIGKILL。
在 ipc_right_copyout() 中出现恐慌,因为条目为空。