CVE-2017-11826 漏洞分析

作者:binjo

CVE-2017-11826是360捕获的一个在野0day,当时的announcement信息较少,随着研究人员在VirusTotal之类平台发现真实样本后,陆续有分析文章面世,然而对于漏洞本身似乎并没有文章进行深入分析。遂成此文,记录及分享之。
笔者的分析平台基于Windows 7 + Office 2010。笔者假设读者已经阅读过其它分析文章,对该漏洞样本有个大致了解。

Crash现场

真实样本中内嵌了两个docx,一个负责spray heap,一个负责触发漏洞,为了方便调试,我们可以利用oletools工具,先dump出来再单独加载、调试。dump的文件包含OLE头部,使用二进制编辑软件如010Editor去除。
打开该docx文件后,Office崩溃场景如下:

(97c.438): Access violation - code c0000005 (!!! second chance !!!)
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:Program FilesMicrosoft OfficeOffice14wwlib.dll -
eax=088888ec ebx=00000000 ecx=03d50f00 edx=00000004 esi=012b42b0 edi=0128c1dc
eip=5b38962a esp=002f3134 ebp=002f319c iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
wwlib!DllGetClassObject+0xf2e3a:
5b38962a 8b08            mov     ecx,dword ptr [eax]  ds:0023:088888ec=????????

引用寄存器eax时产生异常,查看该语句上下文,可以发现0x088888ec从某个对象+44h处取得,而设置其值就在上面不远处。

5b38960b 8b06            mov     eax,dword ptr [esi]
5b38960d 8b10            mov     edx,dword ptr [eax]
5b38960f 4a              dec     edx
5b389610 4a              dec     edx
5b389611 8bce            mov     ecx,esi
5b389613 e8ee70d4ff      call    wwlib!DllMain+0x3b15 (5b0d0706) // 关键call
5b389618 8b4044          mov     eax,dword ptr [eax+44h]
5b38961b 8b4044          mov     eax,dword ptr [eax+44h]
5b38961e 8b4f44          mov     ecx,dword ptr [edi+44h]
5b389621 894144          mov     dword ptr [ecx+44h],eax        // [[edi+44h]+44h] = [[eax+44h]+44h]
5b389624 8b4744          mov     eax,dword ptr [edi+44h]
5b389627 8b4044          mov     eax,dword ptr [eax+44h]        // eax = [[edi+44h]+44h]
5b38962a 8b08            mov     ecx,dword ptr [eax]  ds:0023:088888ec=????????
5b38962c 50              push    eax
5b38962d ff5104          call    dword ptr [ecx+4]              // 飞向光明之巅!

5b389613(wwlib!DllGetClassObject+0xf2e23)处的call wwlib!DllMain+0x3b15就是关键,其取得的某个对象+44h处应该是个指针,指针指向的对象+44h处便是0x088888ec了。

倒撵猴

为了验证,我们先attach windbg到winword.exe,对其设断,然后再打开触发文件。

(8fc.aa4): Break instruction exception - code 80000003 (first chance)
eax=7ffaf000 ebx=00000000 ecx=00000000 edx=7725ec4b esi=00000000 edi=00000000
eip=771f3c8c esp=01a9fe30 ebp=01a9fe5c iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint:
771f3c8c cc              int     3
0:012> bp wwlib!DllGetClassObject+0xf2e23
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:Program FilesMicrosoft OfficeOffice14wwlib.dll -
0:012> g
Breakpoint 0 hit
eax=039f7800 ebx=00000000 ecx=012b4450 edx=00000004 esi=012b4450 edi=039f79dc
eip=5b389613 esp=00120c40 ebp=00120ca8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
wwlib!DllGetClassObject+0xf2e23:
5b389613 e8ee70d4ff      call    wwlib!DllMain+0x3b15 (5b0d0706)

这时单步进入,慢慢调戏,哦不,调试之。当然看官也可同时在IDA中查看。

.text:318D0706 xxx_retrieve_obj_ptr proc near          ; CODE XREF: sub_318CFA51+2A9↑p
.text:318D0706                                         ; sub_318D0659+1E↑p ...
.text:318D0706                 mov     ecx, [ecx]
.text:318D0708                 mov     eax, [ecx]
.text:318D070A                 cmp     edx, eax
.text:318D070C                 jb      short loc_318D0710
.text:318D070E                 mov     edx, eax
.text:318D0710
.text:318D0710 loc_318D0710:                           ; CODE XREF: xxx_retrieve_obj_ptr+6↑j
.text:318D0710                 mov     eax, [ecx+8]
.text:318D0713                 imul    eax, edx
.text:318D0716                 add     eax, [ecx+0Ch]
.text:318D0719                 add     eax, ecx
.text:318D071B                 retn
.text:318D071B xxx_retrieve_obj_ptr endp

