macOS IOKit

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°

Basic Information

I/O Kit은 XNU μ»€λ„μ—μ„œ 동적 λ‘œλ“œλœ μž₯치 λ“œλΌμ΄λ²„λ₯Ό μ²˜λ¦¬ν•˜λŠ” μ˜€ν”ˆ μ†ŒμŠ€, 객체 μ§€ν–₯ μž₯치 λ“œλΌμ΄λ²„ ν”„λ ˆμž„μ›Œν¬μž…λ‹ˆλ‹€. μ΄λŠ” λ‹€μ–‘ν•œ ν•˜λ“œμ›¨μ–΄λ₯Ό μ§€μ›ν•˜λ©°, 컀널에 λͺ¨λ“ˆμ‹ μ½”λ“œλ₯Ό μ¦‰μ‹œ μΆ”κ°€ν•  수 있게 ν•΄μ€λ‹ˆλ‹€.

IOKit λ“œλΌμ΄λ²„λŠ” 기본적으둜 μ»€λ„μ—μ„œ ν•¨μˆ˜λ₯Ό λ‚΄λ³΄λƒ…λ‹ˆλ‹€. 이 ν•¨μˆ˜ λ§€κ°œλ³€μˆ˜ μœ ν˜•μ€ 미리 μ •μ˜λ˜μ–΄ 있으며 κ²€μ¦λ©λ‹ˆλ‹€. λ˜ν•œ, XPC와 μœ μ‚¬ν•˜κ²Œ, IOKit은 Mach λ©”μ‹œμ§€ μœ„μ— 또 λ‹€λ₯Έ λ ˆμ΄μ–΄μž…λ‹ˆλ‹€.

IOKit XNU 컀널 μ½”λ“œλŠ” Apple에 μ˜ν•΄ https://github.com/apple-oss-distributions/xnu/tree/main/iokitμ—μ„œ μ˜€ν”ˆ μ†ŒμŠ€λ‘œ μ œκ³΅λ©λ‹ˆλ‹€. λ˜ν•œ, μ‚¬μš©μž 곡간 IOKit ꡬ성 μš”μ†Œλ„ μ˜€ν”ˆ μ†ŒμŠ€μž…λ‹ˆλ‹€ https://github.com/opensource-apple/IOKitUser.

κ·ΈλŸ¬λ‚˜ IOKit λ“œλΌμ΄λ²„λŠ” μ˜€ν”ˆ μ†ŒμŠ€κ°€ μ•„λ‹™λ‹ˆλ‹€. μ–΄μ¨Œλ“ , λ•Œλ•Œλ‘œ λ“œλΌμ΄λ²„μ˜ λ¦΄λ¦¬μŠ€κ°€ 디버깅을 μ‰½κ²Œ ν•΄μ£ΌλŠ” κΈ°ν˜Έμ™€ ν•¨κ»˜ 제곡될 수 μžˆμŠ΅λ‹ˆλ‹€. νŽŒμ›¨μ–΄μ—μ„œ λ“œλΌμ΄λ²„ ν™•μž₯을 μ–»λŠ” 방법은 μ—¬κΈ°μ—μ„œ ν™•μΈν•˜μ„Έμš”.

C++둜 μž‘μ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€. λ‹€μŒμ„ μ‚¬μš©ν•˜μ—¬ λ””λ§κΈ€λœ C++ 기호λ₯Ό 얻을 수 μžˆμŠ΅λ‹ˆλ‹€:

# 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 λ…ΈμΆœλœ ν•¨μˆ˜λŠ” ν΄λΌμ΄μ–ΈνŠΈκ°€ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ €κ³  ν•  λ•Œ μΆ”κ°€ λ³΄μ•ˆ 검사λ₯Ό μˆ˜ν–‰ν•  수 μžˆμ§€λ§Œ, 앱은 일반적으둜 IOKit ν•¨μˆ˜μ™€ μƒν˜Έμž‘μš©ν•  수 μžˆλŠ” μƒŒλ“œλ°•μŠ€μ— μ˜ν•΄ μ œν•œλ©λ‹ˆλ‹€.

λ“œλΌμ΄λ²„

