Skip to content

Instantly share code, notes, and snippets.

@hasherezade
Last active July 21, 2025 11:35
Show Gist options
  • Select an option

  • Save hasherezade/87158b926e33418f5d3b0a0026d0ccc2 to your computer and use it in GitHub Desktop.

Select an option

Save hasherezade/87158b926e33418f5d3b0a0026d0ccc2 to your computer and use it in GitHub Desktop.

Revisions

  1. hasherezade revised this gist Nov 17, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion main.cpp
    Original file line number Diff line number Diff line change
    @@ -15,7 +15,7 @@ PPEB get_default_peb()
    PPEB64 get_peb64(HANDLE hProcess, OUT PROCESS_BASIC_INFORMATION_WOW64 &pbi64)
    {
    if (NtWow64QueryInformationProcess64 == nullptr) {
    return false;
    return nullptr;
    }
    //reset structure:
    memset(&pbi64,0, sizeof(PROCESS_BASIC_INFORMATION_WOW64));
  2. hasherezade revised this gist Dec 21, 2017. 1 changed file with 5 additions and 3 deletions.
    8 changes: 5 additions & 3 deletions main.cpp
    Original file line number Diff line number Diff line change
    @@ -5,9 +5,11 @@

    PPEB get_default_peb()
    {
    PTEB myTeb = NtCurrentTeb();
    PPEB myPeb = myTeb->ProcessEnvironmentBlock;
    return myPeb;
    #if defined(_WIN64)
    return (PPEB)__readgsqword(0x60);
    #else
    return (PPEB)__readfsdword(0x30);
    #endif
    }

    PPEB64 get_peb64(HANDLE hProcess, OUT PROCESS_BASIC_INFORMATION_WOW64 &pbi64)
  3. hasherezade created this gist Dec 21, 2017.
    67 changes: 67 additions & 0 deletions main.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,67 @@
    #include <Windows.h>

    #include <iostream>
    #include "ntdll_undoc.h"

    PPEB get_default_peb()
    {
    PTEB myTeb = NtCurrentTeb();
    PPEB myPeb = myTeb->ProcessEnvironmentBlock;
    return myPeb;
    }

    PPEB64 get_peb64(HANDLE hProcess, OUT PROCESS_BASIC_INFORMATION_WOW64 &pbi64)
    {
    if (NtWow64QueryInformationProcess64 == nullptr) {
    return false;
    }
    //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;
    }
    95 changes: 95 additions & 0 deletions ntdll_undoc.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,95 @@
    #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;
    }
    111 changes: 111 additions & 0 deletions ntdll_undoc.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,111 @@
    #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);