CVE-2016-0143 漏洞分析(2016.4)

CVE-2016-0143漏洞分析算法

0x00 背景

420日,Nils Sommerexploitdb上爆出了一枚新的Windows內核漏洞PoC。該漏洞影響全部版本的Windows操做系統,攻擊者利用成功後可得到權限提高,微軟在4月補丁日修復了該漏洞。shell

 

0x01 漏洞分析

Nils Sommer並無說明該漏洞爲什麼種類型的漏洞,咋看崩潰場景會認爲是NULL Pointer dereference或者UAF漏洞,粗略分析後,以爲是整數溢出漏洞,可是最後仍是將其定義爲特殊的NULL Pointer dereference漏洞。下面對漏洞成因進行簡單分析。函數

 

In xxxRealDrawMenuItem spa

崩潰的地方是在win32k!xxxRealDrawMenuItem函數內,在windbg中查看崩潰時的內存狀態:操作系統

 

崩潰上下文代碼的IDA截圖,將其命名爲過程A(最後說明時會用到): code

 

crash以前,eax會和[ebp+arg_8]作有符號乘法,並將結果和ebx作比較,來肯定是否執行crash的指令。blog

此時的eaxPoCr.bottomr.top運算後的結果,具體操做在win32k!xxxDrawMenuBarTemp內,算法爲:eax= r.bottom-r.top-1; 內存

[ebp+arg_8]PoC中的info.bmiHeader.biSize; it

 

PoC 給的值會讓"imul eax,[ebp+arg_8]"產生溢出,走向crash流程。這裏看起來是因爲整數溢出形成的漏洞,其實正常流程都會走這個流程的,這並非漏洞成因所在。io

 

所操做的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中設定的值,二者分別爲0x7fffff690x274

當二者進行乘法運算後,一樣發生了溢出,但因爲是無符號運算,因此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.bottomr.topinfo.bmiHeader.biWidth知足必定的約束就好了,不必定須要和做者給出PoC的數值徹底相同。r.bottomr.topinfo.bmiHeader.biWidth的值能知足下面兩個條件就能夠致使crash

  1. 過程B分配DIBObject失敗。
  2. 過程A走向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

相關文章
相關標籤/搜索