You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何确定Windows开放进程中可读取的内存地址?

解决ReadProcessMemory遇到不可读地址的问题

嘿,这在Windows进程内存扫描里绝对是高频踩坑点!我来给你几个实用的解决方案,帮你顺畅绕过这些不可读的内存区域:

1. 先用VirtualQueryEx预判地址可读性

在调用ReadProcessMemory之前,先用VirtualQueryEx查询目标地址的内存属性,提前筛掉不可读的区域。这个函数会返回MEMORY_BASIC_INFORMATION结构,里面的Protect字段能明确告诉你这块内存的访问权限。

示例代码(C++):

MEMORY_BASIC_INFORMATION mbi;
if (VirtualQueryEx(hProcess, (LPCVOID)targetAddr, &mbi, sizeof(mbi))) {
    // 覆盖所有可能的可读保护标志
    const DWORD readableFlags = PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY 
                              | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY;
    if ((mbi.Protect & readableFlags) == 0) {
        // 这块内存不可读,直接跳过
        continue;
    }
} else {
    // 地址无效,同样跳过
    continue;
}

2. 分块读取,容错部分不可读区域

有时候目标地址所在的内存块不是完全不可读,可能只是其中某几页无法访问。你可以按系统页面大小(通常是4KB)拆分读取任务,逐个页面尝试读取,遇到不可读的页面就跳过,这样不会因为局部不可读导致整个读取任务失败。

3. 启用SeDebugPrivilege提升权限

有些进程(比如系统核心进程、受保护的安全进程)即使你用VM_READ打开了句柄,也会因为权限不足无法读取。这时候可以尝试启用当前进程的SeDebugPrivilege权限,这能让你获得更高的进程访问权限。

示例代码(C++):

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

记得在程序启动初期调用这个函数,提升权限后再尝试读取进程内存。

4. 用结构化异常处理(SEH)捕获访问异常

如果上面的预判方法没覆盖到所有边缘情况,你可以用Windows的结构化异常处理包裹ReadProcessMemory调用,当触发EXCEPTION_ACCESS_VIOLATION异常时,直接捕获并跳过当前地址。

示例代码(C++):

BYTE buffer[4096];
SIZE_T bytesRead;

__try {
    BOOL success = ReadProcessMemory(hProcess, (LPCVOID)targetAddr, buffer, sizeof(buffer), &bytesRead);
    if (success) {
        // 处理读取到的数据
    }
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
    // 捕获到不可读异常,跳过这个地址
    continue;
}

额外提醒

  • 注意区分错误码:调用ReadProcessMemory失败后,用GetLastError()获取错误码,ERROR_ACCESS_DENIED是权限问题,ERROR_INVALID_ADDRESS是地址无效,针对性处理会更高效。
  • 受系统保护的进程(比如Windows Defender核心进程)即使有SeDebug权限也可能无法读取,这是系统安全机制,不要强行突破。

内容的提问来源于stack exchange,提问作者TheAnonyMoose1234512

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:32:11