macOSμ—μ„œλŠ” λ‹€μŒ μœ„μΉ˜μ— μžˆμŠ΅λ‹ˆλ‹€:

  • /System/Library/Extensions
  • OS X 운영 μ²΄μ œμ— λ‚΄μž₯된 KEXT 파일.
  • /Library/Extensions
  • 3rd νŒŒν‹° μ†Œν”„νŠΈμ›¨μ–΄μ— μ˜ν•΄ μ„€μΉ˜λœ KEXT 파일

iOSμ—μ„œλŠ” λ‹€μŒ μœ„μΉ˜μ— μžˆμŠ΅λ‹ˆλ‹€:

  • /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κΉŒμ§€ λ‚˜μ—΄λœ λ“œλΌμ΄λ²„λŠ” μ£Όμ†Œ 0에 λ‘œλ“œλ©λ‹ˆλ‹€. μ΄λŠ” 이듀이 μ‹€μ œ λ“œλΌμ΄λ²„κ°€ μ•„λ‹ˆλΌ μ»€λ„μ˜ 일뢀이며 μ–Έλ‘œλ“œν•  수 μ—†μŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€.

νŠΉμ • ν™•μž₯을 μ°ΎκΈ° μœ„ν•΄ λ‹€μŒμ„ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

kextfind -bundle-id com.apple.iokit.IOReportFamily #Search by full bundle-id
kextfind -bundle-id -substring IOR #Search by substring in bundle-id

컀널 ν™•μž₯을 λ‘œλ“œν•˜κ³  μ–Έλ‘œλ“œν•˜λ €λ©΄ λ‹€μŒμ„ μˆ˜ν–‰ν•˜μ‹­μ‹œμ˜€:

kextload com.apple.iokit.IOReportFamily
kextunload com.apple.iokit.IOReportFamily

IORegistry

IORegistryλŠ” macOS 및 iOS의 IOKit ν”„λ ˆμž„μ›Œν¬μ—μ„œ μ‹œμŠ€ν…œμ˜ ν•˜λ“œμ›¨μ–΄ ꡬ성 및 μƒνƒœλ₯Ό λ‚˜νƒ€λ‚΄λŠ” λ°μ΄ν„°λ² μ΄μŠ€μ˜ μ€‘μš”ν•œ λΆ€λΆ„μž…λ‹ˆλ‹€. μ΄λŠ” μ‹œμŠ€ν…œμ— λ‘œλ“œλœ λͺ¨λ“  ν•˜λ“œμ›¨μ–΄ 및 λ“œλΌμ΄λ²„λ₯Ό λ‚˜νƒ€λ‚΄λŠ” 객체의 계측적 μ»¬λ ‰μ…˜μ΄λ©°, 이듀 κ°„μ˜ 관계λ₯Ό λ‚˜νƒ€λƒ…λ‹ˆλ‹€.

μ½˜μ†”μ—μ„œ IORegistryλ₯Ό κ²€μ‚¬ν•˜κΈ° μœ„ν•΄ cli **ioreg**λ₯Ό μ‚¬μš©ν•˜μ—¬ 얻을 수 μžˆμŠ΅λ‹ˆλ‹€(특히 iOS에 μœ μš©ν•©λ‹ˆλ‹€).

ioreg -l #List all
ioreg -w 0 #Not cut lines
ioreg -p <plane> #Check other plane

**IORegistryExplorer**λŠ” https://developer.apple.com/download/all/의 Xcode Additional Toolsμ—μ„œ λ‹€μš΄λ‘œλ“œν•  수 있으며, κ·Έλž˜ν”½ μΈν„°νŽ˜μ΄μŠ€λ₯Ό 톡해 macOS IORegistryλ₯Ό 검사할 수 μžˆμŠ΅λ‹ˆλ‹€.

