簡介
漏洞編號:cve-2016-7193 漏洞類型:堆溢出 軟件名稱:Office 模塊名稱:wwlib 歷史漏洞:較多 影響的版本 攻擊利用:APT 攻擊利器-Word 漏洞 CVE-2016-7193 原理揭秘
操作環境
系統:Win10 1607 軟件版本:Office2016 16.0.4266.1003 poc:cve-2016-7193.rtf 工具:Process Monitor、windbg、IDA
分析
文件格式分析:樣本經過博主進行簡化,經過控制字運行分開運行之后發現 \dfrxst9(具有長度字節的 Unicode 字符數組)和 *\shpinst(RTF 用于繪圖對象)控制字是觸發漏洞的原因之一
原因分析
崩潰點分析
開啟堆調試載入文檔后引發異常,可見 eax 指向了未知地址導致了異常 從 IDA 分析崩潰點可以看出 mov ecx, [eax] 是取出了對象的虛表,并且調用了虛表 +1C 位置的函數
逆向分析(基地址:0x66730000)
經過逆向分析之后,得出 wwlib 在解析包含數字的 dfrxst 控制字時會在 wwlib!PTLS7::FsUpdateFinitePage+0x6d181(66a16efc) 地址上調用 sub_66a16c81 函數對數字進行處理。例如 langfe1024 控制字的數字為 1024,ASCII 為 0x31 0x30 0x32 0x34,在此基礎上減去 0x30 得出 1 0 2 4,然后經過 ((((1) * a) * a + 2) * a + 4) 公式計算得出為 0x400,暫時稱這個值為 “dfrxst 控制字后數字運算值” 在 wwlib!PTLS7::FsUpdateFinitePage+0x7a9c0(66A2473B) 地址上將 “dfrxst 控制字后數字運算值” 循環寫入 v126 + v13 + 0x8FA0 這個地址,暫時將這個地址中的數據結構稱為 “dfrxst 控制字后數字運算值數組” 在 wwlib!PTLS7::FsUpdateFinitePage+0x74113(66a1de8e) 地址中將 v257[0x8FC4] 傳入 sub_669e393f 函數,v257 變量中的值實際上指向上面的 v126 + v13 計算后得出的地址 在 wwlib!PTLS7::FsUpdateFinitePage+0x39dc0(669E3B3B) 地址中會將之前 v257[0x8FC4] 往后的數據寫入到 TLS(0x1e) 中指定的地址,方便后面取出 在 wwlib!PTLS7::FsDestroySubpageBreakRecord+0x10920(669477DD) 地址中會取出上面 TLS(0x1e) 的地址 在 wwlib!PTLS7::FsDestroySubpageBreakRecord+0xbfdd(66942E9A) 地址上會取出 “dfrxst 控制字后數字運算值數組” +0x24 偏移的數據,調試時值為 0x09c00c0c 然后調用 MSO_557 函數取出 0x09c00c0c + 0x48 地址的值,因為沒有堆噴射,所以值為 0x00000000,最后在調用 mov ecx, [eax] 指令從 0x00000000 地址取值時崩潰
根本原因
由于 wwlib!PTLS7::FsUpdateFinitePage+0x7a9c0(66A2473B) 地址上循環調用 swtich case 138 分支將 “dfrxst 控制字后數字運算值” 寫入 v126 + v13 + 0x8FA0 地址時并沒有控制循環的次數,導致只要存在足夠多的帶數字的控制字,就會造成堆中的數據溢出 以下為寫入前的 “dfrxst 控制字后數字運算值數組” 結構,可以看到 +0x24 的地方是一個數據結構,值為 0x56f30f90
56 bc1450 00000009 00000000 00000000 00000000
56 bc1460 00000000 00000000 00000000 00000000
56 bc1470 00000001 56f 30f90 00000000 00000000
56 bc1480 00000000 00000000 00000000 00000000
56 bc1490 00000000 00000000 00000000 00000000
56 bc14a0 00000000 00000000 00000000 00000000
56 bc14b0 00000000 00000000 00000000 00000000
56 bc14c0 56f 30f90 00000000 00000000 00000001
在持續寫入之后會造成溢出,可以看出 0x56f30f90 變成了 0x09c00c0c。至于為什么 +0x20 的地方沒有變化,因為這是一個 int 變量,用于統計寫入的字節大小,并且在寫入之后進行更新
56 bc1450 0 c0cc009 0 c09c00c 0 c09c00c 0 c09c00d
56 bc1460 0 bc0090c 15172018 09 c00c0c 200 c09c0
56 bc1470 00000028 09 c00c0c 00000000 00000000
56 bc1480 00000000 00000000 00000000 00000000
56 bc1490 00000000 00000000 00000000 00000000
56 bc14a0 00000000 00000000 00000000 00000000
56 bc14b0 00000000 00000000 00000000 00000000
56 bc14c0 56f 30f90 00000000 00000000 00000001
構建與利用
構建流程
只要存在足夠多的 dfrxst[數字] 控制字就會造成堆中數據溢出
利用姿勢
使用堆噴射技術將載荷噴射到 0x09c00c0c + 0x48 地址左右就可以進行利用,也可以手動修改 0x09c00c0c 地址
緩解
補丁:https://learn.microsoft.com/en-us/security-updates/securitybulletins/2016/ms16-121
參考
https://paper.seebug.org/288/ https://bbs.kanxue.com/thread-221792.htm