缓冲区应该用于ReadProcessMemory的数据类型是什么?

时间:2016-02-18 05:06:55

标签: c++ winapi buffer virtual-address-space

在所有的例子中,我看到第三个参数或buffer是一个整数,但我不太确定wtf这个值应该代表什么或它如何有用,所以我尝试了{{ 1}}数组并得到随机垃圾所以我很好奇这个值可以用于什么,以及最好的容器,如果数据类型依赖于我们正在询问的值。

在查看我的代码之后,我意识到我在声明它时没有初始化进程句柄时犯了一个非常愚蠢的错误。这是我的代码,现在我得到了charERROR_PARTIAL_COPY为0. wtf

dwRead

2 个答案:

答案 0 :(得分:1)

BOOL WINAPI ReadProcessMemory(
    HANDLE hProcess,
    LPCVOID lpBaseAddress,
    LPVOID lpBuffer,
    SIZE_T nSize,
    SIZE_T *lpNumberOfBytesRead
);

参数声明为LPVOIDtypedef的{​​{1}}。任何指针都可以隐式转换为指向void的指针 - 这意味着您提供的缓冲区实际上可以是您喜欢的任何类型。唯一的限制是它必须足够大以容纳void*个字节的数据。

nSize

如果您在返回的缓冲区中收到垃圾,可能是因为读取失败,或者没有读取您请求的数据,并且您没有检查返回价值得当。如果函数成功,SIZE_T dwRead; int iValue; if (ReadProcessMemory(hProcess, lpAddress, &iValue, sizeof(iValue), &dwRead)) // read an int { if (dwRead == sizeof(iValue)) { // got int successfully } } char buf[256]; if (ReadProcessMemory(hProcess, lpAddress, buf, sizeof(buf), &dwRead)) // read 256 chars { // got dwRead bytes successfully } 参数可以让您找出成功读取的字节数。

如果函数返回lpNumberOfBytesRead,则表示它完全失败 - 在这种情况下,您提供的缓冲区的内容是未定义的,不应使用。

答案 1 :(得分:0)

您应该使用该功能希望您使用的数据类型。

https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553(v=vs.85).aspx

对于第三个参数,只要相应地调整第四个参数,就可以使用指向任何类型数据的指针。

e.g。将指针传递给int作为第三个参数,sizeof(int)作为第四个参数可能完全没问题。

我建议初始化你传递的数据为零(至少出于调试原因),并检查函数返回的所有数据(特别是变量的值,你传递给第5个变量的指针)。 )

哪种数据类型非常适合您的用例取决于您。

如果您使用char - 数组,这将是一种方法:

#include <iostream>
#include <Windows.h>


int main()
{
    HANDLE hProcess = NULL;     //to be initialized
    LPCVOID lpBaseAddress = NULL;  //to be initialized

    char buffer[256];
    SIZE_T bufferSize = sizeof(buffer);
    SIZE_T bytesRead = 0;
    if (::ReadProcessMemory(hProcess, lpBaseAddress, buffer, bufferSize, &bytesRead))  // read 256 chars
    {
        std::cout << "ReadProcessMemory succeeded by reading " << bytesRead << " bytes";
        //Do something with the buffer....
    }
    else
    {
        char messageBuffer[256];
        DWORD messageBufferSize = sizeof(messageBuffer);
        DWORD lastError = ::GetLastError();
        DWORD realMessageSize = ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
                                        NULL,
                                        lastError,
                                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                                        messageBuffer,
                                        messageBufferSize,
                                        NULL);

        //If FormatMessageA fails it returns 0. So we make sure that the string is empty
        messageBuffer[realMessageSize] = 0;

        std::cerr << "ReadProcessMemory failed with " << lastError << ": " << messageBuffer;
    }
}

因为&#34; David Heffernan&#34;指出我不清楚用零填充缓冲区的意思我会尝试解释:

这意味着&#34;提示&#34;用于调试,因为我认为调试器中的数据变化比将单元化数据更容易。 绝对不需要。

让我们说您的ReadProcessMemory调用成功返回,并且您想检查缓冲区中的数据。 您需要首先检查写入缓冲区的字节数,然后查看数组的第一个bytesWritten字节。

如果您作为缓冲区传递的数据未使用0进行初始化,则可能更难找到真实数据&#34;之间的中断。而且只是被酉化的数据 - 因此可能导致误解。特别是对于大错误。

这仅仅是在开发过程中使用的一种工具,可以更容易地检查数据,一旦所有内容按预期工作,应该被删除。