Search code examples
c++windowsmemoryprocessreadprocessmemory

get the entry point to a 64bit process memory from a 32bit process


I want to get the entry point to a 64bit process I wrote from a 32bit process, the same way you'd use EnumProcessModule and take the memory addr of the main module. My end goal is to read a byte from memory in my 64bit process from an offset to it (entry+Offset).

But my NtWow64ReadVirtualMemory64 function keeps failing. I think it has something to do with my entry memory addr.

    #define PROC_BASIC_INFO 0
    #define NT_WOW64_QUERY_INFORMATION_PROCESS_64_NAME  "NtWow64QueryInformationProcess64"
    #define NT_WOW64_READ_VIRTUAL_MEMORY_64_NAME  "NtWow64ReadVirtualMemory64"

    typedef UINT64 SYM;
    typedef SIZE_T SIZE_T64;

    HWND   WINDOW_HANDLE;
    HANDLE PROC_HANDLE;
    DWORD PROC_ID;
    UINT address;
    UINT64 address64;
    SIZE_T bytesRead;
    SIZE_T64 bytesRead64;

    using namespace std;


    //initialize variables for importing of essential 64 bit reading functions
    //from ntdll
    typedef NTSTATUS(NTAPI *FUNC_NtReadVirtualMemory64)
    ( 
        IN  HANDLE  ProcessHandle,
        IN  PVOID64 BaseAddress,
        OUT PVOID   Buffer,
        IN  ULONGLONG BufferLength,
        OUT PULONGLONG ReturnLength OPTIONAL
    );
    typedef NTSTATUS (NTAPI *FUNC_NtWow64QueryInformationProcess64) 
    (
        IN  HANDLE ProcessHandle,
        IN  ULONG  ProcessInformationClass,
        OUT PVOID  ProcessInformation64,
        IN  ULONG  Length,
        OUT PULONG ReturnLength OPTIONAL
    );

    struct PROCESS_BASIC_INFORMATION64 {

        SYM Reserved1;
        SYM PebBaseAddress;
        SYM Reserved2[2];
        SYM UniqueProcessId;
        SYM Reserved3;
        /*
        NTSTATUS ExitStatus;
        ULONG64 PebBaseAddress;
        ULONG64 AffinityMask;
        LONG    BasePriority;
        UINT64  Reserved1;
        ULONG64 UniqueProcessId;
        ULONG64 InheritedFromUniqueProcessId;
        */
    };



    HINSTANCE ntdll = LoadLibrary("ntdll.dll");
    FUNC_NtWow64QueryInformationProcess64 NtWow64QueryInformationProcess64 = (FUNC_NtWow64QueryInformationProcess64)GetProcAddress(ntdll, NT_WOW64_QUERY_INFORMATION_PROCESS_64_NAME);
    FUNC_NtReadVirtualMemory64 NtReadVirtualMemory64 = (FUNC_NtReadVirtualMemory64)GetProcAddress(ntdll, NT_WOW64_READ_VIRTUAL_MEMORY_64_NAME);

    int Init32To64MemoryRead(const char* windowClass, const char* caption, SYM addressOffset)
    {

        DWORD cbNeeded;
        DWORD dwdResult;
        HMODULE mainModule;
        BOOL enumResult;
        ULONG read_length=0;
        HINSTANCE ntdll; 
        PROCESS_BASIC_INFORMATION64 procInfo;
        ZeroMemory(&procInfo, sizeof(procInfo));



        //Get the window handle
        WINDOW_HANDLE = FindWindow(windowClass, NULL);
        if (WINDOW_HANDLE == NULL)
        {
            //Window was not foud
            return 10;
        }

        //Get the process ID
        dwdResult = GetWindowThreadProcessId(WINDOW_HANDLE, &PROC_ID);

        if (dwdResult == 0)
        {
            //Getting Process ID failed
            return 20;
        }

        //Open the process
        PROC_HANDLE = OpenProcess(PROCESS_ALL_ACCESS, false, PROC_ID);

        if (PROC_HANDLE == NULL)
        {
            //Process failed to open
            return 30;
        }
        DWORD result;

        //Query Proc Information to get .exe entry point
        result = NtWow64QueryInformationProcess64( PROC_HANDLE, 0, &procInfo, sizeof(procInfo), &read_length);
        if (result != 0)
        {
            cerr << "Query Information Process has failed" << endl;

            return 40;
        }

        address64 =  (procInfo.PebBaseAddress + addressOffset);
        cerr << address64 << endl;

        string number;
        stringstream stristream;

        stristream << address64;
        stristream >> number;

        byte testByte = 0;
        (byte)ReadMemory64<byte>(testByte);

        system("PAUSE");
        return 1;
    }


template <typename _ret_t> _ret_t ReadMemory64(_ret_t& ret)
{

    NTSTATUS result = NtReadVirtualMemory64(PROC_HANDLE, (void*)address64, &ret, 8, NULL);
    ///* Debug # when too lazy for breakpoints
    cerr <<"value: " << ret << endl;
    cerr << "Error Code: " << GetLastError() << endl;
    if (result != 0)
    {
        cerr << "ReadMemory Failed.\r\nAddress: " << address64 << "\r\nSize: " << sizeof(_ret_t) << "\r\nResult: " << result << endl;
        cerr << "NtReadVirtualMemory64 has failed" << endl;
        system("PAUSE");

    } //*/
    return ret;
 };

I'd like to know what I am doing wrong.

Edit: Upon further inspection, I noticed that NtWow64ReadVirtualMemory, does not store a value in the variable "ret" used as the buffer.


Solution

  • I ran a simple test and figured out that the value of my buffer-"ret" was not changed when inserted to the function "NtWow64ReadVirtualMemory64".
    The code did compile and run without errors(compile and runtime) except for NtReadMemory64 returning a weird number (there is no documentation available for the ntdll NtWow64 functions, so goolgling it did not yield anything useful).
    So i figured I am either providing a faulty buffer or am not reading from a valid memory addr.

    since I did initialize the buffer explicitly outside of the function, I figured that my problem is the latter(not providing a valid memory address).

    I was using the following when calling NtReadVirtualMemory

    NTSTATUS result = NtReadVirtualMemory64(PROC_HANDLE, (void*)address64, &ret, 8, NULL);
    

    apparently, when calling NtWow64ReadVirtualMemory64, I cast the addr to a 32 bit void pointer (void*)address64 , and since address64 is a UINT64-type , the cast truncated the address, and I was trying to read off of a memory segment I wasn't able to read I resolved it by changing the cast to (PVOID64)address64 which casts it to a native 64bit pointer.

    simpler than I thought, but finding it was hell after days of googling and reviewing the code.

    Edit: this didn't cut it since my address is wrong. I need to get the ".exe"s' entry point through the location of the process' main module in memory.
    looking at the how to now.
    any help is appreciated!