深入分析MicrosoftOutlook漏洞

Microsoft Outlook是Microsoft Office套件的组件之一,广泛用于发送和接收电子邮件,管理联系人,记录和跟踪日程安排以及执行其他任务。在Windows上运行的多个版本的Outlook中发现了堆崩溃漏洞,涵盖了从Outlook 2010到最新的Outlook 2019以及Office 365 ProPlus的所有32/64位版本的软件。该漏洞可能由格式错误的RWZ文件来触发。当Outlook收到恶意的RWZ文件内容时,它会分配太少的堆内存,并且缺少适当的边界检查,导致堆内存越界写入。

为重现此漏洞,我们需要运行Microsoft Outlook,然后单击“规则=>管理规则和警报=>选项=>导入规则”选择可触发Outlook崩溃的PoC文件。

以下是发生崩溃时,调用堆栈情况:

 

分析漏洞

正如我们从调用堆栈中看到的那样,当堆内存被释放时就发生程序崩溃了。由于我们现在无法确认堆释放时有什么问题,我们可以打开完整的堆内存页表来跟踪堆内存的数据变化。命令如下:

YOUR_WINDBG_INSATALL_LOCATION \ gfl​​ags.exe / p /enable outlook.exe / full

您可以看到以下返回的结果,表明它已成功执行。

完成此操作后,我们可以再次打开Outlook并选择PoC文件以在发生崩溃时监视新堆栈:

现在我们可以看到ECX指向的非0内存地址是不可读的,并且在将数据写入该内存地址时会发生异常。尝试将数据写入未分配(或释放)的内存地址的可能性很高。我们可以通过检查内存页面分配来验证这个预测,在那里我们可以看到内存仍然具有Reserve属性。

我们现在需要弄清楚程序为什么要将数据写入未使用的内存页面。通过静态分析,我们可以看到ECX的值来自EDI,并且EDI在调用MAPIAllocateBuffer之后被修改:

通过静态分析,我们了解到函数MAPIAllocateBuffer是RtlAllocateHeap的封装函数,它检查以确保请求的堆大小参数不大于0x7FFFFFF7。但是,在这种情况下,它不会检查0是否可以用作参数。并且因为实际分配的堆大小比请求的堆大小多8个字节,所以8个字节用0x0000000001000010填充。之后,MAPIAllocateBuffer在这8个字节后返回一个堆地址。因此,调用MAPIAllocateBuffer后的EDI值为8 +从RtlAllocateHeap接收的分配堆地址。

从上面的静态分析中,我们可以大致的预测在Reserve堆中写入数据的原因是由整型溢出引起的。结合调试,我们发现调用MAPIAllocateBuffer的堆大小参数为0.但是,由于MAPIAllocateBuffer请求分配大小为0 + 8 = 8的堆,因此RtlAllocateHeap不会返回错误并成功返回正确的堆地址。但是,MAPIAllocateBuffer使用这8个字节写入0x0000000001000010,然后向用户返回无效的内存地址。

接下来,我们需要弄清楚请求的堆大小的值变为0的原因,结合调试和静态分析,我们发现值0来自当前函数的参数:arg_4(eax = arg_4 * 4 + 4) 。但是,当调用当前函数时,arg_4的值并不是之前传入的参数值,这意味着此arg_4的值被修改了。通过分析我们可以看到值是在子函数sub_65F7DA中被修改的。

对子函数sub_65F7DA分析之后,我们发现它是另一个封装函数。函数是ReadFile ,说明arg_4的值实际上来自PoC文件。

调试显示arg_4读取的文件中的内容为0xFFFFFFFF,因此,由于整型溢出,传递的内存分配大小为0xFFFFFFFF * 4 + 4 = 0。但是,程序没有检查这一点,导致出现了越界写入行为。

检查PoC文件,可以看到0xFFFFFFFF值确实存在。

将其修改为0xAABBCCDD后执行调试,就可以验证溢出是由这4个字节造成的。

通过在Patch发布之后比较程序的汇编代码,我们可以看到现在已经添加了对所请求的分配堆大小的验证。请参见下面的截图:

因此修补程序至关重要,因为成功利用此漏洞的攻击者可以使用特制文件在当前用户的安全context中执行操作。

解决方法

建议存在漏洞的Microsoft Outlook版本的所有用户升级到最新的Outlook版本或立即更新最新的补丁。

 

 

原文链接