macOS Kernel Extensions & Debugging
Reading time: 9 minutes
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
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:
- Uruchomienia ponownego w Recovery → Startup Security Utility.
- Wybrania Reduced Security i zaznaczenia „Zezwól użytkownikowi na zarządzanie rozszerzeniami jądra od zidentyfikowanych deweloperów”.
- 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:
.png)
- 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 przyznaniacom.apple.rootless.storage.KernelExtensionManagement
). - Na koniec, podczas próby załadowania, użytkownik otrzyma prośbę o potwierdzenie 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
kextutil
cli rozpoczyna proces weryfikacji ładowania rozszerzenia
- Będzie komunikować się z
kextd
, wysyłając za pomocą usługi Mach.
kextd
sprawdzi kilka rzeczy, takich jak podpis
- Będzie komunikować się z
syspolicyd
, aby sprawdzić, czy rozszerzenie może być załadowane.
syspolicyd
poprosi użytkownika, jeśli rozszerzenie nie zostało wcześniej załadowane.
syspolicyd
przekaże wynik dokextd
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
:
# 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:
# (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:
# 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:
# 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
W 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, uzyskać dostęp do folderu .kext
i wyodrębnić go.
Sprawdź to pod kątem symboli za pomocą:
nm -a ~/Downloads/Sandbox.kext/Contents/MacOS/Sandbox | wc -l
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 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
Inspekcja kernelcache
Sprawdź, czy kernelcache ma symbole z
nm -a kernelcache.release.iphone14.e | wc -l
Dzięki temu możemy teraz wyodrębnić wszystkie rozszerzenia lub to, które Cię interesuje:
# 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
- Szukaj demonów z uprawnieniami (
codesign -dvv /path/bin | grep entitlements
), które współdziałają z Disk Arbitration, Installer lub Kext Management. - 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
# 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
- Pobierz i zainstaluj dokładną wersję KDK dla docelowej maszyny.
- Podłącz docelowego Maca i Maca gospodarza za pomocą kabelka USB-C lub Thunderbolt.
- Na docelowym:
sudo nvram boot-args="debug=0x100 kdp_match_name=macbook-target"
reboot
- Na hoście:
lldb
(lldb) kdp-remote "udp://macbook-target"
(lldb) bt # get backtrace in kernel context
Podłączanie LLDB do konkretnego załadowanego kexta
# 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
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.