office CVE-2017-11826雜談
該漏洞為office中的一處混淆漏洞,相應的poc如下所示:可以看到其中font標簽未閉合。
該漏洞中一個重要的點在於明白對應poc中解析標簽在內存中的結構,如下所示為其中漏洞觸發時的地方,這裏有兩個重要的函數即fun_GettagObject,fun_CalcspectailTagobject,
fun_GettagObject:返回當前tag對象,傳入的參數為一個taglist對象,實際索引依賴於fun_CalcspectailTagobject
fun_CalcspectailTagobject:通過傳入的level層級返回數組中對應的tag對象,如下所示漏洞觸發時使用的正是fun_CalcspectailTagobject返回的Tagobject對象,在poc下該對象被混淆為一個font對象,從而導致後續調用對象虛表函數時的代碼執行。
具體的Taglist/TagObject結構如下所示(這個地方感謝部門魔法師同學的提醒):
如下所示為對應的fun_GettagObject函數,該函數的參數為一個Taglist,首先獲取對應的current_index,之後通過fun_CalcspectailTagobject獲取當前curren_index標記的Tagobject
fun_CalcspectailTagobject,首先比較索引層級和當前層級,之後獲取對應TagObect數組中對應的tag對象,公式為taglist base address + head len + index * tagobject len
如下圖所示為正常對應的Taglist在內存中的布局,頭部長度為0x10,偏移0x0的位置為current_index,之後為對應TagObject arragy,如下所示
將下圖對應到poc中,可以看到此時對應的標簽,由於對象存在數組中,所以實際標簽層級要比數組中大一,這也就是索引時減一的原因。
下圖為漏洞函數的父函數,在處理對應的poc時,font標簽會在fun_copy5_Vul_17_11826中生成並完成對應對象的初始化,然後返回,而對於其余的標簽,如oleobject則在第二個紅框fun_may_TagobjInit中完成初始化,註意初始化時會將taglist中的curren_index+1,如oleobject對象進入漏洞父函數是current_index為3,在fun_may_TagobjInit中完成初始化後變成4(即實際的level,對照上圖),font進入漏洞函數父函數時current_index為4,fun_copy5_Vul_17_11826執行之後為5。
當一個標簽解析完後,會調用以下函數對current_index減一,如正常閉合font標簽的doc中在解析完font後會將current_index減一,之後再進入到idmap的解析流程中,而office中這個減一的過程應該是依賴於結束標簽,至少font標簽如果沒有對應的結束標簽則不會對curren_index減一,這也是導致該漏洞的根本原因(即無閉合標簽,導致fun_may_sub函數未調用,Taglist中的current_index未減一,後續標簽尋址的時出錯)。
通過以下斷點對比正常doc和漏洞poc標簽處理的過程,可以首先下第一個斷點,斷下之後g兩次,然後再下後續的斷點,這樣可以減少大量不必要的斷下。
bp wwlib+0x000861d4 ".printf \"vul_fun\";du poi(poi(esp + 8) + 18) Lpoi(poi(esp + 8) + 1c);dc poi(poi(poi(esp + 4) + b14)) L8"
bp wwlib+0x0003d3fb ".printf \"parent_fun\";du poi(poi(esp + 8) + 18) Lpoi(poi(esp + 8) + 1c);dc poi(poi(poi(poi(esp+4)+b10) + b14)) L8"
bp wwlib+0x0003d5e9 ".printf \"font copy and level+1\\n\""
bp wwlib+0x0004e3a8 ".printf\"tag level+1\\n\""
bp wwlib+0x00033aad ".printf\"font level-1\\n\""
如下圖所示可以看到左右兩邊分別是從處理oleobject開始到漏洞觸發函數正常和不正常的文檔的標簽輸出(左為正常doc,右為poc),其中最大的區別就在於正常情況下font會對current_index中減一,最終到處理idmap時進入漏洞父函數時為4,之後+1=5,最後傳入漏洞函數時為5,而poc中傳入漏洞函數時為6。
回到觸發漏洞時的代碼,此時如果是正常情況,進入idmap是current_index為5,函數fun_CalcspectialTagobject中索引的位置為5-2=3,即Tagobject array[3]的對象,為oleobject對象,但是當運行poc時,current_index為6,6-2=4,即Tagobject array[4]的對象,為font對象,即正常情況上用於處理oleobject對象的代碼,被用於處理font對象,由於這兩個對象在內存中是完全不同的內存布局從而導致代碼執行。
下圖為觸發時通過fun_CalcspectialTagobject返回的Tagobj對象,可以看到該對象就是font對象
下圖為漏洞觸發時對應的Taglist,可以看到正常應該調用時獲取的應該是Tagobject[3]的oleobj對象,由於漏洞導致current_index未減一,通過6-2=4獲取的卻是之後Tagobject[4]中的font對象,反應到之後具體的比特位就是正常應該返回03a07780,卻返回了05696b00
可以看05696b00+44的位置就是poc中攻擊者可控的heap sprey地址,從而導致之後call [ecx+4]時代碼執行,而正常的03a07780+44位置是一處虛表,從而在call [ecx+4]中調用的時正常的函數處理流程。
相關參考:
https://www.anquanke.com/post/id/87122
https://bbs.pediy.com/thread-221995.htm
感謝魔法師的提醒-_-
轉載請註明出處
office CVE-2017-11826雜談