2025年libnids源码分析(libgo源码分析)

libnids源码分析(libgo源码分析)对于安全研究人员来说 他们经常需要研究各种内核 以充分了解研究目标 在 Windows 平台上这样做并不是什么难事 因为有无数关于内核调试设置的现成文章 但是 对于 macOS 情况就略有不同 有很多文章已经描述了如何在两台设备之间设置内核调试 但是所有这些都建议应该禁用 SIP 系统完整性保护 进行内核调试 如果我们要调查 macOS 安全机制的内部运作 则会产生问题 因为关闭 SIP 也会关闭操作系统的大多数基本安全功能 这篇文章将会介绍几个设置 这些设置使你可以在调试时启用 SIP



  对于安全研究人员来说,他们经常需要研究各种内核,以充分了解研究目标。在Windows平台上这样做并不是什么难事,因为有无数关于内核调试设置的现成文章。但是,对于macOS,情况就略有不同。

  有很多文章已经描述了如何在两台设备之间设置内核调试,但是所有这些都建议应该禁用SIP(系统完整性保护)进行内核调试。如果我们要调查macOS安全机制的内部运作,则会产生问题,因为关闭SIP也会关闭操作系统的大多数基本安全功能。

  这篇文章将会介绍几个设置,这些设置使你可以在调试时启用SIP。

  设置如下:

  主机:带有补充更新的macOS Catalina 10.15.4;

  来宾:具有补充更新的macOS Catalina 10.15.4;

  VMware Fusion 11.5.3;

  调试器:LLDB;

  第一种方法

  我们将从调试内核的原始发行版开始,该发行版默认包含在macOS中。到目前为止,这是我们将看到的最简单的方法。

  第一步是从Apple的开发人员下载中下载内核调试工具包(KDK)。但是,在执行此操作之前,我们需要确定感兴趣的构建版本。这可以通过在来宾VM上使用以下命令来完成:

  % sw_vers

  ProductName: Mac OS X

  ProductVersion: 10.15.4

  BuildVersion: 19E287

  检索内核构建版本信息

  知道BuildVersion编号后,就可以下载相应的KDK并将其安装在主机上。它将安装在/ Library / Developer / KDKs /下。

  % ls -l /Library/Developer/KDKs/KDK_10.15.4_19E287.kdk/System/Library/Kernels/

  total 212112

  -rwxr-xr-x 1 root wheel 16030560 Mar 5 07:38 kernel

  drwxr-xr-x 3 root wheel 96 Mar 5 07:38 kernel.dSYM

  -rwxr-xr-x 1 root wheel 23795528 Mar 5 07:27 kernel.debug

  drwxr-xr-x 3 root wheel 96 Mar 5 07:27 kernel.debug.dSYM

  -rwxr-xr-x 1 root wheel 19329072 Mar 5 07:39 kernel.development

  drwxr-xr-x 3 root wheel 96 Mar 5 07:39 kernel.development.dSYM

  -rwxr-xr-x 1 root wheel 49436536 Mar 5 07:30 kernel.kasan

  KDK的位置

  下一步是在来宾VM上启用远程调试。幸运的是,VMware Fusion具有一个称为gdb stub的功能,该功能可以设置GDB服务器,并允许调试器使用GDB远程协议调试任何VM(包括Windows)。由于LLDB支持GDB协议,因此我们可以使用这种方法。

  要为我们的来宾VM启用GDB存根,就需要在虚拟机vmx配置文件中添加以下行:

  debugStub.listen.guest64 = "TRUE"

  启用VMware gdb存根

  接下来,我们启动虚拟机,在主机上启动lldb,并发出以下命令来指定我们的内核并启用符号文件的加载:

  (lldb) target create /Library/Developer/KDKs/KDK_10.15.4_19E287.kdk/System/Library/Kernels/kernel

  (lldb) settings set target.load-script-from-symbol-file true

  (lldb) gdb-remote 8864

  使用适当的符号启动LLBD

  第一个命令将告诉lldb在哪里可以找到内核符号,此命令不是严格必需的,因为lldb会搜索/ Library / Developer / KDKs路径以及Spotlight索引的任何其他路径,但即使搜索失败,它仍然是一个很好的实践。

  第二个命令将告诉lldb加载在符号(dSYM)目录中找到的所有脚本,这非常有用,因为这些脚本通常扩展lldb的功能。对于内核,我们可以使用大约400个新命令。

  最后一个命令告诉lldb远程服务器正在侦听哪个端口,如果我们未指定IP地址或主机名(如此处所示),它将连接到本地主机。在默认情况下,VMware监听本地主机上的端口8864,所以这是我们连接到的端口。

  如果一切顺利,我们应该进入虚拟机并开始调试。我们还可以随时使用调试器中的“CTRL+C”快捷键再次中断。

  (lldb) gdb-remote 8864

  Kernel UUID: AB0AA7EE-3D03-3C21-91AD-5719D79D7AF6

  Load Address: 0xffffff8002600000

  Kernel slid 0x2400000 in memory.

  (...)

  Process 1 stopped

  * thread #3, name = '0xffffff8009854a40', queue = 'cpu-0', stop reason = signal SIGTRAP

  frame #0: 0xffffff800284dede kernel`machine_idle at pmCPU.c:181:3 [opt]

  Target 0: (kernel) stopped.

  (lldb) image list

  [ 0] AB0AA7EE-3D03-3C21-91AD-5719D79D7AF6 0xffffff8002600000 /Library/Developer/KDKs/KDK_10.15.4_19E287.kdk/System/Library/Kernels/kernel

  /Library/Developer/KDKs/KDK_10.15.4_19E287.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/DWARF/kernel

  (...)

  使用符号调试LLDB macOS内核

  需要注意的一件事是,如果我们的VM和主机运行相同的内核,我们也可以使用基本内核二进制文件(/ System / Library / Kernels / kernel)作为目标。但是,我们将无权访问这些符号。

  (lldb) target create /System/Library/Kernels/kernel

  Current executable set to '/System/Library/Kernels/kernel' (x86_64).

  (lldb) gdb-remote 8864

  Process 1 stopped

  * thread #1, stop reason = signal SIGTRAP

  frame #0: 0xffffff8003b980f6

  -> 0xffffff8003b980f6: rep stosb byte ptr es:[rdi], al

  0xffffff8003b980f8: ret

  0xffffff8003b980f9: add byte ptr [rax], al

  0xffffff8003b980fb: add byte ptr [rax], al

  Target 0: (kernel) stopped.

  (lldb) image list

  [ 0] AB0AA7EE-3D03-3C21-91AD-5719D79D7AF6 0xffffff8000200000 /System/Library/Kernels/kernel

  (lldb) memory read 0xffffff8000200000

  0xffffff8000200000: cf fa ed fe 07 00 00 01 03 00 00 00 02 00 00 00 ????............

  0xffffff8000200010: 12 00 00 00 d0 0f 00 00 01 00 20 00 00 00 00 00 ....?..... .....

  (lldb) continue

  没有符号的LLDB macOS内核调试

  最后,需要注意的是,VMware默认使用硬件断点,这将我们限制为四个。但是,可以通过将vmx配置文件中的hideBreakpoints设置设置为FALSE来克服此限制,如下所示:

  debugStub.hideBreakpoints = "FALSE"

  禁用VMWare使用硬件断点

  第二种方法

  在上一节中,我们讨论了如何使用内核的发行版设置macOS内核调试。不过,必须要指出的是,苹果还发布了调试或开发内核。根据苹果的说法,它们是使用“其他断言和错误检查”进行编译的,它们可以在初次启动后停止并等待调试器连接。

  对于这个设置,这些内核并不是严格需要的,因为我们仍然会使用VMware以前的功能。更具体地说,macOS内核将不负责实际的调试。但是,如果在特殊情况下确实需要这些内核,这就是我们可以进行设置的方式。

  在来宾VM上执行其他任何操作之前,我们首先需要暂时禁用SIP。这样做的原因是因为/ System /路径受SIP写入保护。为此,我们可以启动到恢复模式(在打开虚拟机后启动CMD + R),运行csrutil disable命令,然后重新启动。

  研究人员发现,MIME库中MFMutableData的实现缺少对系统调用ftruncate()的漏洞检查,该漏洞导致越界写入。我们还找到了一种无需等待系统调用ftruncate失败即可触发OOB-Write的方法。此外,我们发现了可以远程触发的堆溢出。众所周知,这两种漏洞都是可以远程触发的。OOB写入漏洞和堆溢出漏洞都是由于相同的漏洞而引发的,即未正确处理系统调用的返回值。远程漏洞可以在处理下载的电子邮件时触发,在这种情况下,电子邮件将无法完全下载到设备上。

  受影响的库:/System/Library/PrivateFrameworks/MIME.framework/MIME;易受攻击的函数:-[MFMutableData appendBytes:length:]。

  除了手机邮件应用暂时放缓外,用户观察不到任何其他异常行为。在iOS 12上尝试利用漏洞(成功/失败)之后,用户只会注意到邮件应用程序突然崩溃。在iOS13上,除了暂时的速度下降之外,这不会引起注意。如果随后进行另一次攻击并删除电子邮件,则失败的攻击在iOS 13上不会明显。

  在失败的攻击中,攻击者发送的电子邮件将显示消息:“此消息无内容。”用户经历的部分崩溃(多次崩溃中的一部分)如下;崩溃的指令是stnp x8,x9,[x3],这意味着x8和x9的值已被写入x3并由于访问存储在x3中的无效地址0x000000013aa1c000而崩溃。

  为了找出导致进程崩溃的原因,我们需要看一下MFMutableData的实现。

  下面的调用树是从崩溃日志中提取的,只有选定的一些设备才会发生崩溃。通过分析MIME库,-[MFMutableData appendBytes:length:]的伪代码如下:在崩溃发生之前执行以下调用堆栈:如果数据大小达到阈值,则使用文件存储实际数据,当数据更改时,应相应更改映射文件的内容和大小,系统调用ftruncate()被inside -[MFMutableData _flushToDisk:capacity:]调用以调整映射文件的大小。ftruncate的帮助文档是这样说明的:如上所示,如果调用失败,则返回-1,并且全局变量errno指定漏洞。这意味着在某些情况下,此系统调用将无法截断文件并返回漏洞代码。但是,在ftruncate系统调用失败时,_flushToDisk无论如何都会继续,这意味着映射的文件大小不会扩展,执行最终会到达appendBytes()函数中的memmove(),从而导致mmap文件出现超出边界(OOB)的写入。自macOS Catalina发行以来,/路径作为只读安装,作为除SIP之外的附加保护。因此,我们需要使其可写,以便将调试内核复制到正确的位置。

  重新启动后,我们将根目录mount 为可写:

  sudo mount -uw /

  将根目录mount 为可写,并复制我们选择的内核(在本例中为调试):

  sudo cp /Library/Developer/KDKs/KDK_10.15.4_19E287.kdk/System/Library/Kernels/kernel.debug /System/Library/Kernels/

  将调试内核复制到适当的位置

  然后,我们需要使内核缓存无效,这是必需的,因为macOS不会直接运行内核二进制文件,而是作为预链接的内核运行,它是由内核和内核扩展构建的。通常,预链接是在我们安装新的内核扩展或内核时发生的,但在本例中并非如此。在这里,我们只需复制内核的开发或调试版本。

  sudo kextcache -invalidate /

  sudo kextcache -invalidate /Volumes/Macintosh HD

  内核缓存无效

  最后,我们需要设置NVRAM引导参数以引导进入调试内核而不是常规内核,并引导进入恢复模式以使用csrutil enable命令重新打开SIP。

  sudo nvram boot-args="kcsuffix=debug"

  设置启动内核

  现在,我们可以在主机上运行与以前相同的命令,这次指定调试内核。

  (lldb) target create /Library/Developer/KDKs/KDK_10.15.4_19E287.kdk/System/Library/Kernels/kernel.debug

  (lldb) settings set target.load-script-from-symbol-file true

  (lldb) gdb-remote 8864

  启动调试内核调试的命令

  现在,我们可以在调试版而不是内核的发行版上执行macOS内核调试。

  Process 1 stopped

  * thread #2, name = '0xffffff80158f0e28', queue = 'cpu-0', stop reason = signal SIGTRAP

  frame #0: 0xffffff80052ee796 kernel.debug`machine_idle at pmCPU.c:181:3

  Target 0: (kernel.debug) stopped.

  (lldb) image list

  [ 0] 16545FA7-C11F-3D9E-88FA-8DDB13E1A439 0xffffff8005000000 /Library/Developer/KDKs/KDK_10.15.4_19E287.kdk/System/Library/Kernels/kernel.debug

  /Library/Developer/KDKs/KDK_10.15.4_19E287.kdk/System/Library/Kernels/kernel.debug.dSYM/Contents/Resources/DWARF/kernel.debug

  [ 1] A6D59354-C9A1-3C61-87A7-C04DD74421B1 0xffffff7f8609f000 //System/Library/Extensions/corecrypto.kext/Contents/MacOS/corecrypto

  (...)

  其他方法

  为了完整起见,我们将简要讨论如何使用macOS内核而不是VMware gdb存根设置内核调试,这是其他地方最常用的方法。我们还将展示我们可以启用SIP,尽管人们普遍错误地认为SIP必须关闭。

  这些步骤与前面的步骤本质上是相同的,只是有一点不同。在本例中,应按如下所示设置调试器框中的NVRAM变量:

  nvram boot-args="kcsuffix=debug debug=0x44"

  为内核调试设置NVRAM变量

  从本质上讲,这些设置表明调试对象可以执行网络级调试并中断时中断。但是,中断是很复杂的,因为我们需要按CMD + OPTION + CONTROL + SHIFT + ESCAPE来进入调试器。此外,这必须在我们正在调试的目标VM上完成。当其他人使用这种方法成功使用此方法导致了中断,,我们就没有那么幸运了。相反,我们在VMware Key Mappings使用CMD + B为这个组合创建了一个键盘快捷键。

  “Windows”和“Alt”按钮作为目标键映射,但它们在macOS中分别转换为“Command”和“Option”,VMware没有提供指定密钥macOS版本的选项。

  最后,在主机上,我们将使用带有调试对象IP地址的kdp-remote命令,而不是gdb-remote。请注意,在发出此命令之前,我们需要在debuggee上进入调试器。

  (lldb) kdp-remote 192.168.242.129

  使用kdp-remote

  总结

  在这篇文章中,我们展示了调试macOS内核的三种不同方式,同时确定不需要永久禁用SIP。由于易于设置,我们首选的方法是我们描述的第一种方法,但如果情况需要,可以使用其他方法。

  参考及来源:https://www.offensive-security.com/offsec/kernel-debugging-macos-with-sip/?utm_content=129155041&utm_medium=social&utm_source=twitter&hss_channel=tw-134994790

编程小号
上一篇 2025-02-07 13:33
下一篇 2025-02-11 11:17

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ri-ji/45233.html