它逻辑很简单,edx是某个index值,ecx经过两次defer后指向一个结构体,返回的是edx对应index值对应的结构体(某个对象)指针。查看内存,可以推断当前存在6个对象,在内存中的大小为0x5c。

0:000> dd poi(ecx) l10/4
039f7800  00000006 00000019 0000005c 00000010
0:000> dd poi(ecx)+10+5c*0 l5c/4
039f7810  0000007d 00000096 0000002e 00000027
039f7820  00000000 00000000 00000000 00000000
039f7830  ffff0000 ffffffff 0000ffff 00000000
039f7840  ffff0000 0000ffff 00000000 00000000
039f7850  00000000 00000000 00000000 00000000
039f7860  00000000 00000000 00000000
0:000> dd poi(ecx)+10+5c*1 l5c/4
039f786c  00000132 00000030 0000002e 00000027
039f787c  00000000 00000000 00000000 00000000
039f788c  ffff0000 ffffffff 0000ffff 00000000
039f789c  ffff0000 0000ffff 00000000 00000000
039f78ac  00000000 00000000 00000000 00000000
039f78bc  00000000 00000000 00000000
0:000> dd poi(ecx)+10+5c*2 l5c/4
039f78c8  000001c7 000001ca 0000002e 00000027
039f78d8  00000000 00000000 00000000 00000000
039f78e8  ffff0000 ffffffff 0000ffff 00000000
039f78f8  ffff0000 0000ffff 00000000 00000000
039f7908  00000000 00000000 00000000 00000000
039f7918  00000000 00000000 00000000
0:000> dd poi(ecx)+10+5c*3 l5c/4
039f7924  0000ffff 0000ffff 0000001a 0000001a
039f7934  00000001 00000000 00000000 00000000
039f7944  ffff0000 ffffffff 0000ffff 00000000
039f7954  ffff0000 0000ffff 00000000 00000000
039f7964  00000000 015006e0 5b694a29 00000000
039f7974  00000000 00000000 00000000
0:000> dd poi(ecx)+10+5c*4 l5c/4
039f7980  0000020a 000000e0 0000002e 00000027
039f7990  00000000 00000000 00000000 00000000
039f79a0  ffff0000 ffffffff 0000ffff 00000000
039f79b0  ffff0000 0000ffff 00000000 00000000
039f79c0  00000000 0148d300 5b2acb04 00000000
039f79d0  00000000 00000000 00000000
0:000> dd poi(ecx)+10+5c*5 l5c/4
039f79dc  0000ffff 0000ffff 0000001a 0000001a
039f79ec  00000000 00000000 00000000 00000000
039f79fc  ffff0000 ffffffff 0000ffff 00000000
039f7a0c  ffff0000 0000ffff 00000000 00000000
039f7a1c  00000000 01500640 5b694a29 00000000
039f7a2c  00000000 00000000 00000000

由前面断下时寄存器edx可知,程序在取得index=4对应的对象后,产生了崩溃,让我们看看这是个什么神仙。

0:000> dd poi(ecx)+10+5c*4 l5c/4
039f7980  0000020a 000000e0 0000002e 00000027
039f7990  00000000 00000000 00000000 00000000
039f79a0  ffff0000 ffffffff 0000ffff 00000000
039f79b0  ffff0000 0000ffff 00000000 00000000
039f79c0  00000000 0148d300 5b2acb04 00000000
039f79d0  00000000 00000000 00000000
0:000> dc 0148d300
0148d300  0000045f 00000000 00000000 00000000  _...............
0148d310  00000000 00000000 00000000 00000000  ................
0148d320  00000000 00000000 0069004c 0063006e  ........L.i.n.c.
0148d330  00720065 00680043 00720061 00680043  e.r.C.h.a.r.C.h.
0148d340  00720061 088888ec 006f0066 0074006e  a.r.....f.o.n.t.
0148d350  0062ff1a 00740061 006e0061 00000067  ..b.a.t.a.n.g...
0148d360  00000000 00000000 00000000 00000000  ................
0148d370  00000000 00000000 00000000 00000000  ................

这时我们发现那个0x088888ec在这对象的+44h处了,对照docx中的样式,我们可以推断这是那个font对象。

<w:body >
<w:shapeDefaults >
<o:OLEObject >
<w:font w:name="LincerCharChar裬࢈font:batang"><o:idmap/>
</o:OLEObject>
</w:shapeDefaults>
</w:body>

不知道客官是否好奇那个结构体数组中其它对象是什么呢,我们再来一探究竟。

