0

I know that there are other people that have asked this question but it seems as though none of them reached a satisfying or understandable conclusion. I can't use what isn't answered. I am not quite sure what the problem is and I have tried various different solutions with no success so here is my code:

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION, FALSE, (DWORD)7312);

    if(hProc == NULL)
    {
        cout << "Error: " << GetLastError() << endl;
    }

    HANDLE token;

    OpenProcessToken(hProc, TOKEN_ALL_ACCESS, &token);

    void *baseAddr = VirtualAllocEx(hProc, NULL, 500, MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    if(baseAddr == NULL)
    {
        cout << "VirtualAllocEx has failed" << endl;
    }
    else
    {
        cout << "Base Address: " << baseAddr << "\n" << endl;
    }

    DWORD prevProt;

    if(VirtualProtectEx(hProc, &baseAddr, sizeof(DWORD), PAGE_EXECUTE_READWRITE, &prevProt) == 0)
    {
        if(GetLastError() == 87)
        {
            cout << "ERROR_INVALID_PARAMETER\n" << endl;
        }
        else if(GetLastError() == 487)
        {
            cout << "ERROR_INVALID_ADDRESS\n" << endl;
        }
    }

    void *buffer;

    if(ReadProcessMemory(hProc, baseAddr, &buffer, sizeof(SIZE_T), NULL) == 0)
    {
        if(GetLastError() == 299)
        {
            cout << "ERROR_PARTIAL_COPY" << endl;
        }
    }
}

Any contribution and knowledge you can offer is deeply appreciated! :)

David Leon
  • 11
  • 1
  • 4
  • Do you have a 32 bit process and a 64 bit target? – David Heffernan Jan 07 '16 at 05:59
  • Bare with me here because I really don't know much about how memory works, but I don't know the difference. – David Leon Jan 07 '16 at 06:22
  • @DavidLeon: what exactly are you trying to accomplish with this code in the first place? – Remy Lebeau Jan 07 '16 at 06:23
  • I was curious about how decompilation works and such so I'm testing this out on some screen capturing software I made. – David Leon Jan 07 '16 at 06:38
  • To simply read another process's compiled code, you don't need to use `VirtualAllocEx()` and `VirtualProtectEx()` at all. Simply allocate a local buffer big enough to receive the code, and then `ReadProcessMemory()` into that buffer. Code can be large, so you will likely have to read it in chunks. As for the base address of the code, you will have to read and parse the remote process's PE header to discover where the code is located in memory. Then you can disassemble it manually as needed. – Remy Lebeau Jan 07 '16 at 19:42
  • Your buffer is not initialized `void *buffer;`, that's why you get the error. – LPVOID May 28 '21 at 15:17

2 Answers2

3

I see some issues with your code.

  1. Bad error handling. If an error happens, you log it, but keep going forward with bad data. If an error happens, STOP. And you are misusing GetLastError().

  2. You are passing the wrong base addess to VirtualProtectEx(). &baseAddr neds to be baseAddr instead. Also, you are allocating and protecting the memory with EXECUTE permissions, which you should not be using unless you intend to store executable code in the memory (which this code is not doing).

  3. You are using sizeof(DWORD) to set protection flags on the remote memory, but you are using sizeof(SIZE_T) to read the memory. DWORD is a fixed 32 bits in size, but SIZE_T is 32 or 64 bits, depending on the platform you are compiling for. Change SIZE_T to DWORD to match the rest of your code.

  4. You are not allocating any memory in the calling process for ReadProcessMemory() to write to. Change void *buffer; to DWORD buffer;.

Try this:

#include <windows.h>
#include <iostream>
using namespace std;

int main()
{
    DWORD dwError;

    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION, FALSE, (DWORD)7312);
    if (hProc == NULL)
    {
        dwError = GetLastError();
        cout << "OpenProcess has failed. Error: " << dwError << endl;
        return 0;
    }

    HANDLE token;
    if (!OpenProcessToken(hProc, TOKEN_ALL_ACCESS, &token))
    {
        dwError = GetLastError();
        cout << "OpenProcessToken has failed. Error: " << dwError << endl;
        return 0;
    }

    void *baseAddr = VirtualAllocEx(hProc, NULL, 500, MEM_RESERVE, PAGE_READWRITE);
    if (baseAddr == NULL)
    {
        dwError = GetLastError();
        cout << "VirtualAllocEx has failed. Error: " << dwError << endl;
        return 0;
    }

    cout << "Base Address: " << baseAddr << endl;

    DWORD prevProt;
    if (!VirtualProtectEx(hProc, baseAddr, sizeof(DWORD), PAGE_READWRITE, &prevProt))
    {
        dwError = GetLastError();
        cout << "VirtualAllocEx has failed. Error: ";
        if (dwError == ERROR_INVALID_PARAMETER)
        {
            cout << "ERROR_INVALID_PARAMETER";
        }
        else if (dwError == ERROR_INVALID_ADDRESS)
        {
            cout << "ERROR_INVALID_ADDRESS";
        }
        else
        {
            cout << dwError;
        }
        cout << endl;
        return 0;
    }

    DWORD buffer;
    if (ReadProcessMemory(hProc, baseAddr, &buffer, sizeof(DWORD), NULL))
    {
        dwError = GetLastError();
        cout << "ReadProcessMemory has failed. Error: ";
        if (dwError == ERROR_PARTIAL_COPY)
        {
            cout << "ERROR_PARTIAL_COPY";
        }
        else
        {
            cout << dwError;
        }
        cout << endl;
        return 0;
    }

    cout << "Value: " << buffer << endl;
    return 0;
}

Some more issues:

  1. You are reserving memory in the remote process, but you are not committing physical storage for that memory, and you are not writing anything into the memory before reading from it. Reading reserved uncommitted memory is not very useful, and is the likely culprit of your error:

    https://stackoverflow.com/a/4457745/65863

    ReadProcessMemory would return FALSE and GetLastError would return ERROR_PARTIAL_COPY when the copy hits a page fault.

    Working Set

    When a process references pageable memory that is not currently in its working set, a page fault occurs.

  2. You are not using the token returned by OpenProcessToken(), so that call is useless.

  3. You are protecting the remote memory with VirtualProtectEx() using the same protection flags you specified when allocating the memory. So this call is useless, too.

Community
  • 1
  • 1
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • I did all the stuff you said and it still says `ERROR_PARTIAL_COPY`. – David Leon Jan 07 '16 at 06:09
  • 1
    http://stackoverflow.com/a/4457745/65863: "*ReadProcessMemory would return FALSE and GetLastError would return ERROR_PARTIAL_COPY when the copy hits a page fault.*" – Remy Lebeau Jan 07 '16 at 06:21
1

The expression &buffer is wrong - ReadProcessMemory won't allocate buffer for you, it will write on the buffer you provide. You need to allocate memory, and pass that buffer to ReadProcessMemory. Possible approach:

void *buffer = new BYTE[512];
ReadProcessMemory(hProc, baseAddr, buffer, sizeof(SIZE_T), NULL);
Ajay
  • 18,086
  • 12
  • 59
  • 105