安全技术

iOS 8.4.1 Kernel Vulnerabilities in AppleHDQGasGaugeControl

When auditing iOS kernel executable, we found that the code quality of com.apple.driver.AppleHDQGasGaugeControl is very bad. In this blog, we will disclose 3 vulnerabilities in this kernel extension on the latest public iOS (version 8.4.1). More importantly, one of these bugs is a perfect heap overflow vulnerability that allows us to defeat all kernel mitigations and gain code execution in the kernel, just by exploiting this single vulnerability.

1st – Stack overflow bug in the function for selector 7

The handler function takes 3 input scalars and 1 output scalar. The following code shows that stack overflow may occur since there’s no restriction for inputScalar[1]. If inputScalar[1] is a very large number, the loop will corrupt the stack.

(更多…)

越狱插件盗取22万个苹果账号样本分析

盗号事件

最近乌云爆出某些越狱插件盗取22万个苹果账号的事件,如果曾经安装过不明源里的插件,建议用户立刻修改密码。

样本分析

下文将分析获取的一个盗号插件样本,该盗号木马将自己捆绑到知名的iFile越狱插件中以达到安装执行的目的。解开deb可以看到跟原版的iFile相比多了一个基于Substrate框架的插件:

$ ls iFile_2.2.0-2-2/data/Library/MobileSubstrate/DynamicLibraries/
iFile.dylib iFile.plist

查看iFile.plist发现iFile.dylib模块被注入了itunesstored这个关键服务:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Filter</key>
    <dict>
        <key>Executables</key>
        <array>
            <string>MobileSafari</string>
            <string>assertiond</string>
            <string>SpringBoard</string>
            <string>itunesstored</string>
        </array>
    </dict>
</dict>
</plist>

使用IDA分析iFile.dylib,hookaid方法调用MSHookFunction函数hook了”/System/Library/Frameworks/Security.framework/Security”框架的SSLWrite和SSLRead函数。

(更多…)

CVE-2015-5774

IOHIDResourceDeviceUserClient::_postReportResult堆溢出漏洞

漏洞描述

该内核漏洞被用于太极越狱v2.0,并于iOS 8.4.1版本中被修补。Apple的安全公告中给出的漏洞编号为CVE-2015-5774,但并未提及漏洞的细节。

通过查看IOHIDFamily的代码,检查IOHIDResourceDeviceUserClient的3号处理函数_postReportResult。该函数的入参是2个uint64(分别对应result和token),以及任意长度的一个struct数据(report数据)。

typedef enum {
    kIOHIDResourceUserClientResponseIndexResult = 0,
    kIOHIDResourceUserClientResponseIndexToken,
    kIOHIDResourceUserClientResponseIndexCount
} IOHIDResourceUserClientResponseIndex;

    {   // kIOHIDResourceDeviceUserClientMethodPostReportResult
        (IOExternalMethodAction) &IOHIDResourceDeviceUserClient::_postReportResult,
        kIOHIDResourceUserClientResponseIndexCount, -1, /* 1 scalar input: the result, 1 struct input : the buffer */
        0, 0
    }

(更多…)

IE浏览器漏洞一例及未初始化内存占位研究

很久以前我们在检测safari稳定性的时候,偶然遇到了一个IE的问题,但在四月份补丁后,这一崩溃不再重现。通过咨询过IE大牛,我们发现这个问题极有可能是今年三月份补丁中的CVE-2015-1625。这个在MS15-018中被修补了的问题被描述为内存破坏漏洞,影响到全部的IE版本,鉴于我们在微软鸣谢中没有找到对应的报告者,所以这个漏洞有可能归于微软内部发现。
要触发这个IE问题,只需要以下代码:

<html>
 <head>
  <meta http-equiv="x-ua-compatible" content="IE=5" />
  <script>
   function fuzz0(){
    e_2.replaceNode(e_2);
    e_0.replaceNode(e_0);
   }
   function entry(){
    e_0.contentEditable="true";
    e_0.createTextRange().select();
    e_1.insertRow();
   }
  </script>
 </head>
 <body id=e_0 onload=entry() onactivate=fuzz0()>
  <table id=e_1>
   <tr>02</tr>
   <big id=e_2>
    <tbody></tbody>
   </big>
  </table>
 </body>
</html>

挂上调试器打开此页面,崩溃地址和寄存器的数值非常不稳定,但在打开page heap后,崩溃点很明显的指向一个固定地址。以WinXP SP3全补丁虚拟机为例,崩溃时log如下:

(更多…)

IOHIDSecurePromptClient::injectStringGated Heap Overflow

IOHIDSecurePromptClient::injectStringGated堆溢出漏洞

update – 漏洞发现者博客

前两周网上有披露一个IOHID中的堆溢出漏洞,并且有完整的攻击代码,这里做个简单的分析:D

漏洞出现在IOHIDSecurePromptClient的12号处理函数中:

