218 lines
13 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# macOS Kernel Extensions & Debugging
{{#include ../../../banners/hacktricks-training.md}}
## Podstawowe informacje
Rozszerzenia jądra (Kexts) to **pakiety** z rozszerzeniem **`.kext`**, które są **ładowane bezpośrednio do przestrzeni jądra macOS**, zapewniając dodatkową funkcjonalność głównemu systemowi operacyjnemu.
### Status deprecacji & DriverKit / System Extensions
Począwszy od **macOS Catalina (10.15)**, Apple oznaczyło większość przestarzałych KPI jako *deprecated* i wprowadziło frameworki **System Extensions & DriverKit**, które działają w **przestrzeni użytkownika**. Od **macOS Big Sur (11)** system operacyjny *odmówi załadowania* kextów firm trzecich, które polegają na przestarzałych KPI, chyba że maszyna jest uruchomiona w trybie **Reduced Security**. Na Apple Silicon, włączenie kextów dodatkowo wymaga od użytkownika:
1. Uruchomienia ponownego w **Recovery***Startup Security Utility*.
2. Wybrania **Reduced Security** i zaznaczenia **„Zezwól użytkownikowi na zarządzanie rozszerzeniami jądra od zidentyfikowanych deweloperów”**.
3. Ponownego uruchomienia i zatwierdzenia kextu w **Ustawienia systemowe → Prywatność i bezpieczeństwo**.
Sterowniki w przestrzeni użytkownika napisane z użyciem DriverKit/System Extensions znacznie **zmniejszają powierzchnię ataku**, ponieważ awarie lub uszkodzenia pamięci są ograniczone do procesów w piaskownicy, a nie przestrzeni jądra.
> 📝 Od macOS Sequoia (15) Apple całkowicie usunęło kilka przestarzałych KPI dotyczących sieci i USB jedynym rozwiązaniem zgodnym z przyszłością dla dostawców jest migracja do System Extensions.
### Wymagania
Oczywiście, jest to tak potężne, że **załadowanie rozszerzenia jądra** jest **skomplikowane**. Oto **wymagania**, które musi spełnić rozszerzenie jądra, aby mogło być załadowane:
- Podczas **wejścia w tryb odzyskiwania**, rozszerzenia jądra **muszą być dozwolone** do załadowania:
<figure><img src="../../../images/image (327).png" alt=""><figcaption></figcaption></figure>
- Rozszerzenie jądra musi być **podpisane certyfikatem podpisu kodu jądra**, który może być **przyznany tylko przez Apple**. Kto dokładnie przeanalizuje firmę i powody, dla których jest to potrzebne.
- Rozszerzenie jądra musi być również **notaryzowane**, Apple będzie mogło je sprawdzić pod kątem złośliwego oprogramowania.
- Następnie, użytkownik **root** jest tym, który może **załadować rozszerzenie jądra**, a pliki wewnątrz pakietu muszą **należeć do root**.
- Podczas procesu ładowania, pakiet musi być przygotowany w **chronionej lokalizacji nie-root**: `/Library/StagedExtensions` (wymaga przyznania `com.apple.rootless.storage.KernelExtensionManagement`).
- Na koniec, podczas próby załadowania, użytkownik [**otrzyma prośbę o potwierdzenie**](https://developer.apple.com/library/archive/technotes/tn2459/_index.html) i, jeśli zostanie zaakceptowana, komputer musi być **ponownie uruchomiony**, aby go załadować.
### Proces ładowania
W Catalina wyglądało to tak: Interesujące jest to, że proces **weryfikacji** odbywa się w **przestrzeni użytkownika**. Jednak tylko aplikacje z przyznaniem **`com.apple.private.security.kext-management`** mogą **zażądać od jądra załadowania rozszerzenia**: `kextcache`, `kextload`, `kextutil`, `kextd`, `syspolicyd`
1. **`kextutil`** cli **rozpoczyna** proces **weryfikacji** ładowania rozszerzenia
- Będzie komunikować się z **`kextd`**, wysyłając za pomocą **usługi Mach**.
2. **`kextd`** sprawdzi kilka rzeczy, takich jak **podpis**
- Będzie komunikować się z **`syspolicyd`**, aby **sprawdzić**, czy rozszerzenie może być **załadowane**.
3. **`syspolicyd`** **poprosi** **użytkownika**, jeśli rozszerzenie nie zostało wcześniej załadowane.
- **`syspolicyd`** przekaże wynik do **`kextd`**
4. **`kextd`** w końcu będzie mógł **powiedzieć jądru, aby załadowało** rozszerzenie
Jeśli **`kextd`** nie jest dostępny, **`kextutil`** może przeprowadzić te same kontrole.
### Enumeracja i zarządzanie (załadowane kexty)
`kextstat` był historycznym narzędziem, ale jest **deprecated** w ostatnich wydaniach macOS. Nowoczesnym interfejsem jest **`kmutil`**:
```bash
# 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
```
Starsza składnia jest nadal dostępna do odniesienia:
```bash
# (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` może być również wykorzystane do **zrzucenia zawartości Kolekcji Jądra (KC)** lub weryfikacji, że kext rozwiązuje wszystkie zależności symboli:
```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]
> Mimo że rozszerzenia jądra powinny znajdować się w `/System/Library/Extensions/`, jeśli przejdziesz do tego folderu, **nie znajdziesz żadnego pliku binarnego**. Dzieje się tak z powodu **kernelcache** i aby odwrócić jeden `.kext`, musisz znaleźć sposób na jego uzyskanie.
**Kernelcache** to **wstępnie skompilowana i wstępnie połączona wersja jądra XNU**, wraz z niezbędnymi **sterownikami** i **rozszerzeniami jądra**. Jest przechowywana w formacie **skompresowanym** i dekompresowana do pamięci podczas procesu uruchamiania. Kernelcache ułatwia **szybszy czas uruchamiania**, mając gotową do uruchomienia wersję jądra i kluczowych sterowników, co zmniejsza czas i zasoby, które w przeciwnym razie byłyby wydawane na dynamiczne ładowanie i łączenie tych komponentów w czasie uruchamiania.
### Lokalny Kernelcache
W iOS znajduje się w **`/System/Library/Caches/com.apple.kernelcaches/kernelcache`**, w macOS możesz go znaleźć za pomocą: **`find / -name "kernelcache" 2>/dev/null`** \
W moim przypadku w macOS znalazłem go w:
- `/System/Volumes/Preboot/1BAEB4B5-180B-4C46-BD53-51152B7D92DA/boot/DAD35E7BC0CDA79634C20BD1BD80678DFB510B2AAD3D25C1228BB34BCD0A711529D3D571C93E29E1D0C1264750FA043F/System/Library/Caches/com.apple.kernelcaches/kernelcache`
#### IMG4
Format pliku IMG4 to format kontenera używany przez Apple w swoich urządzeniach iOS i macOS do bezpiecznego **przechowywania i weryfikowania komponentów oprogramowania układowego** (takich jak **kernelcache**). Format IMG4 zawiera nagłówek i kilka tagów, które kapsułkują różne fragmenty danych, w tym rzeczywisty ładunek (tak jak jądro lub bootloader), podpis oraz zestaw właściwości manifestu. Format wspiera weryfikację kryptograficzną, pozwalając urządzeniu potwierdzić autentyczność i integralność komponentu oprogramowania układowego przed jego wykonaniem.
Zwykle składa się z następujących komponentów:
- **Payload (IM4P)**:
- Często skompresowany (LZFSE4, LZSS, …)
- Opcjonalnie szyfrowany
- **Manifest (IM4M)**:
- Zawiera podpis
- Dodatkowy słownik klucz/wartość
- **Restore Info (IM4R)**:
- Znany również jako APNonce
- Zapobiega powtarzaniu niektórych aktualizacji
- OPCJONALNE: Zwykle to nie jest znalezione
Rozpakuj Kernelcache:
```bash
# 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
```
### Pobierz
- [**KernelDebugKit Github**](https://github.com/dortania/KdkSupportPkg/releases)
W [https://github.com/dortania/KdkSupportPkg/releases](https://github.com/dortania/KdkSupportPkg/releases) można znaleźć wszystkie zestawy debugowania jądra. Możesz je pobrać, zamontować, otworzyć za pomocą narzędzia [Suspicious Package](https://www.mothersruin.com/software/SuspiciousPackage/get.html), uzyskać dostęp do folderu **`.kext`** i **wyodrębnić go**.
Sprawdź to pod kątem symboli za pomocą:
```bash
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/)
Czasami Apple wydaje **kernelcache** z **symbolami**. Możesz pobrać niektóre firmware z symbolami, korzystając z linków na tych stronach. Firmware będzie zawierać **kernelcache** oraz inne pliki.
Aby **wyodrębnić** pliki, zacznij od zmiany rozszerzenia z `.ipsw` na `.zip` i **rozpakuj** go.
Po wyodrębnieniu firmware otrzymasz plik taki jak: **`kernelcache.release.iphone14`**. Jest w formacie **IMG4**, możesz wyodrębnić interesujące informacje za pomocą:
[**pyimg4**](https://github.com/m1stadev/PyIMG4)**:**
```bash
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
```
[**img4tool**](https://github.com/tihmstar/img4tool)**:**
```bash
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
```
### Inspekcja kernelcache
Sprawdź, czy kernelcache ma symbole z
```bash
nm -a kernelcache.release.iphone14.e | wc -l
```
Dzięki temu możemy teraz **wyodrębnić wszystkie rozszerzenia** lub **to, które Cię interesuje:**
```bash
# List all extensions
kextex -l kernelcache.release.iphone14.e
## Extract com.apple.security.sandbox
kextex -e com.apple.security.sandbox kernelcache.release.iphone14.e
# Extract all
kextex_all kernelcache.release.iphone14.e
# Check the extension for symbols
nm -a binaries/com.apple.security.sandbox | wc -l
```
## Ostatnie luki i techniki eksploatacji
| Rok | CVE | Podsumowanie |
|------|-----|---------|
| 2024 | **CVE-2024-44243** | Błąd logiczny w **`storagekitd`** pozwalał atakującemu *root* zarejestrować złośliwy pakiet systemu plików, który ostatecznie ładował **niesigned kext**, **omijając Ochronę Integralności Systemu (SIP)** i umożliwiając trwałe rootkity. Naprawione w macOS 14.2 / 15.2. |
| 2021 | **CVE-2021-30892** (*Shrootless*) | Demon instalacyjny z uprawnieniem `com.apple.rootless.install` mógł być nadużyty do wykonywania dowolnych skryptów po instalacji, wyłączania SIP i ładowania dowolnych kextów. |
**Wnioski dla zespołów red-team**
1. **Szukaj demonów z uprawnieniami (`codesign -dvv /path/bin | grep entitlements`), które współdziałają z Disk Arbitration, Installer lub Kext Management.**
2. **Nadużywanie omijania SIP prawie zawsze daje możliwość ładowania kextu → wykonanie kodu jądra**.
**Wskazówki obronne**
*Zachowaj włączone SIP*, monitoruj wywołania `kmutil load`/`kmutil create -n aux` pochodzące z nie-Apple binariów i alarmuj o jakimkolwiek zapisie do `/Library/Extensions`. Wydarzenia bezpieczeństwa punktów końcowych `ES_EVENT_TYPE_NOTIFY_KEXTLOAD` zapewniają niemal rzeczywistą widoczność.
## Debugowanie jądra macOS i kextów
Zalecany przez Apple proces to zbudowanie **Kernel Debug Kit (KDK)**, który odpowiada działającej wersji, a następnie podłączenie **LLDB** przez sesję sieciową **KDP (Kernel Debugging Protocol)**.
### Jednorazowe lokalne debugowanie paniki
```bash
# Create a symbolication bundle for the latest panic
sudo kdpwrit dump latest.kcdata
kmutil analyze-panic latest.kcdata -o ~/panic_report.txt
```
### Zdalne debugowanie na żywo z innego Maca
1. Pobierz i zainstaluj dokładną wersję **KDK** dla docelowej maszyny.
2. Podłącz docelowego Maca i Maca gospodarza za pomocą **kabelka USB-C lub Thunderbolt**.
3. Na **docelowym**:
```bash
sudo nvram boot-args="debug=0x100 kdp_match_name=macbook-target"
reboot
```
4. Na **hoście**:
```bash
lldb
(lldb) kdp-remote "udp://macbook-target"
(lldb) bt # get backtrace in kernel context
```
### Podłączanie LLDB do konkretnego załadowanego kexta
```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 udostępnia tylko interfejs **tylko do odczytu**. Aby uzyskać dynamiczną instrumentację, będziesz musiał zpatchować binarny plik na dysku, wykorzystać **hooking funkcji jądra** (np. `mach_override`) lub przenieść sterownik do **hypervisora** w celu pełnego odczytu/zapisu.
## References
- DriverKit Security Apple Platform Security Guide
- Microsoft Security Blog *Analyzing CVE-2024-44243 SIP bypass*
{{#include ../../../banners/hacktricks-training.md}}