¿Trabajas en una empresa de ciberseguridad? ¿Quieres ver tu empresa anunciada en HackTricks? ¿O quieres tener acceso a la última versión de PEASS o descargar HackTricks en PDF? ¡Consulta los PLANES DE SUSCRIPCIÓN!
**IORegistry(입출력 레지스트리)**는 macOS와 iOS의 IOKit 프레임워크의 중요한 부분으로, 시스템의 하드웨어 구성 및 상태를 나타내는 데이터베이스 역할을 합니다. 이는 시스템에 로드된 모든 하드웨어 및 드라이버를 나타내는 객체들의 계층적인 컬렉션이며, 서로의 관계를 보여줍니다.
ioreg 명령어를 사용하여 CLI에서 IORegistry를 가져와 검사할 수 있습니다(특히 iOS에서 유용).
ioreg-l#List allioreg-w0#Not cut linesioreg-p<plane>#Check other plane
**IORegistryExplorer**을 Xcode 추가 도구에서 다운로드할 수 있으며, 그래픽 인터페이스를 통해 macOS IORegistry를 검사할 수 있습니다.
IORegistryExplorer에서 "planes"는 IORegistry의 다른 객체 간의 관계를 조직화하고 표시하는 데 사용됩니다. 각 plane은 시스템 하드웨어 및 드라이버 구성의 특정 보기나 특정 유형의 관계를 나타냅니다. 다음은 IORegistryExplorer에서 만날 수 있는 일반적인 plane 중 일부입니다:
IOService Plane: 이것은 가장 일반적인 plane으로, 드라이버와 nub(드라이버 간의 통신 채널)를 나타내는 서비스 객체를 표시합니다. 이 객체들 간의 제공자-클라이언트 관계를 보여줍니다.
IODeviceTree Plane: 이 plane은 시스템에 연결된 장치들 간의 물리적 연결을 나타냅니다. USB 또는 PCI와 같은 버스를 통해 연결된 장치들의 계층 구조를 시각화하는 데 자주 사용됩니다.
IOPower Plane: 전원 관리 관점에서 객체와 그 관계를 표시합니다. 다른 객체들의 전원 상태에 영향을 주는 객체를 보여주어 전원 관련 문제의 디버깅에 유용합니다.
IOUSB Plane: USB 장치 및 그 관계에 특히 초점을 맞춘 것으로, USB 허브 및 연결된 장치의 계층 구조를 보여줍니다.
IOAudio Plane: 이 plane은 시스템 내의 오디오 장치와 그 관계를 나타내는 데 사용됩니다.
...
드라이버 통신 코드 예시
다음 코드는 IOKit 서비스 "YourServiceNameHere"에 연결하고 셀렉터 0 내부의 함수를 호출합니다. 이를 위해:
먼저 IOServiceMatching 및 **IOServiceGetMatchingServices**를 호출하여 서비스를 가져옵니다.
그런 다음 **IOServiceOpen**을 호출하여 연결을 설정합니다.
마지막으로 **IOConnectCallScalarMethod**를 사용하여 셀렉터 0(호출하려는 함수에 할당된 번호)를 지정하여 함수를 호출합니다.
#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;
}
**IOConnectCallScalarMethod**와 같은 IOConnectCallMethod, **IOConnectCallStructMethod**과 같은 IOKit 함수를 호출하는 데 사용할 수 있는 다른 함수들이 있습니다.
드라이버 엔트리포인트 역어셈블링
예를 들어 펌웨어 이미지 (ipsw)에서 이러한 함수들을 얻을 수 있습니다. 그런 다음, 즐겨 사용하는 디컴파일러에 로드하십시오.
올바른 함수를 호출하는 호출을 받는 드라이버 함수인 externalMethod 함수의 디컴파일을 시작할 수 있습니다:
이제 (IOExternalMethodDispatch2022 *)&sIOExternalMethodArray를 따라가면 많은 데이터를 볼 수 있습니다:
데이터 유형을 **IOExternalMethodDispatch2022:**로 변경하세요:
변경 후:
이제 여기에 7개 요소의 배열이 있는 것을 알 수 있습니다 (최종 디컴파일된 코드를 확인하세요). 7개 요소의 배열을 생성하려면 클릭하세요:
배열이 생성된 후 모든 내보낸 함수를 볼 수 있습니다:
기억하시나요? 사용자 공간에서 내보낸 함수를 호출할 때 함수 이름을 호출할 필요가 없고 선택기 번호를 호출해야 합니다. 여기서 선택기 0은 함수 **initializeDecoder**를 나타내고, 선택기 1은 **startDecoder**를 나타내며, 선택기 2는 **initializeEncoder**를 나타냅니다...