【问题标题】:Function ReadProcessMemory keeps returning ERROR_PARTIAL_COPY函数 ReadProcessMemory 不断返回 ERROR_PARTIAL_COPY
【发布时间】:2016-11-09 07:21:42
【问题描述】:

我知道还有其他人问过这个问题,但似乎他们都没有得出令人满意或可以理解的结论。我不能使用没有回答的东西。我不太确定问题出在哪里,我尝试了各种不同的解决方案但没有成功,所以这是我的代码:

#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;
        }
    }
}

非常感谢您提供的任何贡献和知识! :)

【问题讨论】:

  • 你有 32 位进程和 64 位目标吗?
  • 这里只和我一起,因为我真的不太了解内存是如何工作的,但我不知道其中的区别。
  • @DavidLeon:你到底想用这段代码完成什么?
  • 我很好奇反编译是如何工作的,所以我正在我制作的一些屏幕捕获软件上进行测试。
  • 要简单地读取另一个进程的编译代码,您根本不需要使用VirtualAllocEx()VirtualProtectEx()。只需分配一个足够大的本地缓冲区来接收代码,然后将ReadProcessMemory() 放入该缓冲区。代码可能很大,因此您可能必须分块阅读。至于代码的基地址,您将不得不读取并解析远程进程的 PE 标头以发现代码在内存中的位置。然后可以根据需要手动拆解。

标签: c++ winapi dll-injection


【解决方案1】:

我发现您的代码存在一些问题。

  1. 错误处理错误。如果发生错误,您会记录它,但继续处理错误数据。如果发生错误,请停止。而且你在滥用GetLastError()

  2. 您将错误的基本地址传递给VirtualProtectEx()&amp;baseAddr 需要改为 baseAddr。此外,您正在使用EXECUTE 权限分配和保护内存,除非您打算在内存中存储可执行代码(此代码没有这样做),否则您不应使用该权限。

  3. 您正在使用sizeof(DWORD) 在远程内存上设置保护标志,但您正在使用sizeof(SIZE_T) 来读取内存。 DWORD 的大小是固定的 32 位,但 SIZE_T 是 32 位或 64 位,具体取决于您编译的平台。将 SIZE_T 更改为 DWORD 以匹配您的其余代码。

  4. 您没有在调用进程中分配任何内存供ReadProcessMemory() 写入。将void *buffer; 更改为DWORD buffer;

试试这个:

#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;
}

还有一些问题:

  1. 您在远程进程中保留内存,但您没有提交该内存的物理存储,并且在读取内存之前您没有向内存写入任何内容.读取保留的未提交内存不是很有用,并且可能是您的错误的罪魁祸首:

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

    ReadProcessMemory 将返回 FALSE,GetLastError 将返回 ERROR_PARTIAL_COPY当副本遇到页面错误时

    Working Set

    当进程引用当前不在其工作集中的可分页内存时,会发生页面错误

  2. 你没有使用OpenProcessToken()返回的token,所以调用没用。

  3. 您正在通过VirtualProtectEx() 使用分配内存时指定的相同保护标志来保护远程内存。所以这个调用也没用。

【讨论】:

  • 我做了你说的所有事情,但它仍然显示ERROR_PARTIAL_COPY
  • stackoverflow.com/a/4457745/65863: "当副本遇到页面错误时,ReadProcessMemory 将返回 FALSE,GetLastError 将返回 ERROR_PARTIAL_COPY。"
【解决方案2】:

表达式&amp;buffer 是错误的 - ReadProcessMemory 不会为您分配缓冲区,它会写入您提供的缓冲区。您需要分配内存,并将该缓冲区传递给ReadProcessMemory。可能的方法:

void *buffer = new BYTE[512];
ReadProcessMemory(hProc, baseAddr, buffer, sizeof(SIZE_T), NULL);

【讨论】:

  • 仍然返回ERROR_PARTIAL_COPY,但感谢您纠正我。
猜你喜欢
  • 2021-01-15
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
  • 2011-11-04
  • 2014-06-29
  • 2019-09-28
相关资源
最近更新 更多