IORegistryExplorerμ—μ„œ β€œplanesβ€œλŠ” IORegistry의 λ‹€μ–‘ν•œ 객체 κ°„μ˜ 관계λ₯Ό μ‘°μ§ν•˜κ³  ν‘œμ‹œν•˜λŠ” 데 μ‚¬μš©λ©λ‹ˆλ‹€. 각 plane은 νŠΉμ • μœ ν˜•μ˜ 관계 λ˜λŠ” μ‹œμŠ€ν…œμ˜ ν•˜λ“œμ›¨μ–΄ 및 λ“œλΌμ΄λ²„ ꡬ성에 λŒ€ν•œ νŠΉμ • λ·°λ₯Ό λ‚˜νƒ€λƒ…λ‹ˆλ‹€. IORegistryExplorerμ—μ„œ 마주칠 수 μžˆλŠ” 일반적인 planesλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

  1. IOService Plane: λ“œλΌμ΄λ²„μ™€ nubs(λ“œλΌμ΄λ²„ κ°„μ˜ 톡신 채널)λ₯Ό λ‚˜νƒ€λ‚΄λŠ” μ„œλΉ„μŠ€ 객체λ₯Ό ν‘œμ‹œν•˜λŠ” κ°€μž₯ 일반적인 planeμž…λ‹ˆλ‹€. 이 객체듀 κ°„μ˜ 제곡자-ν΄λΌμ΄μ–ΈνŠΈ 관계λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€.
  2. IODeviceTree Plane: μ‹œμŠ€ν…œμ— μ—°κ²°λœ μž₯치 κ°„μ˜ 물리적 연결을 λ‚˜νƒ€λ‚΄λŠ” planeμž…λ‹ˆλ‹€. USB λ˜λŠ” PCI와 같은 λ²„μŠ€λ₯Ό 톡해 μ—°κ²°λœ μž₯치의 계측 ꡬ쑰λ₯Ό μ‹œκ°ν™”ν•˜λŠ” 데 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
  3. IOPower Plane: 전원 관리 μΈ‘λ©΄μ—μ„œ 객체와 κ·Έ 관계λ₯Ό ν‘œμ‹œν•©λ‹ˆλ‹€. λ‹€λ₯Έ 객체의 전원 μƒνƒœμ— 영ν–₯을 λ―ΈμΉ˜λŠ” 객체λ₯Ό 보여쀄 수 μžˆμ–΄ 전원 κ΄€λ ¨ 문제λ₯Ό λ””λ²„κΉ…ν•˜λŠ” 데 μœ μš©ν•©λ‹ˆλ‹€.
  4. IOUSB Plane: USB μž₯μΉ˜μ™€ κ·Έ 관계에 νŠΉλ³„νžˆ μ΄ˆμ μ„ λ§žμΆ”μ–΄ USB ν—ˆλΈŒμ™€ μ—°κ²°λœ μž₯치의 계측 ꡬ쑰λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€.
  5. IOAudio Plane: μ‹œμŠ€ν…œ λ‚΄μ—μ„œ μ˜€λ””μ˜€ μž₯μΉ˜μ™€ κ·Έ 관계λ₯Ό λ‚˜νƒ€λ‚΄λŠ” planeμž…λ‹ˆλ‹€.
  6. …

Driver Comm Code Example

λ‹€μŒ μ½”λ“œλŠ” IOKit μ„œλΉ„μŠ€ "YourServiceNameHere"에 μ—°κ²°ν•˜κ³  μ„ νƒμž 0 λ‚΄μ˜ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€. 이λ₯Ό μœ„ν•΄:

  • λ¨Όμ € IOServiceMatching 및 **IOServiceGetMatchingServices**λ₯Ό ν˜ΈμΆœν•˜μ—¬ μ„œλΉ„μŠ€λ₯Ό κ°€μ Έμ˜΅λ‹ˆλ‹€.
  • 그런 λ‹€μŒ **IOServiceOpen**을 ν˜ΈμΆœν•˜μ—¬ 연결을 μ„€μ •ν•©λ‹ˆλ‹€.
  • λ§ˆμ§€λ§‰μœΌλ‘œ μ„ νƒμž 0(μ„ νƒμžλŠ” ν˜ΈμΆœν•˜λ €λŠ” ν•¨μˆ˜μ— ν• λ‹Ήλœ 번호)둜 **IOConnectCallScalarMethod**λ₯Ό μ‚¬μš©ν•˜μ—¬ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€.
