215 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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 IOKit
{{#include ../../../banners/hacktricks-training.md}}
## Temel Bilgiler
I/O Kit, XNU çekirdeğinde **dinamik olarak yüklenen cihaz sürücüleri** ile ilgilenen açık kaynaklı, nesne yönelimli **cihaz sürücü çerçevesidir**. Farklı donanımları destekleyerek çekirdeğe anında modüler kod eklenmesine olanak tanır.
IOKit sürücüleri esasen **çekirdekten fonksiyonlar dışa aktarır**. Bu fonksiyon parametre **tipleri** **önceden tanımlıdır** ve doğrulanır. Ayrıca, XPC'ye benzer şekilde, IOKit sadece **Mach mesajlarının** üzerinde başka bir katmandır.
**IOKit XNU çekirdek kodu**, Apple tarafından [https://github.com/apple-oss-distributions/xnu/tree/main/iokit](https://github.com/apple-oss-distributions/xnu/tree/main/iokit) adresinde açık kaynak olarak yayınlanmıştır. Ayrıca, kullanıcı alanı IOKit bileşenleri de açık kaynak [https://github.com/opensource-apple/IOKitUser](https://github.com/opensource-apple/IOKitUser).
Ancak, **hiçbir IOKit sürücüsü**ık kaynak değildir. Yine de, zaman zaman bir sürücü sürümü, hata ayıklamayı kolaylaştıran sembollerle birlikte gelebilir. [**Firmware'den sürücü uzantılarını nasıl alacağınızı buradan kontrol edin**](#ipsw)**.**
**C++** ile yazılmıştır. Demangled C++ sembollerini almak için:
```bash
# 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 **açık fonksiyonlar** bir istemci bir fonksiyonu çağırmaya çalıştığında **ek güvenlik kontrolleri** gerçekleştirebilir, ancak uygulamaların genellikle etkileşimde bulunabilecekleri IOKit fonksiyonlarıısından **sandbox** ile **sınırlı** olduğunu unutmayın.
## Sürücüler
macOS'ta şunlarda bulunurlar:
- **`/System/Library/Extensions`**
- OS X işletim sistemine entegre edilmiş KEXT dosyaları.
- **`/Library/Extensions`**
- 3. parti yazılımlar tarafından yüklenen KEXT dosyaları
iOS'ta şunlarda bulunurlar:
- **`/System/Library/Extensions`**
```bash
#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 **0 adresinde yüklenmiştir**. Bu, bunların gerçek sürücüler olmadığı, ancak **çekirdek parçası oldukları ve boşaltılamayacakları** anlamına gelir.
Belirli uzantıları bulmak için şunları kullanabilirsiniz:
```bash
kextfind -bundle-id com.apple.iokit.IOReportFamily #Search by full bundle-id
kextfind -bundle-id -substring IOR #Search by substring in bundle-id
```
Kernel uzantılarını yüklemek ve kaldırmak için:
```bash
kextload com.apple.iokit.IOReportFamily
kextunload com.apple.iokit.IOReportFamily
```
## IORegistry
**IORegistry**, macOS ve iOS'taki IOKit çerçevesinin önemli bir parçasıdır ve sistemin donanım yapılandırmasını ve durumunu temsil eden bir veritabanı olarak hizmet eder. Bu, sistemde yüklü olan tüm donanım ve sürücüleri temsil eden **hiyerarşik bir nesne koleksiyonudur** ve bunların birbirleriyle olan ilişkilerini gösterir.
IORegistry'yi, konsoldan incelemek için cli **`ioreg`** kullanarak alabilirsiniz (özellikle iOS için faydalıdır).
```bash
ioreg -l #List all
ioreg -w 0 #Not cut lines
ioreg -p <plane> #Check other plane
```
**`IORegistryExplorer`**'ı **Xcode Ek Araçlar**'dan [**https://developer.apple.com/download/all/**](https://developer.apple.com/download/all/) indirip **macOS IORegistry**'ni **grafiksel** bir arayüz üzerinden inceleyebilirsiniz.
<figure><img src="../../../images/image (1167).png" alt="" width="563"><figcaption></figcaption></figure>
IORegistryExplorer'da, "düzlemler" IORegistry'deki farklı nesneler arasındaki ilişkileri düzenlemek ve görüntülemek için kullanılır. Her düzlem, belirli bir ilişki türünü veya sistemin donanım ve sürücü yapılandırmasının belirli bir görünümünü temsil eder. IORegistryExplorer'da karşılaşabileceğiniz bazı yaygın düzlemler şunlardır:
1. **IOService Düzlemi**: Bu, sürücüleri ve nubs'ları (sürücüler arasındaki iletişim kanalları) temsil eden hizmet nesnelerini görüntüleyen en genel düzlemdir. Bu nesneler arasındaki sağlayıcı-müşteri ilişkilerini gösterir.
2. **IODeviceTree Düzlemi**: Bu düzlem, cihazların sisteme bağlı olduğu fiziksel bağlantıları temsil eder. Genellikle USB veya PCI gibi bus'lar aracılığıyla bağlı cihazların hiyerarşisini görselleştirmek için kullanılır.
3. **IOPower Düzlemi**: Güç yönetimi açısından nesneleri ve ilişkilerini görüntüler. Hangi nesnelerin diğerlerinin güç durumunu etkilediğini gösterir, güçle ilgili sorunları gidermek için faydalıdır.
4. **IOUSB Düzlemi**: Özellikle USB cihazları ve bunların ilişkilerine odaklanır, USB hub'larının ve bağlı cihazların hiyerarşisini gösterir.
5. **IOAudio Düzlemi**: Bu düzlem, ses cihazlarını ve bunların sistem içindeki ilişkilerini temsil etmek için kullanılır.
6. ...
## Sürücü İletişim Kodu Örneği
Aşağıdaki kod, IOKit hizmetine `"YourServiceNameHere"` bağlanır ve seçici 0 içindeki fonksiyonu çağırır. Bunun için:
- Öncelikle **`IOServiceMatching`** ve **`IOServiceGetMatchingServices`** çağrılarak hizmet alınır.
- Ardından **`IOServiceOpen`** çağrılarak bir bağlantı kurulur.
- Son olarak, seçici 0 ile bir fonksiyon **`IOConnectCallScalarMethod`** ile çağrılır (seçici, çağırmak istediğiniz fonksiyona atanan numaradır).
```objectivec
#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;
}
```
Diğer **`IOConnectCallScalarMethod`** gibi IOKit fonksiyonlarını çağırmak için kullanılabilecek **diğer** fonksiyonlar vardır, örneğin **`IOConnectCallMethod`**, **`IOConnectCallStructMethod`**...
## Sürücü giriş noktasını tersine mühendislik
Bunları örneğin bir [**firmware image (ipsw)**](#ipsw) üzerinden elde edebilirsiniz. Ardından, bunu en sevdiğiniz dekompilerde yükleyin.
**`externalMethod`** fonksiyonunu decompile etmeye başlayabilirsiniz çünkü bu, çağrıyı alacak ve doğru fonksiyonu çağıracak olan 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 korkunç çağrı demagled, şunu ifade eder:
```cpp
IOUserClient2022::dispatchExternalMethod(unsigned int, IOExternalMethodArgumentsOpaque*, IOExternalMethodDispatch2022 const*, unsigned long, OSObject*, void*)
```
Not edin ki önceki tanımda **`self`** parametresi atlanmış, iyi bir tanım şöyle olmalıdır:
```cpp
IOUserClient2022::dispatchExternalMethod(self, unsigned int, IOExternalMethodArgumentsOpaque*, IOExternalMethodDispatch2022 const*, unsigned long, OSObject*, void*)
```
Aslında, gerçek tanımı [https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/Kernel/IOUserClient.cpp#L6388](https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/Kernel/IOUserClient.cpp#L6388) adresinde bulabilirsiniz:
```cpp
IOUserClient2022::dispatchExternalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque *arguments,
const IOExternalMethodDispatch2022 dispatchArray[], size_t dispatchArrayCount,
OSObject * target, void * reference)
```
Bu bilgiyle Ctrl+Right -> `Edit function signature` yazabilir ve bilinen türleri ayarlayabilirsiniz:
<figure><img src="../../../images/image (1174).png" alt=""><figcaption></figcaption></figure>
Yeni decompile edilmiş kod şöyle görünecek:
<figure><img src="../../../images/image (1175).png" alt=""><figcaption></figcaption></figure>
Bir sonraki adımda **`IOExternalMethodDispatch2022`** yapısını tanımlamamız gerekiyor. Bu yapı [https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/IOKit/IOUserClient.h#L168-L176](https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/IOKit/IOUserClient.h#L168-L176) adresinde açık kaynak olarak bulunmaktadır, bunu tanımlayabilirsiniz:
<figure><img src="../../../images/image (1170).png" alt=""><figcaption></figcaption></figure>
Şimdi, `(IOExternalMethodDispatch2022 *)&sIOExternalMethodArray` ifadesini takip ederek birçok veri görebilirsiniz:
<figure><img src="../../../images/image (1176).png" alt="" width="563"><figcaption></figcaption></figure>
Veri Türünü **`IOExternalMethodDispatch2022:`** olarak değiştirin:
<figure><img src="../../../images/image (1177).png" alt="" width="375"><figcaption></figcaption></figure>
Değişiklikten sonra:
<figure><img src="../../../images/image (1179).png" alt="" width="563"><figcaption></figcaption></figure>
Ve şimdi orada **7 elemanlı bir dizi** olduğunu biliyoruz (son decompile edilmiş kodu kontrol edin), 7 elemanlı bir dizi oluşturmak için tıklayın:
<figure><img src="../../../images/image (1180).png" alt="" width="563"><figcaption></figcaption></figure>
Dizi oluşturulduktan sonra, tüm dışa aktarılan fonksiyonları görebilirsiniz:
<figure><img src="../../../images/image (1181).png" alt=""><figcaption></figcaption></figure>
> [!TIP]
> Hatırlarsanız, kullanıcı alanından bir **dışa aktarılan** fonksiyonu **çağırmak** için fonksiyonun adını değil, **seçici numarasını** çağırmamız gerekiyor. Burada seçici **0** fonksiyonu **`initializeDecoder`**, seçici **1** **`startDecoder`**, seçici **2** **`initializeEncoder`**...
{{#include ../../../banners/hacktricks-training.md}}