HCRM博客

为什么在使用 ReadProcessMemory 时会出现报错?

在使用ReadProcessMemory函数时,开发者常常遇到各种报错问题,这些问题可能源于多种原因,包括权限不足、参数错误、内存地址不正确等,下面将从多个角度详细分析这些常见报错及其解决方法,并提供相关代码示例和常见问题的解答。

ReadProcessMemory 报错原因及解决方法

为什么在使用 ReadProcessMemory 时会出现报错?-图1
(图片来源网络,侵权删除)

1. 错误码299:仅完成部分 ReadProcessMemory 或 WriteProcessMemory 请求

描述

错误码299通常表示尝试读取或写入的内存区域中只有一部分操作成功,这可能是由于目标进程的内存保护设置导致的。

解决方法

可以尝试使用VirtualProtectEx函数更改内存区域的保护属性,使其可读写。

DWORD dwOldProt, dwNewProt = 0;
if(!VirtualProtectEx(hProcess, (void*)pAddress, dwRead, PAGE_READWRITE, &dwOldProt)) {
    // 处理错误
}
if(!ReadProcessMemory(hProcess, (LPCVOID)pAddress, pRead, dwRead, &dwReaded)) {
    // 处理错误
}
// 恢复原来的内存保护属性
VirtualProtectEx(hProcess, (void*)pAddress, dwRead, dwOldProt, &dwNewProt);

2. 错误码5:访问被拒绝

为什么在使用 ReadProcessMemory 时会出现报错?-图2
(图片来源网络,侵权删除)

描述

该错误表示当前进程没有足够权限访问目标进程的内存,这通常是由于权限不足或者目标进程的内存保护设置导致的。

解决方法

确保以管理员身份运行程序,并且目标进程没有设置阻止调试的选项,如果仍然不行,可以尝试启用调试权限:

BOOL EnableDebugPriv() {
    HANDLE hToken;
    TOKEN_PRIVILEGES tp;
    LUID luidDebug;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
        return FALSE;
    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidDebug)) {
        CloseHandle(hToken);
        return FALSE;
    }
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luidDebug;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
        CloseHandle(hToken);
        return FALSE;
    }
    CloseHandle(hToken);
    return TRUE;
}

调用EnableDebugPriv函数启用调试权限后,再尝试读取内存。

3. 错误码299:部分读取

为什么在使用 ReadProcessMemory 时会出现报错?-图3
(图片来源网络,侵权删除)

描述

与错误码299类似,但更具体地指出了部分读取的问题,这可能是由于目标内存区域的保护属性不允许完全读取。

解决方法

同样可以尝试使用VirtualProtectEx函数更改内存区域的保护属性,使其可读写,然后再进行读取操作。

4. 错误码87:参数错误

描述

该错误通常表示传递给ReadProcessMemory的参数有误,例如无效的句柄、地址或大小。

解决方法

检查所有传递给ReadProcessMemory的参数是否正确,尤其是进程句柄、内存地址和读取大小,确保这些参数在有效范围内。

5. 错误码487:试图访问无效地址

描述

该错误表示尝试访问的内存地址无效,可能是由于地址计算错误或传递了错误的地址。

解决方法

仔细检查内存地址的计算逻辑,确保传递给ReadProcessMemory的地址是正确的,可以使用调试工具(如调试器)验证地址的正确性。

代码示例

以下是一个完整的代码示例,演示如何使用ReadProcessMemory读取其他进程的内存,并处理常见的错误:

#include <windows.h>
#include <psapi.h>
#include <iostream>
bool ReadMemory(HANDLE hProcess, LPCVOID lpBaseAddress, SIZE_T dwSize, PVOID lpBuffer) {
    SIZE_T dwRead = 0;
    DWORD dwOldProt, dwNewProt = 0;
    BOOL success = VirtualProtectEx(hProcess, lpBaseAddress, dwSize, PAGE_READWRITE, &dwOldProt);
    if (!success) {
        std::cerr << "Failed to change memory protection: " << GetLastError() << std::endl;
        return false;
    }
    success = ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, dwSize, &dwRead);
    if (!success) {
        std::cerr << "ReadProcessMemory failed: " << GetLastError() << std::endl;
        VirtualProtectEx(hProcess, lpBaseAddress, dwSize, dwOldProt, &dwNewProt); // Restore old protection
        return false;
    }
    if (dwRead != dwSize) {
        std::cerr << "Partial read: " << dwRead << "/" << dwSize << " bytes read." << std::endl;
        VirtualProtectEx(hProcess, lpBaseAddress, dwSize, dwOldProt, &dwNewProt); // Restore old protection
        return false;
    }
    VirtualProtectEx(hProcess, lpBaseAddress, dwSize, dwOldProt, &dwNewProt); // Restore old protection
    return true;
}
int main() {
    DWORD pid = GetProcessIdByName("notepad.exe"); // 获取目标进程ID,例如记事本进程
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (hProcess == NULL) {
        std::cerr << "Failed to open process: " << GetLastError() << std::endl;
        return 1;
    }
    MEMORY_BASIC_INFORMATION mbi;
    SYSTEM_INFO si;
    GetSystemInfo(&si);
    bool isWow64 = si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64;
    SIZE_T regionSize = isWow64 ? sizeof(MEMORY_BASIC_INFORMATION64) : sizeof(MEMORY_BASIC_INFORMATION);
    if (!VirtualQueryEx(hProcess, (LPCVOID)0x1000000, &mbi, regionSize)) {
        std::cerr << "VirtualQueryEx failed: " << GetLastError() << std::endl;
        CloseHandle(hProcess);
        return 1;
    }
    void* baseAddress = (void*)mbi.BaseAddress;
    BYTE buffer[4096] = {0};
    if (!ReadMemory(hProcess, baseAddress, 4096, buffer)) {
        std::cerr << "Failed to read memory" << std::endl;
        CloseHandle(hProcess);
        return 1;
    }
    std::cout << "Memory read successfully!" << std::endl;
    CloseHandle(hProcess);
    return 0;
}

使用ReadProcessMemory读取其他进程的内存时,可能会遇到多种错误,了解这些错误的具体原因并采取相应的解决措施,可以有效地避免这些问题,通过启用调试权限、修改内存保护属性以及仔细检查参数,可以大大提高读取内存的成功率,希望本文提供的信息对您有所帮助。

分享:
扫描分享到社交APP
上一篇
下一篇