Loading
1

暴风影音AviIndexChunk字段堆溢出漏洞分析实战

77edb586 ntdll!RtlpAllocateHeap+0x000000c4
77e83541 ntdll!RtlAllocateHeap+0x0000023a
75440269 MSVCR100!malloc+0x0000004b
可以发现:
a. 当poc.avi样本文件中0x26a位置为02 00 00 00时,申请堆大小为4字节
b. 当poc.avi样本文件中0x26a位置为03 00 00 00时,申请堆大小为6字节
结合call指令之前的指令:
6697303a 8d0c12          lea     ecx,[edx+edx]
6697303d 51              push    ecx
6697303e e869480100      call    AviSplitter!DllGetClassObject+0x337c (669878ac)
edx等于样本文件0x26a位置的数值,可以断定:
生成的页堆大小正好是poc.avi样本文件中0x26a位置所代表数值的两倍
那为何会出现这种规律呢?下面结合avi的格式探究一下漏洞的成因。
4. 再探漏洞成因
漏洞现场主要涉及poc.avi样本末尾的相关数据:
69 64 78 31 02 00 00 00 41 42 idx1….AB
以固定指令写入的69 64 78 31正好是魔术字idx1,这就为文件内容和avi格式建立起了联系。下面是查询的该魔术字相关字段的格式:
Block name="AviIndexChunk">
Block name="IndexChunkHeader">
String name="AviIndex1Start" value="idx1" token="true"/>
Number name="cbFileSize" size="32" endian="little" signed="false">
Relation type="size" of="IndexChunkData" />
Number>
Block>
Block name="IndexChunkData">
Number name="null" size="16" endian="little" signed="false"/>
Block>
Block>
可以看出样本末尾相关内容对应的逻辑为:
-IndexChunkHeader
+AviIndex1Start --> 69 64 78 31
+cbFileSize     --> 02 00 00 00
-IndexChunkData
+ null          --> 41 42
显而易见cbFileSize本意代表IndexChunkData的大小。
根据上面分析过程,页堆的申请大小等于cbFileSize*2,实际根据分配粒度将其扩容为8字节的倍数。如果向页堆写入的8字节IndexChunkHeader和后续IndexChunkData的内容超过页堆的实际大小,就会造成堆溢出。
因此漏洞的成因就是,在页堆申请时,只是单纯地将页堆大小设置为cbFileSize的2倍,没有考虑页堆前8个字节要写入固定的内容IndexChunkHeader,从而造成了堆溢出。
0×03 漏洞造成的具体影响
经反复修改poc.avi样本文件中的cbFileSize的数值和IndexChunkData内容,可以发现memcpy函数的第三个参数“拷贝大小”与两者有下列关系:
memcpy_size = min(cbFileSize, sizeof(IndexChunkData))
而通过上面的分析可知,堆溢出必须满足关系:
memcpy_size + 8  > cbFileSize*2
那如果排除页堆末尾的填充字节,另外最多可以造成多少字节的溢出呢?
通过上述两个数学关系可以得到:
a. 若cbFileSize sizeof(IndexChunkData),memcpy_size= cbFileSize,从而得出cbFileSize 8
b. 若cbFileSize > sizeof(IndexChunkData),memcpy_size= sizeof(IndexChunkData),也能得出cbFileSize 8
综上所述,cbFileSize的数值必须小于8,才有可能出现堆溢出。
列举cbFileSize所有可能的数值:
cbFileSize=1,heap_size = 8,至多溢出1个字节
cbFileSize=2,heap_size = 8,至多溢出2个字节
cbFileSize=3,heap_size = 8,至多溢出3个字节
cbFileSize=4,heap_size = 8,至多溢出4个字节
cbFileSize=5,heap_size = 16,不溢出
cbFileSize=6,heap_size = 16,不溢出
cbFileSize=7,heap_size = 16,不溢出
cbFileSize=8,heap_size = 16,不溢出
由此可知,当且仅当cbFileSize=4时,至多可以溢出页堆填充字节之后的4个字节。也就是说,该堆溢出漏洞造成的最大影响就是,重写堆填充字节之后的4个字节。
0×04 真实环境下的堆溢出
在开启页堆调试选项hpa的情况下,当溢出堆填充字节之后的第一个字节时,调试器就会捕获异常,无法完成4字节的完整溢出。
为看到真实的溢出效果,关闭hpa选项:
> gflags.exe /i StormPlayer.exe –ust -hpa
Current Registry Settings for StormPlayer.exe executable are: 00000000
备注:hpa页堆调试和ust栈回溯选项都会影响堆的实际内存布局,具体参照>P666和P677相关内容。
在poc.avi样本文件结尾修改cbFileSize=00000004,增加16字节的IndexChunkData内容:
00000260h: 64 62 00 00 00 00 69 64 78 31 04 00 00 00 41 42 ; db....idx1....AB
00000270h: 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 ; CDEFGHIJKLMNOPQR
Windbg重新附加至StormPlayer.exe进程,在创建该堆的call指令处下断点:
0:025>  bp AviSplitter+0x0000303e
重新加载poc.avi样本:
Breakpoint 0 hit
eax=31786469 ebx=00000000 ecx=00000008 edx=00000004 esi=01ce0ac0 edi=00000270
eip=6795303e esp=0b37f338 ebp=0b37f38c iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
AviSplitter+0x303e:
6795303e e869480100      call    AviSplitter!DllGetClassObject+0x337c (679678ac)

分页阅读: 1 2 3 4 5 6 7 8 9 10
【声明】:8090安全小组门户(https://www.8090-sec.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们:邮箱hack@ddos.kim,我们会在最短的时间内进行处理。