Translated ['src/macos-hardening/macos-security-and-privilege-escalation

This commit is contained in:
Translator 2025-08-10 16:35:26 +00:00
parent 58f97030d5
commit 932fb9460a

View File

@ -1,32 +1,43 @@
# macOS Kernel Extensions & Debugging
# macOS 内核扩展与调试
{{#include ../../../banners/hacktricks-training.md}}
## 基本信息
内核扩展Kexts**以 `.kext`** 扩展名的 **包**,它们被 **直接加载到 macOS 内核空间**,为主操作系统提供额外的功能。
内核扩展Kexts**以 `.kext` 为扩展名的包**,直接 **加载到 macOS 内核空间**,为主操作系统提供额外功能。
### 废弃状态与 DriverKit / 系统扩展
**macOS Catalina (10.15)** 开始Apple 将大多数遗留 KPI 标记为 *废弃*,并引入了 **系统扩展和 DriverKit** 框架,这些框架在 **用户空间** 中运行。从 **macOS Big Sur (11)** 开始,操作系统将 *拒绝加载* 依赖于废弃 KPI 的第三方 kext除非机器以 **降低安全性** 模式启动。在 Apple Silicon 上,启用 kext 还要求用户:
1. 重启进入 **恢复***启动安全实用工具*
2. 选择 **降低安全性** 并勾选 **“允许用户管理来自已识别开发者的内核扩展”**。
3. 重启并在 **系统设置 → 隐私与安全** 中批准 kext。
使用 DriverKit/系统扩展编写的用户空间驱动程序显著 **减少攻击面**,因为崩溃或内存损坏被限制在沙盒进程中,而不是内核空间。
> 📝 从 macOS Sequoia (15) 开始Apple 完全移除了几个遗留的网络和 USB KPI 唯一向前兼容的解决方案是迁移到系统扩展。
### 要求
显然,这非常强大,以至于 **加载内核扩展****复杂的**。内核扩展必须满足以下 **要求** 才能被加载:
显然,这么强大以至于 **加载内核扩展****复杂的**。内核扩展必须满足以下 **要求** 才能被加载:
- 当 **进入恢复模式** 时,内核 **扩展必须被允许** 加载:
- 当 **进入恢复模式** 时,必须 **允许加载内核扩展**
<figure><img src="../../../images/image (327).png" alt=""><figcaption></figcaption></figure>
- 内核扩展必须 **使用内核代码签名证书签名**,该证书只能由 **Apple** 授予。谁将详细审查公司及其所需的原因。
- 内核扩展必须 **使用内核代码签名证书签名**,该证书只能由 **Apple 授予**。Apple 将详细审核公司及其所需原因。
- 内核扩展还必须 **经过公证**Apple 将能够检查其是否含有恶意软件。
- 然后,**root** 用户是唯一可以 **加载内核扩展** 的人,包内的文件必须 **属于 root**
- 在上传过程中,包必须准备在 **受保护的非 root 位置**`/Library/StagedExtensions`(需要 `com.apple.rootless.storage.KernelExtensionManagement` 授权)。
- 最后,尝试加载时,用户将 [**收到确认请求**](https://developer.apple.com/library/archive/technotes/tn2459/_index.html),如果接受,计算机必须 **重启** 以加载它。
- 最后,尝试加载时,用户将 [**收到确认请求**](https://developer.apple.com/library/archive/technotes/tn2459/_index.html),如果接受,计算机必须 **重启** 以加载它。
### 加载过程
在 Catalina 中是这样的:有趣的是,**验证** 过程发生在 **用户空间**。然而,只有具有 **`com.apple.private.security.kext-management`** 授权的应用程序可以 **请求内核加载扩展**`kextcache``kextload``kextutil``kextd``syspolicyd`
在 Catalina 中是这样的:有趣的是,**验证** 过程发生在 **用户空间**。然而,只有具有 **`com.apple.private.security.kext-management`** 授权的应用程序可以 **请求内核加载扩展**`kextcache``kextload``kextutil``kextd``syspolicyd`
1. **`kextutil`** cli **启动** 加载扩展的 **验证** 过程
- 它将通过发送 **Mach 服务****`kextd`** 进行通信。
2. **`kextd`** 将检查个事项,例如 **签名**
- 它将通过使用 **Mach 服务****`kextd`** 进行通信。
2. **`kextd`** 将检查个事项,例如 **签名**
- 它将与 **`syspolicyd`** 进行通信以 **检查** 扩展是否可以 **加载**
3. **`syspolicyd`** 将 **提示** **用户** 如果扩展尚未被加载。
- **`syspolicyd`** 将结果报告给 **`kextd`**
@ -34,20 +45,41 @@
如果 **`kextd`** 不可用,**`kextutil`** 可以执行相同的检查。
### 枚举(已加载的 kexts
### 枚举与管理(已加载的 kexts
`kextstat` 是历史工具,但在最近的 macOS 版本中已 **废弃**。现代接口是 **`kmutil`**
```bash
# Get loaded kernel extensions
# List every extension currently linked in the kernel, sorted by load address
sudo kmutil showloaded --sort
# Show only third-party / auxiliary collections
sudo kmutil showloaded --collection aux
# Unload a specific bundle
sudo kmutil unload -b com.example.mykext
```
旧语法仍可供参考:
```bash
# (Deprecated) Get loaded kernel extensions
kextstat
# Get dependencies of the kext number 22
# (Deprecated) Get dependencies of the kext number 22
kextstat | grep " 22 " | cut -c2-5,50- | cut -d '(' -f1
```
`kmutil inspect` 还可以用于 **转储内核集合 (KC)** 的内容或验证 kext 是否解析所有符号依赖:
```bash
# List fileset entries contained in the boot KC
kmutil inspect -B /System/Library/KernelCollections/BootKernelExtensions.kc --show-fileset-entries
# Check undefined symbols of a 3rd party kext before loading
kmutil libraries -p /Library/Extensions/FancyUSB.kext --undef-symbols
```
## Kernelcache
> [!CAUTION]
> 尽管内核扩展预计位于 `/System/Library/Extensions/` 中,但如果你去这个文件夹,你 **不会找到任何二进制文件**。这是因为 **kernelcache**,为了反向工程一个 `.kext`,你需要找到获取它的方法。
**kernelcache** 是 **XNU 内核的预编译和预链接版本**,以及基本的设备 **驱动程序****内核扩展**。它以 **压缩** 格式存储并在启动过程中解压到内存中。kernelcache 通过提供一个随时可运行的内核和关键驱动程序的版本,促进了 **更快的启动时间**,减少了在启动时动态加载和链接这些组件所需的时间和资源。
**kernelcache** 是 **XNU 内核的预编译和预链接版本**,以及必要的设备 **驱动程序****内核扩展**。它以 **压缩** 格式存储并在启动过程中解压到内存中。kernelcache 通过提供一个准备就绪的内核和关键驱动程序的版本,促进了 **更快的启动时间**,减少了在启动时动态加载和链接这些组件所需的时间和资源。
### Local Kerlnelcache
@ -58,12 +90,12 @@ kextstat | grep " 22 " | cut -c2-5,50- | cut -d '(' -f1
#### IMG4
IMG4 文件格式是 Apple 在其 iOS 和 macOS 设备中用于安全 **存储和验证固件** 组件(如 **kernelcache**的容器格式。IMG4 格式包括一个头部和几个标签,这些标签封装了不同的数据片段,包括实际的有效载荷(如内核或引导加载程序)、签名和一组清单属性。该格式支持加密验证,允许设备在执行固件组件之前确认其真实性和完整性。
IMG4 文件格式是苹果在其 iOS 和 macOS 设备中用于安全 **存储和验证固件** 组件(如 **kernelcache**的容器格式。IMG4 格式包括一个头部和几个标签,这些标签封装了不同的数据片段,包括实际的有效载荷(如内核或引导加载程序)、签名和一组清单属性。该格式支持加密验证,允许设备在执行固件组件之前确认其真实性和完整性。
它通常由以下组件组成:
- **有效载荷 (IM4P)**
- 通常是压缩的 (LZFSE4, LZSS, …)
- 通常被压缩LZFSE4, LZSS, …)
- 可选加密
- **清单 (IM4M)**
- 包含签名
@ -75,7 +107,7 @@ IMG4 文件格式是 Apple 在其 iOS 和 macOS 设备中用于安全 **存储
解压 Kernelcache
```bash
# img4tool (https://github.com/tihmstar/img4tool
# img4tool (https://github.com/tihmstar/img4tool)
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
# pyimg4 (https://github.com/m1stadev/PyIMG4)
@ -126,11 +158,60 @@ kextex_all kernelcache.release.iphone14.e
# Check the extension for symbols
nm -a binaries/com.apple.security.sandbox | wc -l
```
## 调试
## 最近的漏洞与利用技术
## 参考
| 年份 | CVE | 摘要 |
|------|-----|---------|
| 2024 | **CVE-2024-44243** | **`storagekitd`** 中的逻辑缺陷允许 *root* 攻击者注册一个恶意文件系统包,最终加载一个 **未签名的 kext****绕过系统完整性保护 (SIP)** 并启用持久性 rootkit。已在 macOS 14.2 / 15.2 中修补。 |
| 2021 | **CVE-2021-30892** (*Shrootless*) | 带有 `com.apple.rootless.install` 权限的安装守护进程可能被滥用以执行任意后安装脚本,禁用 SIP 并加载任意 kext。 |
- [https://www.makeuseof.com/how-to-enable-third-party-kernel-extensions-apple-silicon-mac/](https://www.makeuseof.com/how-to-enable-third-party-kernel-extensions-apple-silicon-mac/)
- [https://www.youtube.com/watch?v=hGKOskSiaQo](https://www.youtube.com/watch?v=hGKOskSiaQo)
**红队员的要点**
1. **寻找与磁盘仲裁、安装程序或 Kext 管理交互的有权限的守护进程 (`codesign -dvv /path/bin | grep entitlements`)。**
2. **滥用 SIP 绕过几乎总是授予加载 kext 的能力 → 内核代码执行**
**防御提示**
*保持 SIP 启用*,监控来自非 Apple 二进制文件的 `kmutil load`/`kmutil create -n aux` 调用,并对任何写入 `/Library/Extensions` 的操作发出警报。端点安全事件 `ES_EVENT_TYPE_NOTIFY_KEXTLOAD` 提供近实时的可见性。
## 调试 macOS 内核与 kexts
苹果推荐的工作流程是构建一个与正在运行的版本匹配的 **内核调试工具包 (KDK)**,然后通过 **KDP (内核调试协议)** 网络会话附加 **LLDB**
### 一次性本地调试 panic
```bash
# Create a symbolication bundle for the latest panic
sudo kdpwrit dump latest.kcdata
kmutil analyze-panic latest.kcdata -o ~/panic_report.txt
```
### 从另一台 Mac 进行实时远程调试
1. 下载并安装目标机器的确切 **KDK** 版本。
2. 使用 **USB-C 或 Thunderbolt 电缆** 将目标 Mac 和主机 Mac 连接起来。
3. 在 **目标**
```bash
sudo nvram boot-args="debug=0x100 kdp_match_name=macbook-target"
reboot
```
4. 在**主机**上:
```bash
lldb
(lldb) kdp-remote "udp://macbook-target"
(lldb) bt # get backtrace in kernel context
```
### 将 LLDB 附加到特定加载的 kext
```bash
# Identify load address of the kext
ADDR=$(kmutil showloaded --bundle-identifier com.example.driver | awk '{print $4}')
# Attach
sudo lldb -n kernel_task -o "target modules load --file /Library/Extensions/Example.kext/Contents/MacOS/Example --slide $ADDR"
```
> KDP 仅暴露一个 **只读** 接口。对于动态插桩,您需要在磁盘上修补二进制文件,利用 **内核函数钩子**(例如 `mach_override`)或将驱动程序迁移到 **虚拟机监控程序** 以实现完全的读/写。
## References
- DriverKit Security Apple Platform Security Guide
- Microsoft Security Blog *Analyzing CVE-2024-44243 SIP bypass*
{{#include ../../../banners/hacktricks-training.md}}