macOS IOKit
Tip
AWS Hacking’i öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking’i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
Temel Bilgiler
I/O Kit, XNU kernel içinde açık kaynaklı, nesne yönelimli bir device-driver framework olup dynamically loaded device drivers’ı yönetir. Çeşitli donanımları destekleyerek çekirdeğe modüler kodun anında eklenmesine olanak tanır.
IOKit sürücüleri temelde çekirdekten export functions from the kernel sağlar. Bu fonksiyon parametre types önceden predefined olarak belirlenir ve doğrulanır. Ayrıca, XPC’ye benzer şekilde IOKit, Mach mesajlarının top of Mach messages üzerinde bir başka katmandır.
IOKit XNU kernel code Apple tarafından şu adreste açık kaynak kodlu olarak yayımlandı: https://github.com/apple-oss-distributions/xnu/tree/main/iokit. Ayrıca, kullanıcı alanı IOKit bileşenleri de açık kaynaklıdır: https://github.com/opensource-apple/IOKitUser.
Ancak, no IOKit drivers açık kaynaklı değildir. Yine de zaman zaman bir sürücü sürümü, debug etmeyi kolaylaştıran sembollerle birlikte gelebilir. Sürücü uzantılarını firmware’den nasıl get the driver extensions from the firmware here öğrenebileceğinizi kontrol edin.
Bu C++ ile yazılmıştır. Demangled C++ sembollerini şu şekilde elde edebilirsiniz:
# 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 exposed functions bir istemci bir fonksiyonu çağırmaya çalıştığında ek güvenlik kontrolleri uygulayabilir; ancak uygulamaların genellikle hangi IOKit fonksiyonlarıyla etkileşime girebilecekleri konusunda sandbox ile sınırlı olduğunu unutmayın.
Sürücüler
macOS’ta şu konumlarda bulunurlar:
/System/Library/Extensions- OS X işletim sistemine entegre KEXT dosyaları.
/Library/Extensions-
- taraf yazılımlar tarafından yüklenen KEXT dosyaları
iOS’ta şu konumda bulunurlar:
/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>
9’a kadar listelenen sürücüler adres 0’da yüklenmiştir. Bu, bunların gerçek sürücüler olmadığı, aksine kernel’in bir parçası oldukları ve kaldırılamayacakları anlamına gelir.
Belirli uzantıları bulmak için şunu kullanabilirsiniz:
kextfind -bundle-id com.apple.iokit.IOReportFamily #Search by full bundle-id
kextfind -bundle-id -substring IOR #Search by substring in bundle-id
Kernel extensions yüklemek ve kaldırmak için:
kextload com.apple.iokit.IOReportFamily
kextunload com.apple.iokit.IOReportFamily
IORegistry
The IORegistry macOS ve iOS içindeki IOKit framework’ünün önemli bir parçasıdır ve sistemin donanım yapılandırmasını ve durumunu temsil etmek için bir veritabanı görevi görür. Bu, sistemde yüklü tüm donanımı ve sürücüleri temsil eden nesnelerin hiyerarşik bir koleksiyonu ve bunların birbirleriyle olan ilişkileridir.
IORegistry’yi konsoldan incelemek için komut satırı aracı ioreg ile alabilirsiniz (özellikle iOS için kullanışlı).
ioreg -l #List all
ioreg -w 0 #Not cut lines
ioreg -p <plane> #Check other plane
You could download IORegistryExplorer from Xcode Additional Tools from https://developer.apple.com/download/all/ and inspect the macOS IORegistry through a graphical interface.
.png)
IORegistryExplorer’da, “planes” IORegistry içindeki farklı nesneler arasındaki ilişkileri düzenlemek ve görüntülemek için kullanılır. Her plane, belirli bir ilişki türünü veya sistemin donanım ve driver yapılandırmasının belirli bir görünümünü temsil eder. İşte IORegistryExplorer’da karşılaşabileceğiniz bazı yaygın plane’ler:
- IOService Plane: Bu en genel plandır; driver’ları ve nubs (driver’lar arasındaki iletişim kanalları) temsil eden servis nesnelerini gösterir. Bu nesneler arasındaki provider-client ilişkilerini gösterir.
- IODeviceTree Plane: Bu plane, aygıtlar sisteme bağlandıkça oluşan fiziksel bağlantıları temsil eder. Genellikle USB veya PCI gibi bus’lar üzerinden bağlı aygıtların hiyerarşisini görselleştirmek için kullanılır.
- IOPower Plane: Nesneleri ve bunların güç yönetimi bağlamındaki ilişkilerini gösterir. Hangi nesnelerin diğerlerinin güç durumunu etkilediğini göstererek güçle ilgili sorunların giderilmesinde faydalıdır.
- IOUSB Plane: Özellikle USB cihazlara ve bunların ilişkilerine odaklanır; USB hub’larının ve bağlı cihazların hiyerarşisini gösterir.
- IOAudio Plane: Bu plane, sistem içindeki ses cihazlarını ve bunların ilişkilerini temsil etmek içindir.
- …
Driver Comm Code Example
The following code connects to the IOKit service YourServiceNameHere and calls selector 0:
- It first calls
IOServiceMatchingandIOServiceGetMatchingServicesto get the service. - It then establishes a connection calling
IOServiceOpen. - And it finally calls a function with
IOConnectCallScalarMethodindicating the selector 0 (the selector is the number the function you want to call has assigned).
Kullanıcı uzayından bir driver selector çağrısı örneği
```objectivec #importint 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; }
</details>
IOKit fonksiyonlarını çağırmak için **`IOConnectCallScalarMethod`** dışında kullanılabilecek **diğer** fonksiyonlar da vardır; örneğin **`IOConnectCallMethod`**, **`IOConnectCallStructMethod`**...
## Sürücü entrypoint'ini tersine mühendislik
Bunları örneğin bir [**firmware image (ipsw)**](#ipsw) dosyasından elde edebilirsiniz. Ardından, favori decompiler'ınıza yükleyin.
**`externalMethod`** fonksiyonunun decompile'ına başlayabilirsiniz; bu, çağrıyı alacak ve doğru fonksiyonu çağıracak sürücü fonksiyonudur:
<figure><img src="../../../images/image (1168).png" alt="" width="315"><figcaption></figcaption></figure>
<figure><img src="../../../images/image (1169).png" alt=""><figcaption></figcaption></figure>
O berbat demagled çağrı şu anlama geliyor:
```cpp
IOUserClient2022::dispatchExternalMethod(unsigned int, IOExternalMethodArgumentsOpaque*, IOExternalMethodDispatch2022 const*, unsigned long, OSObject*, void*)
Önceki tanımda self parametresinin eksik olduğuna dikkat edin; doğru tanım şöyle olacaktır:
IOUserClient2022::dispatchExternalMethod(self, unsigned int, IOExternalMethodArgumentsOpaque*, IOExternalMethodDispatch2022 const*, unsigned long, OSObject*, void*)
Aslında gerçek tanımı şu adreste bulabilirsiniz 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)
With this info you can rewrite Ctrl+Right -> Edit function signature and set the known types:
.png)
The new decompiled code will look like:
.png)
For the next step we need to have defined the IOExternalMethodDispatch2022 struct. It’s opensource in https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/IOKit/IOUserClient.h#L168-L176, you could define it:
.png)
Now, following the (IOExternalMethodDispatch2022 *)&sIOExternalMethodArray you can see a lot of data:
.png)
Change the Data Type to IOExternalMethodDispatch2022:
.png)
after the change:
.png)
And as we now in there we have an array of 7 elements (check the final decompiled code), click to create an array of 7 elements:
.png)
After the array is created you can see all the exported functions:
.png)
Tip
If you remember, to call an exported function from user space we don’t need to call the name of the function, but the selector number. Here you can see that the selector 0 is the function
initializeDecoder, the selector 1 isstartDecoder, the selector 2initializeEncoder…
Yakın dönemdeki IOKit saldırı yüzeyi (2023–2025)
- IOHIDFamily üzerinden tuş vuruşlarını yakalama – CVE-2024-27799 (14.5) gösterdi ki izin verilmiş bir
IOHIDSystemclient’ı secure input olsa bile HID event’lerini alabiliyordu;externalMethodhandler’larının sadece user-client tipine değil, entitlements’ı da zorladığından emin olun. - IOGPUFamily bellek bozulması – CVE-2024-44197 ve CVE-2025-24257, yanlış biçimlendirilmiş değişken-uzunlukta veriyi GPU user client’larına ileten sandbox’lanmış uygulamalardan ulaşılabilen OOB yazma hatalarını düzeltti; tipik hata
IOConnectCallStructMethodargümanları etrafında zayıf sınır kontrolleridir. - Legacy tuş vuruşu izleme – CVE-2023-42891 (14.2) HID user client’larının hâlâ sandbox’tan kaçış vektörü olmaya devam ettiğini doğruladı; klavye/event kuyrukları açığa çıkan herhangi bir driver’ı fuzz’layın.
Hızlı triage & fuzzing ipuçları
- Bir user client için userland’den tüm external method’ları enumerate ederek bir fuzzer için seed oluşturun:
# list selectors for a service
python3 - <<'PY'
from ioreg import IORegistry
svc = 'IOHIDSystem'
reg = IORegistry()
obj = reg.get_service(svc)
for sel, name in obj.external_methods():
print(f"{sel:02d} {name}")
PY
- Tersine mühendislik yaparken
IOExternalMethodDispatch2022sayımlarına dikkat edin. Son CVE’lerde yaygın bir hata deseni, gerçekcopyinuzunluğuna kıyasla tutarsızstructureInputSize/structureOutputSizedeğerleri olup, bunun sonucundaIOConnectCallStructMethodiçinde heap OOB’ye yol açmasıdır. - Sandbox erişilebilirliği hâlâ entitlements’a bağlıdır. Bir hedef üzerinde zaman harcamadan önce, third‑party app’ten client’ın izinli olup olmadığını kontrol edin:
strings /System/Library/Extensions/IOHIDFamily.kext/Contents/MacOS/IOHIDFamily | \
grep -E "^com\.apple\.(driver|private)"
- GPU/iomfb hataları için, aşırı büyük dizileri
IOConnectCallMethodaracılığıyla göndermek genellikle hatalı sınır kontrollerini tetiklemek için yeterlidir. size confusion’ı tetiklemek için minimal harness (selector X):
uint8_t buf[0x1000];
size_t outSz = sizeof(buf);
IOConnectCallStructMethod(conn, X, buf, sizeof(buf), buf, &outSz);
Kaynaklar
- Apple Security Updates – macOS Sequoia 15.1 / Sonoma 14.7.1 (IOGPUFamily)
- Rapid7 – IOHIDFamily CVE-2024-27799 summary
- Apple Security Updates – macOS 13.6.1 (CVE-2023-42891 IOHIDFamily)
Tip
AWS Hacking’i öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking’i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.


