簡體   English   中英

緩沖區應為ReadProcessMemory哪種數據類型?

[英]What data type should the buffer be for ReadProcessMemory?

在所有示例中,我都看到了第三個參數或buffer是一個整數,但是我不確定該值應該代表wtf還是無論如何它都有用,所以我嘗試了一個char數組並得到了隨機垃圾,所以我我很好奇這個值可以用於什么,最好的容器,以及數據類型是否取決於我們所查詢的值。

看完我的代碼后,我意識到我在聲明它時沒有初始化進程句柄,從而犯了一個非常愚蠢的錯誤。 雖然這是我的代碼,但是現在我得到ERROR_PARTIAL_COPY dwReaddwRead

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

int main()
{
    system("tasklist");

    SYSTEM_INFO SysInfo;
    GetSystemInfo(&SysInfo);

    DWORD proc_Id = 0;
    cin >> proc_Id;
    HANDLE hProc = INVALID_HANDLE_VALUE;
    char value[500];
    SIZE_T dwRead;

    hProc = OpenProcess(PROCESS_ALL_ACCESS, TRUE, proc_Id);
    if(hProc == NULL)
    {
        cout << "Error when trying to retrieve process handle" << endl;
    }

    void *baseAddr = (void*)hProc;

    if(VirtualAllocEx(hProc, NULL, SysInfo.dwPageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READ) == NULL)
    {
        cout << "VirtualAllocEx error" << endl;
    }

    if(ReadProcessMemory(hProc, baseAddr, &value, sizeof(value), &dwRead) == 0)
    {
        cout << "ReadProcessMemory failed: " << GetLastError() << endl;
    }
    cout << "Value is: " << value << endl;
    cout << "Amount read successfully: " << dwRead << endl;
}
 BOOL WINAPI ReadProcessMemory( HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead ); 

該參數聲明為LPVOIDvoid*typedef )。 任何指針都可以隱式轉換為空指針-這意味着您提供的緩沖區實際上可以是您喜歡的任何類型。 唯一的限制是它必須足夠大以容納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參數可讓您確定成功讀取了多少字節。

如果函數返回0則表示它完全失敗-在這種情況下,您提供的緩沖區的內容是未定義的,不應使用。

您應該使用函數要使用的數據類型。

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

至於第三個參數,只要相應地調整第四個參數,就可以使用指向任何類型數據的指針。

例如,將指向int的指針作為第三參數並將sizeof(int)作為第四參數傳遞可能很好。

我建議使用零初始化您正在傳遞的數據(至少出於調試原因),並檢查該函數返回的所有數據是什么(尤其是作為第5個變量傳遞的指針的變量的值)。

哪種數據類型最適合您的用例取決於您。

如果您使用char -array,這將是一種方法:

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

因為“ David Heffernan”指出了不清楚用零初始化緩沖區的含義,所以我將嘗試解釋一下:

這被認為是調試的“提示”,因為我認為比將數據單位化時更容易看到調試器中已更改的數據。 絕對不需要。

假設您的ReadProcessMemory調用成功返回,並且您要檢查緩沖區中的數據。 你需要檢查多少字節寫入緩沖器,然后看第一bytesWritten您的數組的字節。

如果您未將通過緩沖區傳遞的數據初始化為0則可能更難在“真實數據”和已統一化的數據之間找到破折號,因此可能會導致誤解。 特別是對於大錯誤。

這僅是為了在開發過程中使用某種工具,以便更輕松地檢查數據, 一旦一切按預期進行應將其刪除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM