CVE-2010-3974 Microsoft Windows多個平臺Fax Cover Page Editor記憶體破壞漏洞

Ox9A82發表於2016-07-29

        Microsoft Windows Fax Cover Pages用於個性化傳真以及呈現更正式外觀的傳真傳輸。
        Microsoft Windows XP SP2和SP3,Windows Server 2003 SP2,Windows Vista SP1和SP2,Windows Server 2008 Gold,SP2,R2和R2 SP1,以及Windows 7 Gold和SP1的Fax Cover Page Editor中的fxscover.exe沒有正確解析FAX的封面頁。遠端攻擊者可以藉助特製.cov檔案執行任意程式碼。

開啟POC檔案,異常資訊如下

First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=feeefeee ebx=022107a8 ecx=02222dc0 edx=000000c0 esi=02222dc0 edi=00028d30
eip=6a5cb7af esp=0010f33c ebp=0010f33c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
MFC42u!CObject::IsKindOf+0x7:
6a5cb7af 8b10            mov     edx,dword ptr [eax]  ds:0023:feeefeee=????????

這是一個前不著村後不著店的地方,明顯不是漏洞觸發的第一現場。關閉,啟用頁堆重新載入,依然是斷不到第一現場。這個時候想起了之前看《軟體除錯》時學到的姿勢了,連結在這裡http://www.cnblogs.com/Ox9A82/p/5603172.html 果斷去掉hpa帶上ust和hfc。果然可以想泉哥一樣定位到觸發點了。crash時情況如下:

(1d8.ce8): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000000 ecx=778b07ed edx=000ef391 esi=00410000 edi=0041d770
eip=7795280d esp=000ef5e4 ebp=000ef65c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ntdll!RtlReportCriticalFailure+0x29:
7795280d cc              int     3

來看下回溯,如下。一看到ntdll!RtlFreeHeap就知道肯定是hfc起了作用,這個int3 斷點也肯定是hfc丟擲的(即RtlReportCriticalFailure函式)。

