Entry User Heap Segment Size PrevSize Unused Flags
-----------------------------------------------------------------------------
01d37ce0 01d37ce8 01de0000 7d59a104 0 - c LFH;busy
在01d37ce0起始的LFH低碎片堆中,由于前4个字节的属性信息被覆盖掉了,导致在调用RtlpLowFragHeapFree释放该堆时,出现了异常。
这里就要问,出现异常的esi+4与01d37ce0起始的LFH低碎片堆中被重写的41424344有什么关系呢?查看RtlpLowFragHeapFree函数的源码:
ntdll!RtlpLowFragHeapFree:
773de51a 8bff mov edi,edi
773de51c 55 push ebp
773de51d 8bec mov ebp,esp
773de51f 83ec28 sub esp,28h
773de522 53 push ebx
773de523 56 push esi
773de524 57 push edi
773de525 8d7af8 lea edi,[edx-8]
773de528 807f0705 cmp byte ptr [edi+7],5
773de52c 0f840f510600 je ntdll!RtlpLowFragHeapFree+0x14 (77443641)
773de532 8b07 mov eax,dword ptr [edi]
773de534 8bf7 mov esi,edi
773de536 c1ee03 shr esi,3
773de539 33f0 xor esi,eax
773de53b 3335a4004b77 xor esi,dword ptr [ntdll!RtlpLFHKey (774b00a4)]
773de541 897dfc mov dword ptr [ebp-4],edi
773de544 33f1 xor esi,ecx
773de546 8b4604 mov eax,dword ptr [esi+4] ds:002b:5fdb294f=????????
由edi=0x01d37ce0可知:
01d37ce0 44434241 8c000001 b30518eb 00000069
esi的求解过程如下:
esi = 41424344 ^ 01d37ce0/8 ^ 774b00a4 ^ 01de0000
其参照的公式如下:
Subsegment = *(DWORD)chunk header ^(chunk header/8)^ RTLpLFHKey^ heap
备注:这里涉及到LFH低碎片堆的内存布局,想要了解LFH低碎片堆的童鞋,请参考某杀毒软件的crash dump 分析>中的描述。
综上所述,在真实环境下,漏洞会导致4字节的堆溢出,实现对后一个LFH低碎片堆的chunk header的覆盖重写。
0×05 异常为何继续执行
无论是hpa页堆选项下,还是真实环境下的溢出,windbg捕获异常后,F5可以发现进程能够继续执行,这是为什么呢?
其实熟悉调试的童鞋估计早就知道了这个原因:这与调试器和进程对异常的处理有关:
如果进程中相关代码部分增加了try catch异常处理策略,当windbg第一次捕获异常,F5继续执行后,默认会将异常交由进程继续处理。
暴风影音进程中try catch逻辑,会捕获并处理相关异常,从而不会出现windbg捕获到二次异常的机会。
比较有趣的是,在调试该漏洞的过程中,发现关闭hpa选项的暴风影音进程有以下异常处理策略:
a. 调用memcpy函数时,包含try catch异常处理逻辑,溢出后不会出现异常
b. 关闭进程时,包含try catch异常处理逻辑,溢出后不会出现异常
c. 在不关闭进程的情况下,暴风影音多次打开poc.avi样本时,不包含try catch异常处理逻辑,进程出现崩溃
由此可知,在暴风影音进程内部,多次打开poc.avi样本会导致之前被溢出的低碎片堆被释放掉。由于没添加相关try catch异常处理策略,最终会导致进程的崩溃。崩溃界面如下:
0×06 总结
到这里整个分析就完成了,梳理一下可知,整个过程主要围绕以下思路:
a. 首先根据漏洞现场的指令,寻找al和edi的来源
b. 分析两者来源时,牵扯到memcpy函数的相关逻辑
c. 根据逻辑中出现的疑惑,一步步逆向,并结合avi格式代表的含义,寻找答案
d. 在实际运行环境下,探究漏洞的具体影响
e. 漏洞分析过程中,遇到windbg异常处理和页堆、LFH低碎片堆的相关内容
全文完。

◆◆1
发表评论