连接和更新

查看机器IP

$ scutil --nwi

通过终端更新系统

$ sudo softwareupdae -iaR

关闭SIP

  • 启动到恢复模式(开机时按住Command + R)
  • 打开Terminal并运行csrutil disable
  • 重启到系统

安装Kernel Debug Kit

获取精确的系统版本

$ sw_vers

下载对应版本的KDK工具包并安装,也可以通过命令行完成

# 挂载设备到/Volumes目录
$ hdiutil attach xxxx.dmg

# 安装pkg文件
$ sudo installer -pkg xxxxx.pkg -target /

安装后可以在如下目录找到,如:

$ ls /Library/Developer/KDKs
KDK_10.14.1_18B75.kdk

在目标机上替换相应版本的内核并重启

# 注意mac OS 10.15 Catalina之后根分区只读,需要关闭SIP之后Remount RootFS
$ sudo mount -uw /

$ sudo cp kernel.development /System/Library/Kernels
$ sudo nvram boot-args="debug=0x146 kext-dev-mode=1 kcsuffix=development keepsyms=1"

# 这一步不是很必要,因为Reboot也会检查这个锁
$ sudo kextcache -i /

$ sudo reboot

此时使用

$ uname -a

即可看到内核已经被替换为development版本

调试

在目标机上触发断点(感谢CIA提供的方案)

$ sudo dtrace -w -n "BEGIN { breakpoint(); }"

此时目标机暂停响应并等待连接

宿主机上连接调试器

$ lldb /Library/Developer/KDKs/KDK_XXX.kdk/System/Library/Kernels/kernel.development
lldb> settings set target.load-script-from-symbol-file true
lldb> kdp-remote X.X.X.X
# 获取内核调试的帮助信息
lldb> kgmhelp

注意

Mac OS 15更新后,Xcode 11的LLDB默认切换到Python3,加载内核调试脚本时,会出现对Python2脚本的不兼容,使用下述方式切换

$ defaults write com.apple.dt.lldb DefaultPythonVersion 2

VMWare GDB调试设置

通过编辑虚拟机的.vmx配置文件,设置VMWare的gdb Server,32bit监听在8832,64bit的监听在8864,默认监听在本地,重启后有效

# If you are debugging a 32-bit machine use `guest32`
debugStub.listen.guest64 = "TRUE"

如果需要监听在0.0.0.0上需要添加这一行

# If you are debugging a 32-bit machine use `guest32`
debugStub.listen.guest64.remote = "TRUE"

通过gdb连接,Ctrl + C可以暂停内核执行

(gdb) file /Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Kernels/kernel.development

(gdb) target remote localhost:8864

通过lldb连接

(lldb) file /Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Kernels/kernel.development

(lldb) gdb-remote 8864

通过radare2连接

$ r2 -d gdb://localhost:8864

额外信息

一些有用的调试参数

#define DB_HALT         0x1			// (broken) halt on startup                                                                                   
#define DB_PRT          0x2			// (useful) send kernel debugging printf to console                                                            
#define DB_NMI          0x4			// (essential) drop into debugger on NMI (cmd-power, lcmd+rcmd+power, cmd-opt-ctrl-shift + esc, power)                                   
#define DB_KPRT         0x8			// (useless) send kernel debugging kprintf to serial port
#define DB_KDB          0x10		// (useless) use ddb/custom kernel debugger
#define DB_SLOG         0x20		// (useful) send some diagnostics to syslog
#define DB_ARP          0x40		// (essential) allow debugger to use ARP
#define DB_KDP_BP_DIS   0x80		// (useless) support old gdb versions
#define DB_LOG_PI_SCRN  0x100		// (essential) disable graphical panic dialog                                  
#define DB_KDP_GETC_ENA 0x200		// (useful) enable kdp_getc() prompt for (c) continue/(r) reboot                                  
                                                                                                                 
#define DB_KERN_DUMP_ON_PANIC	0x400	// Trigger core dump on panic               
#define DB_KERN_DUMP_ON_NMI		0x800	// Trigger core dump on NMI 
#define DB_DBG_POST_CORE		0x1000	// Wait in debugger after NMI core    
#define DB_PANICLOG_DUMP		0x2000	// Send paniclog on panic, not core
#define DB_REBOOT_POST_CORE		0x4000 /* Attempt to reboot after                                         
                                        * post-panic crashdump/paniclog                                   
                                        * dump.
                                        */

#define DB_NMI_BTN_ENA  0x8000		// (useful) Enable power button to directly trigger NMI                              
#define DB_PRT_KDEBUG   0x10000		// kprintf KDEBUG traces

macOS自带了一个kdumpd[2]服务可以用来将内核的coredump转储到远程服务器上

参考

  1. https://wikileaks.org/ciav7p1/cms/page_17760389.html

  2. https://developer.apple.com/library/archive/technotes/tn2004/tn2118.html#ACTIVATEKDUMP