Last active
September 12, 2024 05:53
-
-
Save hasherezade/87158b926e33418f5d3b0a0026d0ccc2 to your computer and use it in GitHub Desktop.
Get PEB64 from a WOW64 process
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Windows.h> | |
#include <iostream> | |
#include "ntdll_undoc.h" | |
PPEB get_default_peb() | |
{ | |
#if defined(_WIN64) | |
return (PPEB)__readgsqword(0x60); | |
#else | |
return (PPEB)__readfsdword(0x30); | |
#endif | |
} | |
PPEB64 get_peb64(HANDLE hProcess, OUT PROCESS_BASIC_INFORMATION_WOW64 &pbi64) | |
{ | |
if (NtWow64QueryInformationProcess64 == nullptr) { | |
return nullptr; | |
} | |
//reset structure: | |
memset(&pbi64,0, sizeof(PROCESS_BASIC_INFORMATION_WOW64)); | |
ULONG outLength = 0; | |
NTSTATUS status = NtWow64QueryInformationProcess64( | |
hProcess, | |
ProcessBasicInformation, | |
&pbi64, | |
sizeof(PROCESS_BASIC_INFORMATION_WOW64), | |
&outLength | |
); | |
if (status != STATUS_SUCCESS) { | |
return nullptr; | |
} | |
return (PPEB64) pbi64.PebBaseAddress; | |
} | |
int main() | |
{ | |
BOOL isWow64 = FALSE; | |
IsWow64Process(GetCurrentProcess(), &isWow64); | |
std::cout << "IsWow64" << " : " << isWow64 << std::endl; | |
if (init_ntdll_func(isWow64) == false) { | |
printf("Cannot load functions!\n"); | |
return -1; | |
} | |
PPEB myPeb = get_default_peb(); | |
std::cout << "PEB: \t" ; | |
std::cout << std::hex << myPeb << std::endl; | |
PPEB64 pebWow64 = nullptr; | |
if (isWow64) { | |
PROCESS_BASIC_INFORMATION_WOW64 pbi64 = { 0 }; | |
pebWow64 = get_peb64(GetCurrentProcess(), pbi64); | |
if (pebWow64 == nullptr) { | |
std::cerr << "Fetching PEB64 failed!" << std::endl; | |
return -1; | |
} | |
std::cout << "PEB64:\t" ; | |
std::cout << std::hex << pebWow64 << std::endl; | |
} | |
std::cout << "ImageBaseAddress from PEB: \t" << std::hex << myPeb->ImageBaseAddress << std::endl; | |
if (pebWow64 != nullptr) { | |
std::cout << "ImageBaseAddress from PEB64: \t" << std::hex << pebWow64->ImageBaseAddress << std::endl; | |
} | |
system("pause"); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "ntdll_undoc.h" | |
NTSTATUS (NTAPI *RtlCreateProcessParametersEx)( | |
_Out_ PRTL_USER_PROCESS_PARAMETERS *pProcessParameters, | |
_In_ PUNICODE_STRING ImagePathName, | |
_In_opt_ PUNICODE_STRING DllPath, | |
_In_opt_ PUNICODE_STRING CurrentDirectory, | |
_In_opt_ PUNICODE_STRING CommandLine, | |
_In_opt_ PVOID Environment, | |
_In_opt_ PUNICODE_STRING WindowTitle, | |
_In_opt_ PUNICODE_STRING DesktopInfo, | |
_In_opt_ PUNICODE_STRING ShellInfo, | |
_In_opt_ PUNICODE_STRING RuntimeData, | |
_In_ ULONG Flags // pass RTL_USER_PROC_PARAMS_NORMALIZED to keep parameters normalized | |
) = nullptr; | |
NTSTATUS (NTAPI *NtWow64ReadVirtualMemory64)( | |
IN HANDLE ProcessHandle, | |
IN PVOID64 BaseAddress, | |
OUT PVOID Buffer, | |
IN ULONG64 Size, | |
OUT PULONG64 NumberOfBytesRead | |
) = nullptr; | |
NTSTATUS (NTAPI *NtWow64QueryInformationProcess64) ( | |
IN HANDLE ProcessHandle, | |
IN PROCESSINFOCLASS ProcessInformationClass, | |
OUT PVOID ProcessInformation, | |
IN ULONG ProcessInformationLength, | |
OUT PULONG ReturnLength OPTIONAL | |
) = nullptr; | |
bool init_wow64_func(HMODULE lib) | |
{ | |
if (lib == nullptr) { | |
return false; | |
} | |
FARPROC proc = GetProcAddress(lib, "NtWow64ReadVirtualMemory64"); | |
if (proc == nullptr) { | |
return false; | |
} | |
NtWow64ReadVirtualMemory64 = (NTSTATUS (NTAPI *)( | |
HANDLE, | |
PVOID64, | |
PVOID, | |
ULONG64, | |
PULONG64 | |
)) proc; | |
proc = GetProcAddress(lib, "NtWow64QueryInformationProcess64"); | |
if (proc == nullptr) { | |
return false; | |
} | |
NtWow64QueryInformationProcess64 = (NTSTATUS (NTAPI *)( | |
HANDLE, | |
PROCESSINFOCLASS, | |
PVOID, | |
ULONG, | |
PULONG | |
)) proc; | |
return true; | |
} | |
bool init_ntdll_func(BOOL isWow64) | |
{ | |
HMODULE lib = LoadLibraryA("ntdll.dll"); | |
if (lib == nullptr) { | |
return false; | |
} | |
FARPROC proc = GetProcAddress(lib, "RtlCreateProcessParametersEx"); | |
if (proc == nullptr) { | |
return false; | |
} | |
RtlCreateProcessParametersEx = (NTSTATUS (NTAPI *)( | |
PRTL_USER_PROCESS_PARAMETERS*, | |
PUNICODE_STRING, | |
PUNICODE_STRING, | |
PUNICODE_STRING, | |
PUNICODE_STRING, | |
PVOID, | |
PUNICODE_STRING, | |
PUNICODE_STRING, | |
PUNICODE_STRING, | |
PUNICODE_STRING, | |
ULONG | |
)) proc; | |
if (isWow64) { | |
if (!init_wow64_func(lib)) { | |
return false; | |
} | |
} | |
return true; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <Windows.h> | |
#include "ntddk.h" | |
#include "ntdll_types.h" | |
//Structures: | |
typedef struct _PROCESS_BASIC_INFORMATION_WOW64 | |
{ | |
NTSTATUS ExitStatus; | |
ULONG64 PebBaseAddress; | |
ULONG64 AffinityMask; | |
KPRIORITY BasePriority; | |
ULONG64 UniqueProcessId; | |
ULONG64 InheritedFromUniqueProcessId; | |
} PROCESS_BASIC_INFORMATION_WOW64, *PPROCESS_BASIC_INFORMATION_WOW64; | |
typedef struct _UNICODE_STRING_WOW64 { | |
USHORT Length; | |
USHORT MaximumLength; | |
PVOID64 Buffer; | |
} UNICODE_STRING_WOW64; | |
// PEB 64: | |
typedef struct _PEB64 { | |
BYTE Reserved[16]; | |
PVOID64 ImageBaseAddress; | |
PVOID64 LdrData; | |
PVOID64 ProcessParameters; | |
} PEB64, *PPEB64; | |
typedef struct _CURDIR64 | |
{ | |
UNICODE_STRING_WOW64 DosPath; | |
HANDLE Handle; | |
} CURDIR64, *PCURDIR64; | |
typedef struct _RTL_USER_PROCESS_PARAMETERS64 | |
{ | |
ULONG MaximumLength; // Should be set before call RtlCreateProcessParameters | |
ULONG Length; // Length of valid structure | |
ULONG Flags; // Currently only PPF_NORMALIZED (1) is known: | |
// - Means that structure is normalized by call RtlNormalizeProcessParameters | |
ULONG DebugFlags; | |
PVOID64 ConsoleHandle; // HWND to console window associated with process (if any). | |
ULONG ConsoleFlags; | |
DWORD64 StandardInput; | |
DWORD64 StandardOutput; | |
DWORD64 StandardError; | |
CURDIR64 CurrentDirectory; // Specified in DOS-like symbolic link path, ex: "C:/WinNT/SYSTEM32" | |
UNICODE_STRING_WOW64 DllPath; // DOS-like paths separated by ';' where system should search for DLL files. | |
UNICODE_STRING_WOW64 ImagePathName; // Full path in DOS-like format to process'es file image. | |
UNICODE_STRING_WOW64 CommandLine; // Command line | |
PVOID64 Environment; // Pointer to environment block (see RtlCreateEnvironment) | |
ULONG StartingX; | |
ULONG StartingY; | |
ULONG CountX; | |
ULONG CountY; | |
ULONG CountCharsX; | |
ULONG CountCharsY; | |
ULONG FillAttribute; // Fill attribute for console window | |
ULONG WindowFlags; | |
ULONG ShowWindowFlags; | |
UNICODE_STRING_WOW64 WindowTitle; | |
UNICODE_STRING_WOW64 DesktopInfo; // Name of WindowStation and Desktop objects, where process is assigned | |
UNICODE_STRING_WOW64 ShellInfo; | |
UNICODE_STRING_WOW64 RuntimeData; | |
RTL_DRIVE_LETTER_CURDIR CurrentDirectores[0x20]; | |
ULONG EnvironmentSize; | |
} RTL_USER_PROCESS_PARAMETERS64, *PRTL_USER_PROCESS_PARAMETERS64; | |
//Functions: | |
extern NTSTATUS (NTAPI *RtlCreateProcessParametersEx)( | |
_Out_ PRTL_USER_PROCESS_PARAMETERS *pProcessParameters, | |
_In_ PUNICODE_STRING ImagePathName, | |
_In_opt_ PUNICODE_STRING DllPath, | |
_In_opt_ PUNICODE_STRING CurrentDirectory, | |
_In_opt_ PUNICODE_STRING CommandLine, | |
_In_opt_ PVOID Environment, | |
_In_opt_ PUNICODE_STRING WindowTitle, | |
_In_opt_ PUNICODE_STRING DesktopInfo, | |
_In_opt_ PUNICODE_STRING ShellInfo, | |
_In_opt_ PUNICODE_STRING RuntimeData, | |
_In_ ULONG Flags // pass RTL_USER_PROC_PARAMS_NORMALIZED to keep parameters normalized | |
); | |
//for 32bit process on 64bit system: | |
extern NTSTATUS (NTAPI *NtWow64ReadVirtualMemory64)( | |
IN HANDLE ProcessHandle, | |
IN PVOID64 BaseAddress, | |
OUT PVOID Buffer, | |
IN ULONG64 Size, | |
OUT PULONG64 NumberOfBytesRead | |
); | |
extern NTSTATUS (NTAPI *NtWow64QueryInformationProcess64) ( | |
IN HANDLE ProcessHandle, | |
IN PROCESSINFOCLASS ProcessInformationClass, | |
OUT PVOID ProcessInformation, | |
IN ULONG ProcessInformationLength, | |
OUT PULONG ReturnLength OPTIONAL | |
); | |
// Initialization function: | |
bool init_ntdll_func(BOOL isWow64); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
hi there,
Thank you for sharing your code.
Just a slight error I think for main.cpp line 17,18
if (NtWow64QueryInformationProcess64 == nullptr) { return false;
it should be
if (NtWow64QueryInformationProcess64 == nullptr) { return nullptr;