Windbg漏洞分析之CVE-2013-2551
来源:互联网 发布:网络语香菇是什么意思 编辑:程序博客网 时间:2024/05/22 12:04
第一次写这样的文章,如有不对之处,请批评指正。
1. 漏洞描述
此漏洞是由于负责解析VML的VGX.dll模块,在处理<v:stroke>标签的dashstyle.array.length属性时,没有对传入的参数进行完备验证而导致整数溢出。攻击者利用这个漏洞能够对任意地址进行读写操作——通过读取敏感内存信息、改写对象虚表,就能够完美绕过重重内存防护机制实现任意代码执行。
2. 分析环境
(Win8) + (IE10) +(CVE-2013-2551)
3. Poc脚本分析
通过分析脚本发现两点比较可疑地方,首先是vml1.dashstyle=”12 3 4 5 6 7…”,其次是vml1.dashstyle.array.length = 0-1。 VML为shape元素实现了一个Stroke子元素,Stroke子元素有一个DashStyle属性。DashStyle可以是一个常数也可以是一个自定义的类型。当通过JS读取dashstyle属性时,其内部会调用"vgx!COAStroke::get_dashstyle()",随后"vgx!COAStroke::get_dashstyle()"调用子函数"vgx!COAShapeProg::GetOALineDashStyle()"并最终返回一个COALineDashStyle对象。
Dashstyle属性的功能是由COALineDashStyle对象实现的,针对dashstyle为常熟或自定义两种情况会调用不同的COALineDashStyle实现方法,如果dashstyle属性是常数则会调用COALineDashStyle的get_value/put_value函数,如果dashstyle属性为自定义类型那么会调用COALineDashStyle的get_array()方法,并在其子函数COAShapeProg::GetOALineDashStyleArray中返回一个GetOALineDashStyleArray对象。
GetOALineDashStyleArray对象管理dashstyle的自定义属性,其方法有GetOALineDashStyleArray::get_item,GetOALineDashStyleArray::put_itemGetOALineDashStyleArray::get_length,GetOALineDashStyleArray::put_length
当脚本中设置dashstyle.array.length属性时get_length和put_length会被调用,如果调用dashstyle.array访问元素的时候get_item与put_item会被调用。
脚本中使用js语句对dashstyle属性赋值,形如vml1.dashstyle=”1 2 3 4 5 67…”
这时候vgx的vgx!ParseDashStyle会被调用,将控制流转向_MsoFCreateArray函数来创建一个ORG数组。在_MsoFCreateArray中调用_MsoFInitPx函数根据数组成员个数来、进行内存分配,每个数组成员占四字节内存,所以ORG数组的缓冲区大小为数组成员个数×4(byte)。在对dashstyle.array.length属性赋值时,数组成员的个数会改变,在put_length函数中会根据新设置的值来重新为ORG数组成分配内存。然而在put_length中存在一个整数溢出漏洞。
4.windbg跟踪调试
使用windbg在vgx模块的GetOALineDashStyleArray::put_length函数入口处下断点。
778b125c cc int 3
0:018> bpvgx!COALineDashStyleArray::put_length (put_length处设断点)
vgx!COALineDashStyleArray::put_length+0x56:
6d01b84d 8b01 mov eax,dword ptr [ecx]
6d01b84f 51 push ecx
6d01b850 ff502c call dword ptr[eax+2Ch] (callCElements获取当前数组长度)
6d01b853 8b750c mov esi,dword ptr [ebp+0Ch] (保存当前新数组长度(new_length)到esi)
6d01b856 8bd0 mov edx,eax (保存CElements返回值(cur_length)到edx)
6d01b8583bd6 cmp edx,esi (比较cur_length与 new_length) (new_length为(0-1))所以跳转到
6d01b85a 7d50 jge vgx!COALineDashStyleArray::put_length+0xb5 (6d01b8ac)
…
vgx!COALineDashStyleArray::put_length+0xb5:
6d01b8ac 8b4508 mov eax,dword ptr [ebp+8]
6d01b8af 8b08 mov ecx,dword ptr [eax]
6d01b8b1 2bd6 sub edx,esi
6d01b8b3 52 push edx
6d01b8b4 56 push esi
6d01b8b5 50 push eax
6d01b8b6 ff5128 call dword ptr[ecx+28h] (callORG::DeleteRange)
6d01b8b9 eb08 jmp vgx!COALineDashStyleArray::put_length+0xcc(6d01b8c3)
0:006> bl
0 e6d01b7f7 0001 (0001) 0:**** vgx!COALineDashStyleArray::put_length
0:006> pc (列出put_length一次调用的函数)
Breakpoint 0 hit
eax=0000000a ebx=6cfc0e90 ecx=6d01b7f7edx=00e2e9ba esi=0292b5b0 edi=00e2e974
eip=6d01b7f7 esp=0292b088 ebp=0292b0a0iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
vgx!COALineDashStyleArray::put_length:
6d01b7f7 8bff mov edi,edi
0:006>
eax=6cfc0b5c ebx=0616df98 ecx=0617c6b0edx=00e2e9ba esi=0617c6b0 edi=00e2e974
eip=6d01b80c esp=0292b068 ebp=0292b084iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
vgx!COALineDashStyleArray::put_length+0x15:
6d01b80c ff5020 call dword ptr [eax+20h] ds:0023:6cfc0b7c={vgx!COAProg::CheckProg(6cffe728)}
0:006>
eax=0617c6b0 ebx=0616df98 ecx=02ac6198edx=00e2e9ba esi=0617c6b0 edi=00000000
eip=6d01b831 esp=0292b068 ebp=0292b084iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
vgx!COALineDashStyleArray::put_length+0x3a:
6d01b831 e8a219ffff call vgx!COAShapeProg::GetShape (6d00d1d8)
0:006>
eax=6cfbfbc0 ebx=0616df98 ecx=02ac6190edx=0292b08c esi=0617c6b0 edi=00000000
eip=6d01b844 esp=0292b060 ebp=0292b084iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
vgx!COALineDashStyleArray::put_length+0x4d:
6d01b844 ff10 call dword ptr [eax] ds:0023:6cfbfbc0={vgx!CVMLShape::FetchProp (6d028845)}
0:006>
eax=6cfbca10 ebx=0616df98 ecx=06181920edx=02b1daf8 esi=0617c6b0 edi=00000000
eip=6d01b850 esp=0292b064 ebp=0292b084iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
vgx!COALineDashStyleArray::put_length+0x59:
6d01b850 ff502c call dword ptr [eax+2Ch] ds:0023:6cfbca3c={vgx!ORG::CElements (6cfcc560)}
0:006> pc
eax=05aa7890 ebx=024730b8 ecx=6d79ca10edx=0000002d esi=ffffffff edi=00000000
eip=6d7fb8b6 esp=022badec ebp=022bae14iopl=0 nv up ei pl nz ac pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000217
vgx!COALineDashStyleArray::put_length+0xbf:
6d7fb8b6 ff5128 call dword ptr[ecx+28h] ds:0023:6d79ca38={vgx!ORG::DeleteRange(6d7ac449)}
0:006> bp vgx!ORG::CElements (CElements函数处设断点,调用celement目的是为了重新分配数组)
0:006> g
Breakpoint 1 hit
eax=6cfbca10 ebx=0616df98 ecx=06181920edx=02b1daf8 esi=0617c6b0 edi=00000000
eip=6cfcc560 esp=0292b060 ebp=0292b084iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
vgx!ORG::CElements:
6cfcc560 8bff mov edi,edi
0:006> uf .
vgx!ORG:: CElements (CElements函数反汇编)
6cfcc560 8bff mov edi,edi
6cfcc562 55 push ebp
6cfcc563 8bec mov ebp,esp
6cfcc565 8b4508 mov eax,dword ptr [ebp+8]
6cfcc568 0fb74004 movzx eax,word ptr[eax+4] (movzx为无符号整数操作,猜想是为了获取数组长度,作为返回值)
6cfcc56c 5d pop ebp
6cfcc56d c20400 ret 4
eax=058d9690 ebx=05897eb8 ecx=6d79ca10edx=0000002d esi=ffffffff edi=00000000
eip=6d7ac449 esp=01fbadf8 ebp=01fbae24iopl=0 nv up ei pl nz ac pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000217
vgx!ORG::DeleteRange:
6d7ac449 8bff mov edi,edi
0:006> uf .
vgx!ORG::DeleteRange: (ORG::DeleteRange反汇编函数)
6d7ac449 8bff mov edi,edi
6d7ac44b 55 push ebp
6d7ac44c 8bec mov ebp,esp
6d7ac44e ff7510 push dword ptr [ebp+10h]
6d7ac451 8b4508 mov eax,dword ptr [ebp+8]
6d7ac454 ff750c push dword ptr [ebp+0Ch]
6d7ac457 83c004 add eax,4
6d7ac45a 50 push eax
6d7ac45be8549c0300 call vgx!MsoDeletePx (6d7e60b4) (ORG::DeleteRange调用MsoDeletePx进行delete)
6d7ac460 5d pop ebp
6d7ac461 c20c00 ret 0Ch
0:006> bp vgx!MsoDeletePx
0:006> g
Breakpoint 1 hit
eax=058d9694 ebx=05897eb8 ecx=6d79ca10edx=0000002d esi=ffffffff edi=00000000
eip=6d7e60b4 esp=01fbade4 ebp=01fbadf4iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
vgx!MsoDeletePx:
6d7e60b4 8bff mov edi,edi
0:006> uf .
vgx!MsoDeletePx:
6d7e60b4 8bff mov edi,edi
6d7e60b6 55 push ebp
6d7e60b7 8bec mov ebp,esp
6d7e60b9 56 push esi
6d7e60ba ff7510 push dword ptr [ebp+10h]
6d7e60bd 8b7508 mov esi,dword ptr [ebp+8]
6d7e60c0 ff750c push dword ptr [ebp+0Ch]
6d7e60c3 56 push esi
6d7e60c4 e819000000 call vgx!MsoFRemovePx (6d7e60e2)
6d7e60c9 33c0 xor eax,eax
6d7e60cb 663906 cmp word ptr [esi],ax
6d7e60ce 0f94c0 sete al
6d7e60d1 50 push eax
6d7e60d2 56 push esi
6d7e60d3 e8c7000000 call vgx!MsoFCompactPx (6d7e619f)
6d7e60d8 5e pop esi
6d7e60d9 5d pop ebp
6d7e60da c20c00 ret 0Ch
0:006> uf .
vgx!MsoFRemovePx:
6d7e60e2 8bff mov edi,edi
6d7e60e4 55 push ebp <-------------
6d7e60e5 8bec mov ebp,esp .
6d7e60e7 8b450c mov eax,dword ptr [ebp+0Ch] .(eax为new_length)
6d7e60ea 53 push ebx .
6d7e60eb 8b5d08 mov ebx,dword ptr [ebp+8] .
6d7e60ee 8b4b04 mov ecx,dword ptr [ebx+4] .
...
vgx!MsoFRemovePx+0x83:
6d7e6165 8b7510 mov esi,dword ptr [ebp+10h] <------(esi为cur_length-new_length)
…
vgx!MsoFRemovePx+0x86:
6d7e6168 0fb713 movzx edx,word ptr [ebx] <-------(edx为cur_length)-
6d7e616b 03c6 add eax,esi .
6d7e616d 3bc2 cmp eax,edx .
6d7e616f 741d je vgx!MsoFRemovePx+0xac(6d7e618e)<-------------
...
vgx!MsoFRemovePx+0xac:
6d7e618e 662933 sub word ptr[ebx],si <------cur_length=cur_length-(cur_length-new_length)
6d7e6191 5f pop edi .
6d7e6192 8bc6 mov eax,esi .
6d7e6194 5e pop esi .
6d7e6195 5b pop ebx .
6d7e6196 5d pop ebp .
6d7e6197 c20c00 ret 0Ch <-------------
因此当传入new_length的值为有符号数0xFFFFFFFF时,会导致整数溢出,数组的长度被改写为0xFFFF=65535,但对应的内存却没有被分配。那么就掌握了对内存的控制。
5.此CVE漏洞攻击的主线
(1)使用vml语言
(2)设置stroke.dashstyle=”1 2 3 4 5 6….”转移控制流
(3)对dashstyle.array.length属性进行赋值
(4)步骤3会导致put_length根据新的数组长度对ORG数组重新分配内存
(5)如果步骤3传入的是0xffffffff那么在put_length中会跳转至ORG::DeleteRange,接下来的流程为ORG::DeleteRange-->MsoDeletePx-->MsoFRemovePx。
(6)在MsoFRemovePx函数内部,最终将新赋值的数组长度设置成了current_length,使得在没有重新分配内存的情况下将ORG数组长度current_length改写成0xFFFF。因此,可以通过此时的ORG数组获得越界访问。
(要成功exploit,dashstyle.array.length不能直接设置为0xffffffff,会报错,需要设置为0-1)
- Windbg漏洞分析之CVE-2013-2551
- CVE-2013-2551漏洞分析
- 漏洞分析之CVE-2012-4792(UAF)
- 漏洞分析之CVE-2010-2883(栈溢出)
- CVE-2014-0195漏洞分析
- cve-2012-0158漏洞分析
- cve-2012-1876漏洞分析
- CVE-2010-3333漏洞分析
- CVE-2010-2553漏洞分析
- CVE-2016-1503 漏洞分析
- cve-2011-0027漏洞分析
- CVE-2017-12617漏洞分析
- CVE-2013-4694 WinAmp 5.63 栈溢出漏洞分析
- Android电话拨打权限绕过漏洞(CVE-2013-6272)分析
- CVE 2013-3897 - UAF 漏洞分析学习学习
- PCManFTP v2.0(CVE-2013-4730)漏洞分析报告
- PCManFTP v2.0(CVE-2013-4730)漏洞分析报告
- PCManFTP v2.0(CVE-2013-4730)漏洞分析报告
- C++ 异常
- ubuntu text mode启动
- linux常用命令的常用使用方法---ping
- OpenStack网络指南(12)BGP动态路由
- Oracle 大数据量去重实验
- Windbg漏洞分析之CVE-2013-2551
- mysql 主从配置错误归纳
- Cent OS安装jdk(rpm方式)
- hr与lc的对比
- Win7上安装VS2015以后,VS2013崩溃
- UIwindows 提示框动画显示以及隐藏关闭
- 关于SVM一篇比较全介绍的博文(转)
- Tomcat 进程自动退出问题
- 粗看JavaScript经典指南(第一、二章)