0:000> kp
ChildEBP RetAddr  
000ef65c 7795376b ntdll!RtlReportCriticalFailure+0x29
000ef66c 7795384b ntdll!RtlpReportHeapFailure+0x21
000ef6a0 77953ab4 ntdll!RtlpLogHeapFailure+0xa1
000ef6f8 77917ad7 ntdll!RtlpAnalyzeHeapFailure+0x25b
000ef7ec 778e2d68 ntdll!RtlpFreeHeap+0xc6
000ef80c 75f898cd ntdll!RtlFreeHeap+0x142
000ef858 00a8f43a msvcrt!free+0xcd
000ef868 00a8ab0c FXSCOVER!CDrawRoundRect::`scalar deleting destructor'+0x1a
000ef884 00a8b1d4 FXSCOVER!CDrawDoc::Remove+0x96
000ef890 69c68515 FXSCOVER!CDrawDoc::DeleteContents+0xc
000ef898 69c684df MFC42u!CDocument::OnNewDocument+0x15
000ef8a8 00a8a812 MFC42u!COleDocument::OnNewDocument+0xe
000ef8b0 69c683e8 FXSCOVER!CDrawDoc::OnNewDocument+0xa
000ef8dc 69c68598 MFC42u!CSingleDocTemplate::OpenDocumentFile+0x103
000ef96c 00a880fb MFC42u!CDocManager::OnFileNew+0xaa
000ef978 00a894f3 FXSCOVER!CDrawApp::OnFileNew+0xb
000ef9c0 00a88f62 FXSCOVER!CDrawApp::OpenDocumentFile+0x57a
000ef9ec 69c76572 FXSCOVER!CDrawApp::OnFileOpen+0x4a
000ef9fc 69c5a879 MFC42u!_AfxDispatchCmdMsg+0x49
000efa30 69c5b957 MFC42u!CCmdTarget::OnCmdMsg+0x13c

我們看下是不是真的是二次釋放,看下free的引數就知道了。怎麼看呢?我們知道RtlpFreeHeap是windows native層對free的支援。所以看下哪個引數是一樣的就可以知道哪個引數是要釋放的堆地址了。果然,0041d788處於一個已釋放的堆中,顯然這個就是二次釋放漏洞了。

0:000> kv
ChildEBP RetAddr  Args to Child              
000ef65c 7795376b c0000374 7796cdc8 000ef6a0 ntdll!RtlReportCriticalFailure+0x29 (FPO: [Non-Fpo])
000ef66c 7795384b 00000002 76dd4fca 00410000 ntdll!RtlpReportHeapFailure+0x21 (FPO: [Non-Fpo])
000ef6a0 77953ab4 00000003 00410000 0041d770 ntdll!RtlpLogHeapFailure+0xa1 (FPO: [Non-Fpo])
000ef6f8 77917ad7 00410000 0041d770 00000000 ntdll!RtlpAnalyzeHeapFailure+0x25b (FPO: [Non-Fpo])
000ef7ec 778e2d68 0041d770 0041d788 0041d788 ntdll!RtlpFreeHeap+0xc6 (FPO: [Non-Fpo])
000ef80c 75f898cd 00410000 00000000 0041d788 ntdll!RtlFreeHeap+0x142 (FPO: [Non-Fpo])
000ef858 00a8f43a 0041d788 0041d788 000ef884 msvcrt!free+0xcd (FPO: [Non-Fpo])
000ef868 00a8ab0c 00000001 00412e60 031807b8 FXSCOVER!CDrawRoundRect::`scalar deleting destructor'+0x1a (FPO: [Non-Fpo])
000ef884 00a8b1d4 00000000 031807b8 69c68515 FXSCOVER!CDrawDoc::Remove+0x96 (FPO: [Non-Fpo])
000ef890 69c68515 031807b8 69c684df 031807b8 FXSCOVER!CDrawDoc::DeleteContents+0xc (FPO: [Non-Fpo])
000ef898 69c684df 031807b8 031807b8 000ef8dc MFC42u!CDocument::OnNewDocument+0x15 (FPO: [Non-Fpo])
000ef8a8 00a8a812 031807b8 69c683e8 ee921ffd MFC42u!COleDocument::OnNewDocument+0xe (FPO: [Non-Fpo])
000ef8b0 69c683e8 ee921ffd 00412e60 00412eec FXSCOVER!CDrawDoc::OnNewDocument+0xa (FPO: [Non-Fpo])
000ef8dc 69c68598 00000000 00000001 ee921e4d MFC42u!CSingleDocTemplate::OpenDocumentFile+0x103 (FPO: [Non-Fpo])
000ef96c 00a880fb 031807b8 00aa6000 00a894f3 MFC42u!CDocManager::OnFileNew+0xaa (FPO: [Non-Fpo])
000ef978 00a894f3 ee915bf0 00000000 00aa8798 FXSCOVER!CDrawApp::OnFileNew+0xb (FPO: [Non-Fpo])
000ef9c0 00a88f62 00419478 ee915bdc 00000000 FXSCOVER!CDrawApp::OpenDocumentFile+0x57a (FPO: [Non-Fpo])
000ef9ec 69c76572 00000000 00a81de0 000efa30 FXSCOVER!CDrawApp::OnFileOpen+0x4a (FPO: [Non-Fpo])
000ef9fc 69c5a879 00aa8798 0000e101 00000000 MFC42u!_AfxDispatchCmdMsg+0x49 (FPO: [Non-Fpo])
000efa30 69c5b957 0000e101 00000000 00000000 MFC42u!CCmdTarget::OnCmdMsg+0x13c (FPO: [Non-Fpo])
0:000> !heap -p -a 0041d788 
    address 0041d788 found in
    _HEAP @ 410000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        0041d4e0 0101 0000  [00]   0041d4e8    00800 - (free)

 CDrawRoundRect::`scalar deleting destructor'是函式的解構函式,我們可以看到這裡的free都是這個解構函式的呼叫導致的。說明這個堆的二次釋放的原因是因為這個CDrawRoundRect物件被釋放了兩次導致的。

相關文章