macOS IOKit
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 馃挰 Discord group or the telegram group or follow us on Twitter 馃惁 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Informaci贸n B谩sica
El I/O Kit es un framework de controladores de dispositivos de c贸digo abierto y orientado a objetos en el n煤cleo XNU, que maneja controladores de dispositivos cargados din谩micamente. Permite que se agregue c贸digo modular al n煤cleo sobre la marcha, soportando hardware diverso.
Los controladores de IOKit b谩sicamente exportan funciones del n煤cleo. Estos par谩metros de funci贸n son predefinidos y son verificados. Adem谩s, similar a XPC, IOKit es solo otra capa sobre los mensajes de Mach.
El c贸digo del n煤cleo IOKit XNU es de c贸digo abierto por Apple en https://github.com/apple-oss-distributions/xnu/tree/main/iokit. Adem谩s, los componentes de IOKit en el espacio de usuario tambi茅n son de c贸digo abierto https://github.com/opensource-apple/IOKitUser.
Sin embargo, ning煤n controlador de IOKit es de c贸digo abierto. De todos modos, de vez en cuando, un lanzamiento de un controlador puede venir con s铆mbolos que facilitan su depuraci贸n. Consulta c贸mo obtener las extensiones del controlador del firmware aqu铆.
Est谩 escrito en C++. Puedes obtener s铆mbolos C++ demangled con:
# 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 funciones expuestas podr铆an realizar verificaciones de seguridad adicionales cuando un cliente intenta llamar a una funci贸n, pero ten en cuenta que las aplicaciones suelen estar limitadas por el sandbox con el que pueden interactuar las funciones de IOKit.
Controladores
En macOS se encuentran en:
/System/Library/Extensions
- Archivos KEXT integrados en el sistema operativo OS X.
/Library/Extensions
- Archivos KEXT instalados por software de terceros
En iOS se encuentran en:
/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>
Hasta el n煤mero 9, los controladores listados est谩n cargados en la direcci贸n 0. Esto significa que no son controladores reales, sino parte del n煤cleo y no se pueden descargar.
Para encontrar extensiones espec铆ficas, puedes usar:
kextfind -bundle-id com.apple.iokit.IOReportFamily #Search by full bundle-id
kextfind -bundle-id -substring IOR #Search by substring in bundle-id
Para cargar y descargar extensiones del kernel, haz lo siguiente:
kextload com.apple.iokit.IOReportFamily
kextunload com.apple.iokit.IOReportFamily
IORegistry
El IORegistry es una parte crucial del marco IOKit en macOS e iOS que sirve como una base de datos para representar la configuraci贸n y el estado del hardware del sistema. Es una colecci贸n jer谩rquica de objetos que representan todo el hardware y los controladores cargados en el sistema, y sus relaciones entre s铆.
Puedes obtener el IORegistry usando el cli ioreg
para inspeccionarlo desde la consola (especialmente 煤til para iOS).
ioreg -l #List all
ioreg -w 0 #Not cut lines
ioreg -p <plane> #Check other plane
Podr铆as descargar IORegistryExplorer
de Xcode Additional Tools desde https://developer.apple.com/download/all/ e inspeccionar el macOS IORegistry a trav茅s de una interfaz gr谩fica.
En IORegistryExplorer, "planes" se utilizan para organizar y mostrar las relaciones entre diferentes objetos en el IORegistry. Cada plano representa un tipo espec铆fico de relaci贸n o una vista particular de la configuraci贸n de hardware y controladores del sistema. Aqu铆 hay algunos de los planos comunes que podr铆as encontrar en IORegistryExplorer:
- IOService Plane: Este es el plano m谩s general, que muestra los objetos de servicio que representan controladores y nubs (canales de comunicaci贸n entre controladores). Muestra las relaciones proveedor-cliente entre estos objetos.
- IODeviceTree Plane: Este plano representa las conexiones f铆sicas entre dispositivos a medida que est谩n conectados al sistema. A menudo se utiliza para visualizar la jerarqu铆a de dispositivos conectados a trav茅s de buses como USB o PCI.
- IOPower Plane: Muestra objetos y sus relaciones en t茅rminos de gesti贸n de energ铆a. Puede mostrar qu茅 objetos est谩n afectando el estado de energ铆a de otros, 煤til para depurar problemas relacionados con la energ铆a.
- IOUSB Plane: Enfocado espec铆ficamente en dispositivos USB y sus relaciones, mostrando la jerarqu铆a de hubs USB y dispositivos conectados.
- IOAudio Plane: Este plano es para representar dispositivos de audio y sus relaciones dentro del sistema.
- ...
Ejemplo de C贸digo de Comunicaci贸n de Controlador
El siguiente c贸digo se conecta al servicio de IOKit "YourServiceNameHere"
y llama a la funci贸n dentro del selector 0. Para ello:
- primero llama a
IOServiceMatching
yIOServiceGetMatchingServices
para obtener el servicio. - Luego establece una conexi贸n llamando a
IOServiceOpen
. - Y finalmente llama a una funci贸n con
IOConnectCallScalarMethod
indicando el selector 0 (el selector es el n煤mero que se le ha asignado a la funci贸n que deseas llamar).
#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;
}
Hay otras funciones que se pueden usar para llamar a funciones de IOKit adem谩s de IOConnectCallScalarMethod
como IOConnectCallMethod
, IOConnectCallStructMethod
...
Invirtiendo el punto de entrada del controlador
Podr铆as obtener estos, por ejemplo, de una imagen de firmware (ipsw). Luego, c谩rgalo en tu desensamblador favorito.
Podr铆as comenzar a desensamblar la funci贸n externalMethod
ya que esta es la funci贸n del controlador que recibir谩 la llamada y llamar谩 a la funci贸n correcta:
Esa horrible llamada desmanglada significa:
IOUserClient2022::dispatchExternalMethod(unsigned int, IOExternalMethodArgumentsOpaque*, IOExternalMethodDispatch2022 const*, unsigned long, OSObject*, void*)
Nota c贸mo en la definici贸n anterior falta el par谩metro self
, la buena definici贸n ser铆a:
IOUserClient2022::dispatchExternalMethod(self, unsigned int, IOExternalMethodArgumentsOpaque*, IOExternalMethodDispatch2022 const*, unsigned long, OSObject*, void*)
En realidad, puedes encontrar la definici贸n real en 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)
Con esta informaci贸n, puedes reescribir Ctrl+Right -> Edit function signature
y establecer los tipos conocidos:
El nuevo c贸digo decompilado se ver谩 as铆:
Para el siguiente paso, necesitamos tener definida la estructura IOExternalMethodDispatch2022
. Es de c贸digo abierto en https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/IOKit/IOUserClient.h#L168-L176, podr铆as definirlo:
Ahora, siguiendo el (IOExternalMethodDispatch2022 *)&sIOExternalMethodArray
puedes ver muchos datos:
Cambia el tipo de dato a IOExternalMethodDispatch2022:
despu茅s del cambio:
Y como ahora sabemos que hay un array de 7 elementos (verifica el c贸digo decompilado final), haz clic para crear un array de 7 elementos:
Despu茅s de que se crea el array, puedes ver todas las funciones exportadas:
tip
Si recuerdas, para llamar a una funci贸n exportada desde el espacio de usuario, no necesitamos llamar al nombre de la funci贸n, sino al n煤mero de selector. Aqu铆 puedes ver que el selector 0 es la funci贸n initializeDecoder
, el selector 1 es startDecoder
, el selector 2 initializeEncoder
...
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 馃挰 Discord group or the telegram group or follow us on Twitter 馃惁 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.