0x01 前言
接上文继续对kernel panic进行更进一步的分析.
0x02 分析
前文中使用的IDA分析的二进制文件是没有更详细的符号信息的,因此我们可以使用其他的工具来帮助我们更好的分析.
前期准备
众所周知苹果的MAC OS 内核是开源的,而上层运行库及图形界面是私有的.
下载对应内核版本的kernel源代码。
可以使用uname -a 查看内核版本。
可以看到这里我们使用的版本是xnu-7195.121.3~9。
而后在github上查看对应版本的源代码并下载。
https://github.com/apple/darwin-xnu/tags
如下图。
除此之外还需要安装对应版本的mac 的 kernel debug kit 。
在苹果官网下载https://developer.apple.com/download/more/?q=Kernel%20Debug%20Kit
系统版本可以在关于本机查看。
开始分析
使用lldb 来进行加载kernel。
lldb
(lldb) settings set target.load-script-from-symbol-file true
根据panic report调整kernel slide。
(lldb) target modules load --file kernel --slide 0x000000000bc00000
查看panic report 中发生异常的代码位置。
(lldb) image lookup -a 0xffffff800926997d
Address:kernel[0xffffff800025997d] (kernel.__TEXT.__text + 231805)
Summary:kernel`ipc_kmsg_get_from_kernel + 45 at ipc_kmsg.c:2103:29打开源码包中的对应文件找到对应行数。
通过观察汇编代码能确定问题发生在。
IP_PREALLOC(dest_port)
IP_PREALLOC和IP_VALID的定义为。
ipc_port_valid(ipc_port_t port)
{
return port != IPC_PORT_DEAD&& port;
}
dest_port为 ipc_port_t类型数据。
ipc_port_t dest_port;
typedef struct ipc_port *ipc_port_t;
ipc_port结构体如下:
struct ipc_port {
/*
* Initial sub-structure in common withipc_pset
* First element is an ipc_object second is a
* message queue
*/
struct ipc_object ip_object;
struct ipc_mqueueip_messages;
union {
struct ipc_space *receiver;
struct ipc_port *destination;
ipc_port_timestamp_t timestamp;
} data;
/* updatehost_request_notification if this union is changed */
union {
ipc_kobject_tXNU_PTRAUTH_SIGNED_PTR("ipc_port.kobject") kobject;
ipc_kobject_label_t XNU_PTRAUTH_SIGNED_PTR("ipc_port.kolabel")kolabel;
ipc_importance_task_timp_task;
ipc_port_tsync_inheritor_port;
struct knote*sync_inheritor_knote;
struct turnstile*sync_inheritor_ts;
} kdata;
struct ipc_port*ip_nsrequest;
struct ipc_port*ip_pdrequest;
struct ipc_port_request*ip_requests;
union {
struct ipc_kmsg*XNU_PTRAUTH_SIGNED_PTR("ipc_port.premsg") premsg;
struct turnstile*send_turnstile;
ipc_port_tXNU_PTRAUTH_SIGNED_PTR("ipc_port.alt_port") alt_port;
} kdata2;
mach_vm_address_tip_context;
natural_tip_sprequests:1, /* send-possiblerequests outstanding */
ip_spimportant:1, /* ... at least one is importancedonating */
ip_impdonation:1, /* port supports importance donation*/
ip_tempowner:1, /* dont give donations to currentreceiver */
ip_guarded:1, /* port guarded (use contextvalue as guard) */
ip_strict_guard:1, /* Strict guarding; Prevents usermanipulation of context values directly */
ip_specialreply:1, /* port is a special reply port */
ip_sync_link_state:3, /* link the port to destination port/Workloop */
ip_sync_bootstrap_checkin:1,/* port part ofsync bootstrap checkin, push on thread doing the checkin */
ip_immovable_receive:1, /* the receive right cannot be moved outof a space, until it is destroyed */
ip_no_grant:1, /* Port wont accept complexmessages containing (ool) port descriptors */
ip_immovable_send:1, /* No send(once) rights to this portcan be moved out of a space */
ip_tg_block_tracking:1, /* Track blocking relationship betweenthread groups during sync IPC */
ip_pinned: 1, /* Can't deallocate the lastsend right from a space while the bit is set */
ip_impcount:16; /* number of importance donationsin nested queue */
mach_port_mscount_tip_mscount;
mach_port_rights_tip_srights;
mach_port_rights_tip_sorights;
/* queue_chain_t ip_port_links;*//* all allocated ports */
thread_t ip_thread; /* who made me? thread context */
unsigned long ip_timetrack; /* give an idea of "when" created*/
uintptr_t ip_callstack[IP_CALLSTACK_MAX]; /* stacktrace */
unsigned long ip_spares[IP_NSPARES]; /* for debugging */
uint8_t ip_srp_lost_link:1, /* special reply port turnstile link chainbroken */
ip_srp_msg_sent:1; /* special reply port msgsent */
};
发生崩溃的数据来源于ipc_kmsg_get_from_kernel函数传入的msg参数赋值。
dest_port = msg->msgh_remote_port;
根据panic的调用栈分析,调用ipc_kmsg_get_from_kernel的上层函数为mach_msg_send_from_kernel_proper
往上是ipc_notify_port_destroyed-->ipc_port_destroy-->ipc_port_dealloc_special-->ipc_thread_terminate-->thread_deallocate_complete-->_mpsc_daemon_queue_drain-->_mpsc_queue_thread_continue-->call_continuation。
call_continuation用于继续线程
_mpsc_queue_thread_continue用于mpsc 线程队列的继续
_mpsc_daemon_queue_drain排队,排空和取消
thread_deallocate_complete完成线程释放
ipc_thread_terminateipc线程的终止
ipc_port_dealloc_special释放端口,消除引用
ipc_port_destroy销毁ipc 端口
ipc_notify_port_destroyed(ipc_port 1006) 发送端口销毁通知
ipc_kmsg_get_from_kernel查看端口是否为内核客户端分配了 kmsg
整个过程大概是 在进行ipc线程终止的时,释放端口的过程发生了内存访问错误。
具体原因通过观察panic进行分析。
可以从其中获得Fault CR2 以及Error code 信息来进行发生问题的具体分析。通过翻看源代码可以知道Error code是来自regs->isf.err
在源码中定位到这么一段
找到相关错误代码的定义表
至此有个问题那就是错误代码0x0在哪呢?
仔细观察,定义上面错误代码的源文件是osfmki386trap.h
发现在osfmkarmtrap.h也做了定义如下
因此只能大概的知道是内存访问的问题。
但是不清楚当时的内存是什么布局什么情况,panic要是有类似vmmap那样显示内存布局就好了.
0x03 分析过程的坑
LLDB使用过程中的问题
python 版本问题
loading kernel debugging from /Library/Developer/KDKs/KDK_11.4_20F71.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/Python/kernel.py
LLDB version lldb-1205.0.28.2
Apple Swift version 5.4.2 (swiftlang-1205.0.28.2 clang-1205.0.19.57)
settings set target.process.python-os-plugin-path"/Library/Developer/KDKs/KDK_11.4_20F71.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/Python/lldbmacros/core/operating_system.py"
settings set target.trap-handler-names hndl_allintrs hndl_alltrapstrap_from_kernel hndl_double_fault hndl_machine_check _fleh_prefabt_ExceptionVectorsBase _ExceptionVectorsTable _fleh_undef _fleh_dataabt_fleh_irq _fleh_decirq _fleh_fiq_generic _fleh_dec
command script import"/Library/Developer/KDKs/KDK_11.4_20F71.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/Python/lldbmacros/xnu.py"
error: module importing failed: Traceback (most recent call last):
File "<string>",line 1, in <module>
File"/Library/Developer/KDKs/KDK_11.4_20F71.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/Python/lldbmacros/xnu.py",line 123
print "Executioninterrupted by user"
^
SyntaxError: Missing parentheses in call to 'print'. Did you meanprint("Execution interrupted by user")?
settings set target.process.optimization-warnings false
解决方法在命令行输入
defaults write com.apple.dt.lldb DefaultPythonVersion 2
0x04 小结
本文对kernel更进一步的分析,由于对mac的kernel并没有足够的研究积累。因此还有很多疑问,欢迎大家一起探讨。后续如果能找到能稳定复现的方法可能会出下一章,涉及到内核调试,以及内核漏洞利用的内容。
原文始发于微信公众号(BeFun安全实验室):MAC kernel panic分析(2)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论