Розширення ядра macOS (Kernel Extensions) та Kernelcaches
Reading time: 10 minutes
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Основна інформація
Kernel extensions (Kexts) — це пакети з розширенням .kext
, які завантажуються безпосередньо в простір ядра macOS, додаючи додаткову функціональність до операційної системи.
Стан застарівання & DriverKit / System Extensions
Починаючи з macOS Catalina (10.15) Apple позначила більшість застарілих KPI як deprecated і представила фреймворки System Extensions & DriverKit, які працюють у user-space. Починаючи з macOS Big Sur (11) операційна система відмовляється завантажувати сторонні kext, що залежать від застарілих KPI, якщо машина не завантажена в режимі Reduced Security. На Apple Silicon увімкнення kext також вимагає від користувача:
- Перезавантажитися в Recovery → Startup Security Utility.
- Вибрати Reduced Security і поставити галочку “Allow user management of kernel extensions from identified developers”.
- Перезавантажитися і підтвердити kext у System Settings → Privacy & Security.
Драйвери в user-land, написані з використанням DriverKit/System Extensions, значно зменшують поверхню атаки, оскільки збої або пошкодження пам'яті обмежуються ізольованим процесом, а не простором ядра.
📝 Починаючи з macOS Sequoia (15) Apple повністю видалила кілька застарілих KPI для мереж та USB — єдиним сумісним шляхом для вендорів є міграція до System Extensions.
Вимоги
Очевидно, що це настільки потужно, що завантажити розширення ядра складно. Ось вимоги, які має виконувати розширення ядра для завантаження:
- Під час входу в режим відновлення (recovery mode) має бути дозволено завантаження kernel extensions:
.png)
- Розширення ядра має бути підписане сертифікатом підпису коду для ядра (kernel code signing certificate), який може видати лише Apple. Apple перевіряє компанію та причини, чому потрібен доступ.
- Розширення ядра також має бути notarized, Apple може перевірити його на наявність шкідливого ПЗ.
- Тільки користувач root може завантажити розширення ядра, і файли всередині пакета повинні належати root.
- Під час процесу завантаження пакет має бути підготовлений у захищеному місці не для root:
/Library/StagedExtensions
(вимагає грантуcom.apple.rootless.storage.KernelExtensionManagement
). - Нарешті, при спробі завантажити його користувач отримає запит на підтвердження і, якщо підтвердить, комп'ютер має бути перезапущений для завантаження.
Процес завантаження
У Catalina це було так: цікаво, що процес верифікації відбувається в userland. Проте лише застосунки з грантом com.apple.private.security.kext-management
можуть запитати ядро про завантаження розширення: kextcache
, kextload
, kextutil
, kextd
, syspolicyd
kextutil
cli запускає процес верифікації для завантаження розширення
- Він буде спілкуватися з
kextd
через Mach service.
kextd
перевірятиме кілька речей, наприклад підпис
- Він звертається до
syspolicyd
щоб перевірити, чи можна завантажити розширення.
syspolicyd
спрямує запит користувачу, якщо розширення не було раніше завантажено.
syspolicyd
повідомить результатkextd
kextd
нарешті зможе запросити ядро на завантаження розширення
Якщо kextd
недоступний, kextutil
може виконати ті ж перевірки.
Переліки та управління (завантажені kext)
kextstat
був історичним інструментом, але він deprecated у новіших релізах macOS. Сучасний інтерфейс — kmutil
:
# 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
Старіший синтаксис все ще доступний для довідки:
# (Deprecated) Get loaded kernel extensions
kextstat
# (Deprecated) Get dependencies of the kext number 22
kextstat | grep " 22 " | cut -c2-5,50- | cut -d '(' -f1
kmutil inspect
також можна використати для вивантаження вмісту Kernel Collection (KC) або для перевірки, що kext задовольняє всі залежності символів:
# 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
Навіть якщо kernel extensions очікуються в /System/Library/Extensions/
, якщо ви перейдете в цю папку ви не знайдете жодного бінарного файлу. Це через kernelcache, і щоб виконати реверс-інжиніринг одного .kext
вам потрібно знайти спосіб його отримати.
The kernelcache — це попередньо скомпільована та попередньо зв'язана версія XNU, разом з необхідними пристроєвими drivers та kernel extensions. Він зберігається в стисненому форматі й розпаковується в пам'ять під час завантаження. Kernelcache забезпечує швидше завантаження системи, оскільки має готову для запуску версію ядра та критично важливі драйвери, зменшуючи час і ресурси, які інакше були б витрачені на динамічне завантаження та зв'язування цих компонентів під час завантаження.
Головні переваги kernelcache — швидкість завантаження та те, що всі модулі попередньо зв'язані (немає затримок на завантаження). І після того, як усі модулі попередньо зв'язані, KXLD можна видалити з пам'яті, тож XNU не зможе завантажувати нові KEXTs.
tip
Інструмент https://github.com/dhinakg/aeota розшифровує AEA (Apple Encrypted Archive / AEA asset) контейнер — зашифрований формат контейнера, який Apple використовує для OTA assets та деяких частин IPSW — і може створити базовий .dmg/asset архів, який ви потім можете витягти за допомогою наданих інструментів aastuff.
Local Kerlnelcache
В iOS він розташований у /System/Library/Caches/com.apple.kernelcaches/kernelcache
; в macOS ви можете знайти його командою: find / -name "kernelcache" 2>/dev/null
В моєму випадку в macOS я знайшов його у:
/System/Volumes/Preboot/1BAEB4B5-180B-4C46-BD53-51152B7D92DA/boot/DAD35E7BC0CDA79634C20BD1BD80678DFB510B2AAD3D25C1228BB34BCD0A711529D3D571C93E29E1D0C1264750FA043F/System/Library/Caches/com.apple.kernelcaches/kernelcache
Find also here the kernelcache of version 14 with symbols.
IMG4 / BVX2 (LZFSE) compressed
Формат файлу IMG4 — це контейнерний формат, який Apple використовує в своїх пристроях iOS та macOS для безпечного збереження та перевірки firmware компонентів (наприклад, kernelcache). Формат IMG4 містить заголовок і кілька тегів, які інкапсулюють різні частини даних, включаючи фактичний payload (наприклад ядро або bootloader), підпис і набір властивостей манифесту. Формат підтримує криптографічну перевірку, дозволяючи пристрою підтвердити автентичність і цілісність firmware-компонента перед його виконанням.
Зазвичай він складається з таких компонентів:
- Payload (IM4P):
- Зазвичай стиснений (LZFSE4, LZSS, …)
- Опційно зашифрований
- Manifest (IM4M):
- Містить Signature
- Додатковий Key/Value словник
- Restore Info (IM4R):
- Також відомий як APNonce
- Запобігає повторному відтворенню деяких оновлень
- OPTIONAL: Зазвичай це відсутнє
Decompress the Kernelcache:
# img4tool (https://github.com/tihmstar/img4tool)
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
# pyimg4 (https://github.com/m1stadev/PyIMG4)
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
# imjtool (https://newandroidbook.com/tools/imjtool.html)
imjtool _img_name_ [extract]
# disarm (you can use it directly on the IMG4 file) - [https://newandroidbook.com/tools/disarm.html](https://newandroidbook.com/tools/disarm.html)
disarm -L kernelcache.release.v57 # From unzip ipsw
# disamer (extract specific parts, e.g. filesets) - [https://newandroidbook.com/tools/disarm.html](https://newandroidbook.com/tools/disarm.html)
disarm -e filesets kernelcache.release.d23
Disarm: символи для ядра
Disarm
дозволяє symbolicate функції з kernelcache за допомогою matchers.
Ці matchers — прості правила-патерни (рядки тексту), які вказують disarm, як розпізнати й auto-symbolicate функції, аргументи та panic/log strings у бінарному файлі.
Тобто ви вказуєте рядок, який використовує функція, і disarm знайде його та symbolicate it.
You can find some `xnu.matchers` in [https://newosxbook.com/tools/disarm.html](https://newosxbook.com/tools/disarm.html) in the **`Matchers`** section. You can also create your own matchers.
Перейдіть до /tmp/extracted, куди disarm розпакував filesets
disarm -e filesets kernelcache.release.d23 # Always extract to /tmp/extracted cd /tmp/extracted JMATCHERS=xnu.matchers disarm --analyze kernel.rebuilt # Note that xnu.matchers is actually a file with the matchers
### Download
An **IPSW (iPhone/iPad Software)** is Apple’s firmware package format used for device restores, updates, and full firmware bundles. Among other things, it contains the **kernelcache**.
- [**KernelDebugKit Github**](https://github.com/dortania/KdkSupportPkg/releases)
In [https://github.com/dortania/KdkSupportPkg/releases](https://github.com/dortania/KdkSupportPkg/releases) it's possible to find all the kernel debug kits. You can download it, mount it, open it with [Suspicious Package](https://www.mothersruin.com/software/SuspiciousPackage/get.html) tool, access the **`.kext`** folder and **extract it**.
Check it for symbols with:
nm -a ~/Downloads/Sandbox.kext/Contents/MacOS/Sandbox | wc -l
- [**theapplewiki.com**](https://theapplewiki.com/wiki/Firmware/Mac/14.x)**,** [**ipsw.me**](https://ipsw.me/)**,** [**theiphonewiki.com**](https://www.theiphonewiki.com/)
Sometime Apple releases **kernelcache** with **symbols**. You can download some firmwares with symbols by following links on those pages. The firmwares will contain the **kernelcache** among other files.
To **extract** the kernel cache you can do:
Встановити ipsw tool
brew install blacktop/tap/ipsw
Витягнути лише kernelcache з IPSW
ipsw extract --kernel /path/to/YourFirmware.ipsw -o out/
Ви повинні отримати щось на кшталт:
out/Firmware/kernelcache.release.iPhoneXX
або IMG4 payload: out/Firmware/kernelcache.release.iPhoneXX.im4p
Якщо ви отримаєте IMG4 payload:
ipsw img4 im4p extract out/Firmware/kernelcache*.im4p -o kcache.raw
Another option to **extract** the files start by changing the extension from `.ipsw` to `.zip` and **unzip** it.
After extracting the firmware you will get a file like: **`kernelcache.release.iphone14`**. It's in **IMG4** format, you can extract the interesting info with:
[**pyimg4**](https://github.com/m1stadev/PyIMG4)**:**
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
[**img4tool**](https://github.com/tihmstar/img4tool)**:**
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
[**img4tool**](https://github.com/tihmstar/img4tool)**:**
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
### Inspecting kernelcache
Check if the kernelcache has symbols with
nm -a kernelcache.release.iphone14.e | wc -l
With this we can now **extract all the extensions** or the **one you are interested in:**
Перелічити всі розширення
kextex -l kernelcache.release.iphone14.e
Витягти com.apple.security.sandbox
kextex -e com.apple.security.sandbox kernelcache.release.iphone14.e
Витягти всі
kextex_all kernelcache.release.iphone14.e
Перевірити розширення на наявність символів
nm -a binaries/com.apple.security.sandbox | wc -l
## Recent vulnerabilities & exploitation techniques
| Year | CVE | Summary |
|------|-----|---------|
| 2024 | **CVE-2024-44243** | Logic flaw in **`storagekitd`** allowed a *root* attacker to register a malicious file-system bundle that ultimately loaded an **unsigned kext**, **bypassing System Integrity Protection (SIP)** and enabling persistent rootkits. Patched in macOS 14.2 / 15.2. |
| 2021 | **CVE-2021-30892** (*Shrootless*) | Installation daemon with the entitlement `com.apple.rootless.install` could be abused to execute arbitrary post-install scripts, disable SIP and load arbitrary kexts. |
**Take-aways for red-teamers**
1. **Look for entitled daemons (`codesign -dvv /path/bin | grep entitlements`) that interact with Disk Arbitration, Installer or Kext Management.**
2. **Abusing SIP bypasses almost always grants the ability to load a kext → kernel code execution**.
**Defensive tips**
*Keep SIP enabled*, monitor for `kmutil load`/`kmutil create -n aux` invocations coming from non-Apple binaries and alert on any write to `/Library/Extensions`. Endpoint Security events `ES_EVENT_TYPE_NOTIFY_KEXTLOAD` provide near real-time visibility.
## Debugging macOS kernel & kexts
Apple’s recommended workflow is to build a **Kernel Debug Kit (KDK)** that matches the running build and then attach **LLDB** over a **KDP (Kernel Debugging Protocol)** network session.
### One-shot local debug of a panic
Створіть символікаційний пакет для останнього panic
sudo kdpwrit dump latest.kcdata kmutil analyze-panic latest.kcdata -o ~/panic_report.txt
### Live remote debugging from another Mac
1. Download + install the exact **KDK** version for the target machine.
2. Connect the target Mac and the host Mac with a **USB-C or Thunderbolt cable**.
3. On the **target**:
sudo nvram boot-args="debug=0x100 kdp_match_name=macbook-target" reboot
4. On the **host**:
lldb (lldb) kdp-remote "udp://macbook-target" (lldb) bt # get backtrace in kernel context
### Attaching LLDB to a specific loaded kext
Визначити адресу завантаження kext
ADDR=$(kmutil showloaded --bundle-identifier com.example.driver | awk '{print $4}')
Приєднатися
sudo lldb -n kernel_task -o "target modules load --file /Library/Extensions/Example.kext/Contents/MacOS/Example --slide $ADDR"