【问题标题】:Are There any Cases When ReadProcessMemory Would Fail?是否存在 ReadProcessMemory 失败的情况?
【发布时间】:2019-12-06 14:39:50
【问题描述】:

我目前正在编写一个程序,该程序利用ReadProcessMemory 将一块内存作为文本保存到文件中。在程序中,用户将指定内存块的基地址和大小。输入验证在调用ReadProcessMemory 之前完成,以确保没有与参数相关的错误。内存边界也仅限于预分配的区域,以确保用户不会尝试读取未分配的内存。由于所有分配的内存都是可读的,我认为不需要对ReadProcessMemory 执行一般的调用后错误检查。我这样说正确吗?当然,假设所有参数都是有效的。我过去曾多次使用ReadProcessMemory 并进行适当的错误检查,但发现它是不必要的,因为该功能总是成功的。

示例也将不胜感激。 提前致谢!

【问题讨论】:

  • 是的,正如ReadProcessMemory documentation 中明确指出的那样。它还告诉您如何使用GetLastError() 找出失败的原因。您总是、总是、总是检查 API 调用的返回值。没有例外。不这样做只会让你失败并且难以追踪错误。
  • 内存区域可以标记为可执行但不可读。内存也可以得到保障。仅仅因为分配了内存并不意味着 可以读取它。另外,如果不引入 TICTTOU 竞赛,您将无法检查分配的内存。此外,还不清楚您试图通过使用规范之外的 API 来解决什么实际编程问题。

标签: windows winapi error-handling process readprocessmemory


【解决方案1】:

我假设所有参数都有效:

  • handle 拥有对进程的PROCESS_VM_READ 访问权限;
  • lpBaseAddress 有效;
  • nSize lpBuffer 的大小。
  • ...

我认为导致ReadProcessMemory 失败的唯一因素是Memory Protection 属性。

正如@IInspectable:“分配的内存并不意味着您可以读取它”。

经过测试,我发现以下几种情况会失败。

  • PAGE_NOACCESS

https://docs.microsoft.com/en-us/windows/win32/memory/reserving-and-committing-memory

lpvBase = VirtualAlloc(
                 NULL,                 // System selects address
                 PAGELIMIT*dwPageSize, // Size of allocation
                 MEM_RESERVE,          // Allocate reserved pages
                 PAGE_NOACCESS);       // Protection = no access
  • PAGE_GUARD | ...

https://docs.microsoft.com/en-us/windows/win32/memory/creating-guard-pages

lpvAddr = VirtualAlloc(NULL, dwPageSize,
                 MEM_RESERVE | MEM_COMMIT,
                 PAGE_READONLY | PAGE_GUARD);

或被VirtualProtectEx修改:

VirtualProtectEx(hProcess, lpAddress, dwSize, PAGE_NOACCESS, &old);

VirtualProtectEx(hProcess, lpAddress, dwSize, PAGE_GUARD | PAGE_READONLY, &old);

GetLastError 将返回 299(ERROR_PARTIAL_COPY)

使用VirtualQueryEx检索指定区域内页面的访问保护

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-20
    • 2019-12-23
    • 1970-01-01
    • 2015-10-19
    相关资源
    最近更新 更多