macOS IOKit
Reading time: 8 minutes
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Osnovne informacije
I/O Kit je open-source, objektno orijentisan framework za drajvere uređaja u XNU kernelu, koji upravlja dinamički učitanim drajverima uređaja. Omogućava dodavanje modularnog koda u kernel u hodu, podržavajući raznovrsni hardver.
IOKit drajveri će u osnovi izvoziti funkcije iz kernela. Ovi parametri funkcija su preddefinisani i verifikovani. Štaviše, slično XPC-u, IOKit je samo još jedan sloj iznad Mach poruka.
IOKit XNU kernel kod je open-source od strane Apple-a na https://github.com/apple-oss-distributions/xnu/tree/main/iokit. Takođe, komponente IOKit korisničkog prostora su takođe open-source https://github.com/opensource-apple/IOKitUser.
Međutim, nema IOKit drajvera koji su open-source. U svakom slučaju, s vremena na vreme, objavljivanje drajvera može doći sa simbolima koji olakšavaju njegovo debagovanje. Proverite kako da dobijete ekstenzije drajvera iz firmvera ovde.
Napisano je u C++. Možete dobiti demanglovane C++ simbole sa:
# Get demangled symbols
nm -C com.apple.driver.AppleJPEGDriver
# Demangled symbols from stdin
c++filt
__ZN16IOUserClient202222dispatchExternalMethodEjP31IOExternalMethodArgumentsOpaquePK28IOExternalMethodDispatch2022mP8OSObjectPv
IOUserClient2022::dispatchExternalMethod(unsigned int, IOExternalMethodArgumentsOpaque*, IOExternalMethodDispatch2022 const*, unsigned long, OSObject*, void*)
caution
IOKit izložene funkcije mogu izvršiti dodatne bezbednosne provere kada klijent pokuša da pozove funkciju, ali imajte na umu da su aplikacije obično ograničene od sandbox-a sa kojim IOKit funkcije mogu da interaguju.
Drajveri
U macOS-u se nalaze u:
/System/Library/Extensions
- KEXT datoteke ugrađene u OS X operativni sistem.
/Library/Extensions
- KEXT datoteke instalirane od strane softvera trećih strana
U iOS-u se nalaze u:
/System/Library/Extensions
#Use kextstat to print the loaded drivers
kextstat
Executing: /usr/bin/kmutil showloaded
No variant specified, falling back to release
Index Refs Address Size Wired Name (Version) UUID <Linked Against>
1 142 0 0 0 com.apple.kpi.bsd (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
2 11 0 0 0 com.apple.kpi.dsep (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
3 170 0 0 0 com.apple.kpi.iokit (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
4 0 0 0 0 com.apple.kpi.kasan (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
5 175 0 0 0 com.apple.kpi.libkern (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
6 154 0 0 0 com.apple.kpi.mach (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
7 88 0 0 0 com.apple.kpi.private (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
8 106 0 0 0 com.apple.kpi.unsupported (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
9 2 0xffffff8003317000 0xe000 0xe000 com.apple.kec.Libm (1) 6C1342CC-1D74-3D0F-BC43-97D5AD38200A <5>
10 12 0xffffff8003544000 0x92000 0x92000 com.apple.kec.corecrypto (11.1) F5F1255F-6552-3CF4-A9DB-D60EFDEB4A9A <8 7 6 5 3 1>
Do broja 9, navedeni drajveri su učitani na adresi 0. To znači da to nisu pravi drajveri već deo kernela i ne mogu se ukloniti.
Da biste pronašli specifične ekstenzije, možete koristiti:
kextfind -bundle-id com.apple.iokit.IOReportFamily #Search by full bundle-id
kextfind -bundle-id -substring IOR #Search by substring in bundle-id
Da biste učitali i ispraznili kernel ekstenzije, uradite:
kextload com.apple.iokit.IOReportFamily
kextunload com.apple.iokit.IOReportFamily
IORegistry
IORegistry je ključni deo IOKit okvira u macOS i iOS koji služi kao baza podataka za predstavljanje hardverske konfiguracije i stanja sistema. To je hijerarhijska kolekcija objekata koja predstavlja sav hardver i drajvere učitane na sistemu, i njihove međusobne odnose.
Možete dobiti IORegistry koristeći cli ioreg
da biste ga pregledali iz konzole (posebno korisno za iOS).
ioreg -l #List all
ioreg -w 0 #Not cut lines
ioreg -p <plane> #Check other plane
Možete preuzeti IORegistryExplorer
iz Xcode Additional Tools sa https://developer.apple.com/download/all/ i pregledati macOS IORegistry kroz grafički interfejs.
.png)
U IORegistryExplorer, "planovi" se koriste za organizovanje i prikazivanje odnosa između različitih objekata u IORegistry. Svaki plan predstavlja specifičnu vrstu odnosa ili poseban pogled na hardversku i drajversku konfiguraciju sistema. Evo nekih od uobičajenih planova koje možete sresti u IORegistryExplorer:
- IOService Plane: Ovo je najopštiji plan, koji prikazuje servisne objekte koji predstavljaju drajvere i nubs (kanale komunikacije između drajvera). Prikazuje odnose između provajdera i klijenata ovih objekata.
- IODeviceTree Plane: Ovaj plan predstavlja fizičke veze između uređaja dok su priključeni na sistem. Često se koristi za vizualizaciju hijerarhije uređaja povezanih putem magistrala kao što su USB ili PCI.
- IOPower Plane: Prikazuje objekte i njihove odnose u smislu upravljanja energijom. Može pokazati koji objekti utiču na stanje napajanja drugih, što je korisno za otklanjanje grešaka povezanih sa energijom.
- IOUSB Plane: Specifično fokusiran na USB uređaje i njihove odnose, prikazuje hijerarhiju USB hubova i povezanih uređaja.
- IOAudio Plane: Ovaj plan je za predstavljanje audio uređaja i njihovih odnosa unutar sistema.
- ...
Primer koda za Driver Comm
Sledeći kod se povezuje na IOKit servis "YourServiceNameHere"
i poziva funkciju unutar selektora 0. Za to:
- prvo poziva
IOServiceMatching
iIOServiceGetMatchingServices
da dobije servis. - Zatim uspostavlja vezu pozivajući
IOServiceOpen
. - I konačno poziva funkciju sa
IOConnectCallScalarMethod
označavajući selektor 0 (selektor je broj koji je funkciji koju želite da pozovete dodeljen).
#import <Foundation/Foundation.h>
#import <IOKit/IOKitLib.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// Get a reference to the service using its name
CFMutableDictionaryRef matchingDict = IOServiceMatching("YourServiceNameHere");
if (matchingDict == NULL) {
NSLog(@"Failed to create matching dictionary");
return -1;
}
// Obtain an iterator over all matching services
io_iterator_t iter;
kern_return_t kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
if (kr != KERN_SUCCESS) {
NSLog(@"Failed to get matching services");
return -1;
}
// Get a reference to the first service (assuming it exists)
io_service_t service = IOIteratorNext(iter);
if (!service) {
NSLog(@"No matching service found");
IOObjectRelease(iter);
return -1;
}
// Open a connection to the service
io_connect_t connect;
kr = IOServiceOpen(service, mach_task_self(), 0, &connect);
if (kr != KERN_SUCCESS) {
NSLog(@"Failed to open service");
IOObjectRelease(service);
IOObjectRelease(iter);
return -1;
}
// Call a method on the service
// Assume the method has a selector of 0, and takes no arguments
kr = IOConnectCallScalarMethod(connect, 0, NULL, 0, NULL, NULL);
if (kr != KERN_SUCCESS) {
NSLog(@"Failed to call method");
}
// Cleanup
IOServiceClose(connect);
IOObjectRelease(service);
IOObjectRelease(iter);
}
return 0;
}
Postoje druge funkcije koje se mogu koristiti za pozivanje IOKit funkcija pored IOConnectCallScalarMethod
kao što su IOConnectCallMethod
, IOConnectCallStructMethod
...
Reverzno inženjerstvo ulazne tačke drajvera
Možete ih dobiti, na primer, iz firmware slike (ipsw). Zatim, učitajte je u svoj omiljeni dekompajler.
Možete početi dekompilaciju funkcije externalMethod
jer je to funkcija drajvera koja će primati poziv i pozivati odgovarajuću funkciju:
.png)
.png)
Ta strašna pozivna funkcija demanglovana znači:
IOUserClient2022::dispatchExternalMethod(unsigned int, IOExternalMethodArgumentsOpaque*, IOExternalMethodDispatch2022 const*, unsigned long, OSObject*, void*)
Napomena kako u prethodnoj definiciji nedostaje self
parametar, dobra definicija bi bila:
IOUserClient2022::dispatchExternalMethod(self, unsigned int, IOExternalMethodArgumentsOpaque*, IOExternalMethodDispatch2022 const*, unsigned long, OSObject*, void*)
Zapravo, pravu definiciju možete pronaći na https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/Kernel/IOUserClient.cpp#L6388:
IOUserClient2022::dispatchExternalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque *arguments,
const IOExternalMethodDispatch2022 dispatchArray[], size_t dispatchArrayCount,
OSObject * target, void * reference)
Sa ovom informacijom možete prepraviti Ctrl+Desno -> Edit function signature
i postaviti poznate tipove:
.png)
Novi dekompilirani kod će izgledati ovako:
.png)
Za sledeći korak potrebno je definisati IOExternalMethodDispatch2022
strukturu. Ona je otvorenog koda na https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/IOKit/IOUserClient.h#L168-L176, možete je definisati:
.png)
Sada, prateći (IOExternalMethodDispatch2022 *)&sIOExternalMethodArray
možete videti mnogo podataka:
.png)
Promenite Tip Podataka u IOExternalMethodDispatch2022:
.png)
posle promene:
.png)
I kao što sada znamo, imamo niz od 7 elemenata (proverite konačni dekompilirani kod), kliknite da kreirate niz od 7 elemenata:
.png)
Nakon što je niz kreiran, možete videti sve eksportovane funkcije:
.png)
tip
Ako se sećate, da pozovete eksportovanu funkciju iz korisničkog prostora, ne treba da pozivate ime funkcije, već broj selektora. Ovde možete videti da je selektor 0 funkcija initializeDecoder
, selektor 1 je startDecoder
, selektor 2 initializeEncoder
...
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.