CVE-2016-0143 漏洞分析(2016.4)
CVE-2016-0143漏洞分析
0x00 背景
4月20日,Nils Sommer在exploitdb上爆出了一枚新的Windows內核漏洞PoC。該漏洞影響所有版本的Windows操作系統,攻擊者利用成功后可獲得權限提升,微軟在4月補丁日修復了該漏洞。
?
0x01 漏洞分析
Nils Sommer并沒有說明該漏洞為何種類型的漏洞,咋看崩潰場景會認為是NULL Pointer dereference或者UAF漏洞,粗略分析后,覺得是整數溢出漏洞,但是最后還是將其定義為特殊的NULL Pointer dereference漏洞。下面對漏洞成因進行簡單分析。
?
In xxxRealDrawMenuItem
崩潰的地方是在win32k!xxxRealDrawMenuItem函數內,在windbg中查看崩潰時的內存狀態:
?
崩潰上下文代碼的IDA截圖,將其命名為過程A(最后說明時會用到):
?
在crash之前,eax會和[ebp+arg_8]做有符號乘法,并將結果和ebx做比較,來確定是否執行crash的指令。
此時的eax為PoC中r.bottom和r.top運算后的結果,具體操作在win32k!xxxDrawMenuBarTemp內,算法為:eax= r.bottom-r.top-1;
[ebp+arg_8]為PoC中的info.bmiHeader.biSize;
?
PoC 給的值會讓"imul eax,[ebp+arg_8]"產生溢出,走向crash流程。這里看起來是由于整數溢出造成的漏洞,其實正常流程都會走這個流程的,這并不是漏洞成因所在。
?
所操作的ecx從[ebp+var_28]獲取,原始值為1,[ebp+var_28]本應該為DIBObject的地址,但是在為其分配內存的函數win32k!SURFMEM::bCreateDIB中,并沒有為其分配內存空間,漏洞的關鍵在這里。
下面分析創建DIBObject失敗的原因。
?
In SURFMEM::bCreateDIB
SURFMEM::bCreateDIB的函數調用棧:
xxxDrawMenuBarTemp
????à GreCreateDIBitmapReal
????????àSURFMEM::bCreateDIB
?
在SURFMEM::bCreateDIB函數內有這樣一段代碼,將其命名為過程B:
?
此時eax等于xxxRealDrawMenuItem函數中的edi,[ebp+arg_0]為PoC中的info.bmiHeader.biSize*4,按照PoC中設定的值,兩者分別為0x7fffff69和0x274。
當兩者進行乘法運算后,同樣發生了溢出,但由于是無符號運算,所以edx!=0。調用函數ULongLongAdd后,[ebp+AllocationSize+4]=edx=139h!=0,因此便走向了失敗的流程,不會為DIBObject分配內存,也導致GreCreateDIBitmapReal函數的返回值為0。
?
如果未發生溢出,并且兩者的乘積(+0x154)小于7FFFFFFFh, SURFMEM::bCreateDIB函數就會根據這個乘積(+0x154)為DIBObject分配一塊內存。分配內存的代碼在IDA中的截圖:
分配成功后,會將AllocateObject的返回值作為GreCreateDIBitmapReal函數返回值,并且賦值給xxxRealDrawMenuItem 函數中的[ebp+var_28]。
?
0x02 補丁對比
來看看微軟是怎么來補這個漏洞的,補丁后的部分xxxRealDrawMenuItem函數代碼在IDA中的截圖:
可以看到,補丁后,xxxRealDrawMenuItem函數在調用GreCreateDIBitmapReal函數后,對返回值做了檢查:如果返回值等于0,表示創建DIBObject失敗,則不會再進入到操作DIBObject的流程,也就是過程A中了。
0x03 可能的利用
目前還沒有人公開自己的利用代碼,下面對該漏洞存在的可能利用方式做一個說明。
crash處是一個對ecx進行循環操作的代碼段,循環次數為"imul eax,[ebp+arg_8]"的乘積。正常情況下是對申請的DIBObject進行操作。
這個循環操作中,存在一個可控的寫入操作指令,在IDA中的截圖:
紅框中的指令就是所說的寫入操作指令,edx雖然經歷多條指令操作后才得到,但是參與操作的都是ecx相關內存值,因為ecx也就是零頁地址的內容可控,所以edx也是可控的。
那么理論情況下,在win8之前的系統中,是可以將這條指令操作轉變為:
mov [HalDispatchTable+4],shellcodeAddress
之后用戶層再觸發一下就完成了提權。
0x04 其他
經過深入分析后,要觸發漏洞,r.bottom、r.top和info.bmiHeader.biWidth滿足一定的約束就行了,不一定需要和作者給出PoC的數值完全相同。r.bottom、r.top和info.bmiHeader.biWidth的值能滿足下面兩個條件就可以導致crash:
過程B和過程A要滿足這兩個條件,具體情況如下。
?
過程B
1. 過程B未發生溢出,并且乘積后的值 < 0x7FFFFFFF,造成AllocateObject調用失敗。
2. 過程B未發生溢出,并且乘積后的值 > 0x7FFFFFFF,不走調用AllocateObject的流程。
3. 過程B發生溢出,不走調用AllocateObject的流程。
?
過程A
1.未溢出。
2.溢出后的結果為負數,并且改變sf位為1(有符號數比較)。
根據上面分析給出的過程A和過程B會導致crash的情況,這里給出兩種具體的組合,有興趣的可以修改原PoC中對應的值嘗試一下,都會crash的。
組合1
過程B情況1+過程A的情況1,兩個地方都沒有溢出,但是還是crash了,也說明了不是整數溢出漏洞。
組合2
過程B情況3+過程A情況2:
by:會飛的貓
轉載請注明:http://www.cnblogs.com/flycat-2016
轉載于:https://www.cnblogs.com/flycat-2016/p/5449769.html
總結
以上是生活随笔為你收集整理的CVE-2016-0143 漏洞分析(2016.4)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: servle 3.0 新特性之一 对上传
- 下一篇: 【iCore3 双核心板_ uC/OS-