IOExternalMethod *
IOHIDSecurePromptClient::getTargetAndMethodForIndex(IOService ** targetP, 
                                                    UInt32 index)
{
        ...
        // 12: kIOHIDSecurePromptClient_injectString
        { NULL, (IOMethod)&IOHIDSecurePromptClient::injectStringMethod, kIOUCStructIStructO, kIOUCVariableStructureSize, 0 },       
        ...
};

injectStringMethod -> injectStringGated 函数中将输入的参数拷贝到缓冲区时没有对长度做任何检查,从而会导致堆溢出:

IOReturn
IOHIDSecurePromptClient::injectStringGated(void * p1, void * p2, void * p3 __unused,void * p4 __unused)
{
    IOReturn result = kIOReturnBadArgument;
    IOHIDSecurePromptClient_RawKeystrokeData * dummyRawData = NULL;
    UTF32Char *string = (UTF32Char*)p1;
    intptr_t length = (intptr_t)p2 / sizeof(UTF32Char);
    vm_size_t dummyDataSize = length * sizeof(IOHIDSecurePromptClient_RawKeystrokeData);

    ...

    dummyRawData = (IOHIDSecurePromptClient_RawKeystrokeData*)IOMalloc(dummyDataSize);
    memset(dummyRawData, 0xff, dummyDataSize);

    // _reserved->rawKeystrokes是在IOServiceOpen的时候分配的堆内存,在这里拷贝的时候没有检查输入的length
    __InsertBytes(_reserved->rawKeystrokes, _reserved->insertionPoint, _reserved->stringLength, string, length,  sizeof(UTF32Char));
    __InsertBytes(_reserved->unicode, _reserved->insertionPoint, _reserved->stringLength, dummyRawData, length,  sizeof(UTF32Char));
    __EraseMemory(string, length * sizeof(UTF32Char));
    _reserved->insertionPoint += length;
    result = kIOReturnSuccess;

    ...
}

(更多…)

CVE-2014-4461

CVE-2014-4461 – IOSharedDataQueue映射内存漏洞

漏洞描述

IOSharedDataQueue类用于队列数据的管理,并且能够被映射到用户态下共享。由于返回的映射内存的大小设置问题,导致除了Data数据外还映射了notify msg的内存区域,从而可以在用户态下读取/改写msg内port的指针。

初始化时分配了足够大小的内存,并把notifyMsg成员放在尾部

Boolean IOSharedDataQueue::initWithCapacity(UInt32 size)
{
    ...

    allocSize = round_page(size + DATA_QUEUE_MEMORY_HEADER_SIZE + DATA_QUEUE_MEMORY_APPENDIX_SIZE);

    if (allocSize < size) {
        return false;
    }

    // 分配足够大小的内存给dataQueue
    dataQueue = (IODataQueueMemory *)IOMallocAligned(allocSize, PAGE_SIZE);
    if (dataQueue == 0) {
        return false;
    }

    ...

    // notifyMsg成员被放在dataQueue的尾部
    appendix            = (IODataQueueAppendix *)((UInt8 *)dataQueue + size + DATA_QUEUE_MEMORY_HEADER_SIZE);
    appendix->version   = 0;
    notifyMsg           = &(appendix->msgh);
    setNotificationPort(MACH_PORT_NULL);

    return true;
}

(更多…)

CVE-2014-4487

CVE-2014-4487 – IOHIDLibUserClient堆溢出漏洞

漏洞描述

通过查看IOHIDFamily的代码,检查IOHIDLibUserClient的15号处理函数_getElements。该函数的入参是1个uint64,指定要获取的element是哪个队列的。出参是一个struct结构,无固定长度。

    { //    kIOHIDLibUserClientGetElements
    (IOExternalMethodAction) &IOHIDLibUserClient::_getElements,
    1, 0,
    0, kIOUCVariableStructureSize
    },

_getElements在处理的时候,如果出参是structureOutputDescriptor,则会先IOMalloc用户指定长度的缓冲区然后再去填充elements数据。

IOReturn IOHIDLibUserClient::_getElements(IOHIDLibUserClient * target, void * reference __unused, IOExternalMethodArguments * arguments)
{
    if ( arguments->structureOutputDescriptor )
        return target->getElements((uint32_t)arguments->scalarInput[0], arguments->structureOutputDescriptor, &(arguments->structureOutputDescriptorSize));
    else
        return target->getElements((uint32_t)arguments->scalarInput[0], arguments->structureOutput, &(arguments->structureOutputSize));
}

IOReturn IOHIDLibUserClient::getElements (uint32_t elementType, void *elementBuffer, uint32_t *elementBufferSize)
{
...
        elementLength = mem->getLength();
        if ( elementLength )
        {
            // 根据用户指定的大小来分配内存
            elementData = IOMalloc( elementLength );

            if ( elementData )
            {
                bzero(elementData, elementLength);

                // 向分配的堆中填充数据,elementLength更新为实际填充的数据长度
                ret = getElements(elementType, elementData, &elementLength);

                if ( elementBufferSize )
                    *elementBufferSize = elementLength;

                mem->writeBytes( 0, elementData, elementLength );

                // 释放刚分配的堆
                IOFree( elementData, elementLength );
...
}

(更多…)