#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 ν•¨μˆ˜λ₯Ό λ””μ»΄νŒŒμΌν•˜κΈ° μ‹œμž‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이 ν•¨μˆ˜λŠ” ν˜ΈμΆœμ„ λ°›κ³  μ˜¬λ°”λ₯Έ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” λ“œλΌμ΄λ²„ ν•¨μˆ˜μž…λ‹ˆλ‹€:

κ·Έ λ”μ°ν•œ 호좜의 λ””λ§₯κΈ€λœ μ˜λ―ΈλŠ”:

IOUserClient2022::dispatchExternalMethod(unsigned int, IOExternalMethodArgumentsOpaque*, IOExternalMethodDispatch2022 const*, unsigned long, OSObject*, void*)

이전 μ •μ˜μ—μ„œ self λ§€κ°œλ³€μˆ˜κ°€ λˆ„λ½λœ 점에 μœ μ˜ν•˜μ„Έμš”. μ˜¬λ°”λ₯Έ μ •μ˜λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

IOUserClient2022::dispatchExternalMethod(self, unsigned int, IOExternalMethodArgumentsOpaque*, IOExternalMethodDispatch2022 const*, unsigned long, OSObject*, void*)

μ‹€μ œ μ •μ˜λŠ” 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)

이 정보λ₯Ό 톡해 Ctrl+Right -> Edit function signatureλ₯Ό λ‹€μ‹œ μž‘μ„±ν•˜κ³  μ•Œλ €μ§„ μœ ν˜•μ„ μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

μƒˆλ‘œ λ””μ»΄νŒŒμΌλœ μ½”λ“œλŠ” λ‹€μŒκ³Ό 같이 보일 κ²ƒμž…λ‹ˆλ‹€:

λ‹€μŒ λ‹¨κ³„μ—μ„œλŠ” IOExternalMethodDispatch2022 ꡬ쑰체λ₯Ό μ •μ˜ν•΄μ•Ό ν•©λ‹ˆλ‹€. μ΄λŠ” https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/IOKit/IOUserClient.h#L168-L176μ—μ„œ μ˜€ν”ˆμ†ŒμŠ€λ‘œ 제곡되며, 이λ₯Ό μ •μ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

이제 (IOExternalMethodDispatch2022 *)&sIOExternalMethodArrayλ₯Ό 따라 λ§Žμ€ 데이터λ₯Ό λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€:

데이터 μœ ν˜•μ„ **IOExternalMethodDispatch2022:**둜 λ³€κ²½ν•©λ‹ˆλ‹€:

λ³€κ²½ ν›„:

이제 μ—¬κΈ°μ—μ„œ 7개의 μš”μ†Œλ‘œ κ΅¬μ„±λœ 배열이 μžˆλ‹€λŠ” 것을 μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€(μ΅œμ’… λ””μ»΄νŒŒμΌλœ μ½”λ“œλ₯Ό ν™•μΈν•˜μ„Έμš”). 7개의 μš”μ†Œλ‘œ κ΅¬μ„±λœ 배열을 μƒμ„±ν•˜λ €λ©΄ ν΄λ¦­ν•©λ‹ˆλ‹€:

배열이 μƒμ„±λœ ν›„μ—λŠ” λͺ¨λ“  내보낸 ν•¨μˆ˜λ₯Ό λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€:

Tip

κΈ°μ–΅ν•˜μ‹ λ‹€λ©΄, μ‚¬μš©μž κ³΅κ°„μ—μ„œ 내보낸 ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ €λ©΄ ν•¨μˆ˜μ˜ 이름을 ν˜ΈμΆœν•  ν•„μš”κ°€ μ—†κ³ , μ„ νƒμž 번호λ₯Ό ν˜ΈμΆœν•΄μ•Ό ν•©λ‹ˆλ‹€. μ—¬κΈ°μ—μ„œ μ„ νƒμž 0은 ν•¨μˆ˜ initializeDecoder, μ„ νƒμž 1은 startDecoder, μ„ νƒμž 2λŠ” **initializeEncoder**μž…λ‹ˆλ‹€β€¦

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°