0:000> dd poi(ecx)+10+5c*3 l5c/4
039f7924  0000ffff 0000ffff 0000001a 0000001a
039f7934  00000001 00000000 00000000 00000000
039f7944  ffff0000 ffffffff 0000ffff 00000000
039f7954  ffff0000 0000ffff 00000000 00000000
039f7964  00000000 015006e0 5b694a29 00000000
039f7974  00000000 00000000 00000000
0:000> dc 015006e0
015006e0  00000001 00000001 0148cf18 00000009  ..........H.....
015006f0  00000000 00000000 00000000 00000000  ................
01500700  00000000 000004b0 00000000 00000000  ................
01500710  0005003c 00000000 00000000 00000000  <...............
01500720  00000003 01500b40 00000000 614c223d  ....@.P.....="La
01500730  5957c414 00000000 595ffd5c 54484b4c  ..WY....._YLKHT
01500740  75734d43 69727453 614d676e 00000070  CMsuStringMap...
01500750  00000001 01202e98 592c484d 592c4db0  ...... .MH,Y.M,Y
0:000> du 0148cf18 l9
0148cf18  "OLEObject"
0:000> dd poi(ecx)+10+5c*5 l5c/4
039f79dc  0000ffff 0000ffff 0000001a 0000001a
039f79ec  00000000 00000000 00000000 00000000
039f79fc  ffff0000 ffffffff 0000ffff 00000000
039f7a0c  ffff0000 0000ffff 00000000 00000000
039f7a1c  00000000 01500640 5b694a29 00000000
039f7a2c  00000000 00000000 00000000
0:000> dc 01500640
01500640  00000001 00000001 01f86ee0 00000005  .........n......
01500650  00000000 00000000 00000000 00000000  ................
01500660  00000000 000004b0 00000000 00000000  ................
01500670  0005003c 00000000 00000000 00000000  <...............
01500680  00000003 00000000 00000000 2f226179  ............ya"/
01500690  00016b48 55b77748 0001fbd0 55b778c8  Hk..Hw.U.....x.U
015006a0  0000000e 74202261 00000000 00000000  ....a" t........
015006b0  00000000 00000000 00000001 594f9e4c  ............L.OY
0:000> du 01f86ee0 l5
01f86ee0  "idmap"

原来它们分别对应OLEObject和idmap,和xml相呼应。至此,我想客官可以大胆猜上一猜了,Office在解析那段xml时,解析器维护了一段内存来保存解析状态,当处理<o:idmap>时,存在type confusion漏洞,取得了前置font对象内容,且可以被利用来控制寄存器eax,从而控制程序流程。如果<w:font>这个tag正确闭合,可以验证该font对象内容不会存在于那段内存中。

补丁

知道漏洞关键点后,寻找补丁也就顺理成章,不难找到具体位置了。取得对象指针后,再比较了+48h处的指针,如果不对应则跳转了。

.text:31B8960B 8B 01               mov     eax, [ecx]
.text:31B8960D 8B 10               mov     edx, [eax]
.text:31B8960F 4A                  dec     edx
.text:31B89610 4A                  dec     edx
.text:31B89611 E8 E8 70 D4 FF      call    xxx_retrieve_obj_ptr
.text:31B89616 81 78 48 4A 4A E9+  cmp     dword ptr [eax+48h], offset sub_31E94A4A ; patch for CVE-2017-11826
.text:31B8961D 75 1D               jnz     short loc_31B8963C
.text:31B8961F 8B 40 44            mov     eax, [eax+44h]
.text:31B89622 8B 40 44            mov     eax, [eax+44h]
.text:31B89625 8B 4F 44            mov     ecx, [edi+44h]
.text:31B89628 89 41 44            mov     [ecx+44h], eax
.text:31B8962B 8B 47 44            mov     eax, [edi+44h]
.text:31B8962E 8B 40 44            mov     eax, [eax+44h]
.text:31B89631 8B 08               mov     ecx, [eax]
.text:31B89633 50                  push    eax
.text:31B89634 FF 51 04            call    dword ptr [ecx+4]

禅(xian)定(zhe)时刻

正常打开利用文件,咣当崩溃了,这是为啥呢?

(a70.544): Access violation - code c0000005 (!!! second chance !!!)
eax=768a0000 ebx=088883ec ecx=00000000 edx=77206c74 esi=768a0000 edi=08888f70
eip=08889000 esp=08888f70 ebp=08888f70 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
08889000 e893ffffff      call    08888f98

许久没写文章,疏漏在所难免,欢迎到微博联系指正。@binjo_

欢迎转发分享,或者打赏一杯咖啡钱。 🙂

参考

  1. http://360coresec.blogspot.com/2017/10/new-office-0day-cve-2017-11826.html
  2. http://www.freebuf.com/vuls/150607.html
  3. https://securingtomorrow.mcafee.com/mcafee-labs/analyzing-microsoft-office-zero-day-exploit-cve-2017-11826-memory-corruption-vulnerability/
  4. https://github.com/decalage2/oletools