为何ReadProcessMemory读取的进程数据少于MiniDumpWriteDump?
Python进程内存读取问题:MiniDumpWriteDump 与 ReadProcessMemory 差异分析
测试程序
import time PMMMEMPF = "KDOABC" while True: print(PMMMEMPF) time.sleep(0.1)
注:选择PMMMEMPF和"KDOABC"是为了方便后续定位变量。
问题描述
- 使用Process Explorer或
MiniDumpWriteDump(参数为MiniDumpWithPrivateReadWriteMemory)生成进程完整转储时,能轻松找到PMMMEMPF和"KDOABC"的引用。 - 但调用
Win32 API的ReadProcessMemory(参考常规内存读取代码)时,无法读取运行中进程的PMMMEMPF变量值;用HxD打开进程主内存、Process Explorer的「属性-字符串」功能也找不到相关引用。 - 疑惑:
MiniDumpWriteDump似乎能获取比ReadProcessMemory更多的数据,但不清楚它从何处获取PMMMEMPF的引用,想知道使用ReadProcessMemory时遗漏了什么。
2025年6月10日补充信息
已通过HxD找到变量地址0x1e262366170,但该地址属于PAGE_NOACCESS属性的内存区域(索引11),询问如何访问该区域。
对应的内存区域信息如下:
- idx : 1, Type:UNKNOWN, State: MEM_FREE, Region Size : 1592459264, BaseAddress: None, Protect : PAGE_NOACCESS
- idx : 2, Type:MEM_IMAGE, State: MEM_COMMIT, Region Size : 4096, BaseAddress: 0x5eeb0000, Protect : PAGE_READONLY
- idx : 3, Type:MEM_IMAGE, State: MEM_COMMIT, Region Size : 356352, BaseAddress: 0x5eeb1000, Protect : PAGE_EXECUTE_READ
- idx : 4, Type:MEM_IMAGE, State: MEM_COMMIT, Region Size : 131072, BaseAddress: 0x5ef08000, Protect : PAGE_READONLY
- idx : 5, Type:MEM_IMAGE, State: MEM_COMMIT, Region Size : 126976, BaseAddress: 0x5ef28000, Protect : PAGE_READWRITE
- idx : 6, Type:MEM_IMAGE, State: MEM_COMMIT, Region Size : 24576, BaseAddress: 0x5ef47000, Protect : PAGE_READONLY
- idx : 7, Type:UNKNOWN, State: MEM_FREE, Region Size : 554250240, BaseAddress: 0x5ef4d000, Protect : PAGE_NOACCESS
- idx : 8, Type:MEM_PRIVATE, State: MEM_COMMIT, Region Size : 4096, BaseAddress: 0x7ffe0000, Protect : PAGE_READONLY
- idx : 9, Type:UNKNOWN, State: MEM_FREE, Region Size : 20480, BaseAddress: 0x7ffe1000, Protect : PAGE_NOACCESS
- idx : 10, Type:MEM_PRIVATE, State: MEM_COMMIT, Region Size : 4096, BaseAddress: 0x7ffe6000, Protect : PAGE_READONLY
- idx : 11, Type:UNKNOWN, State: MEM_FREE, Region Size : 824078077952, BaseAddress: 0x7ffe7000, Protect : PAGE_NOACCESS
- idx : 12, Type:UNKNOWN, State: UNKNOWN, Region Size : 0, BaseAddress: None, Protect : UNKNOWN
核心原因与解决方案
1. MiniDumpWriteDump 与 ReadProcessMemory 的本质差异
MiniDumpWriteDump在指定MiniDumpWithPrivateReadWriteMemory参数时,会捕获进程的虚拟内存快照,包括进程地址空间中所有预留但未提交的区域;而ReadProcessMemory默认只能读取当前已提交(MEM_COMMIT)且具备合法访问权限的内存页,未提交或标记为PAGE_NOACCESS的区域无法直接读取。
2. PAGE_NOACCESS 内存区域的访问方法
你找到的地址属于MEM_FREE状态的PAGE_NOACCESS区域,说明该地址当前未映射到物理内存,但Python解释器会预先预留大块虚拟地址空间作为堆内存,按需提交物理内存——MiniDump会捕获这些预留的虚拟地址空间信息,而常规ReadProcessMemory不会处理这类区域。
要访问该地址,需按以下步骤操作:
- 调用
VirtualProtectEx函数,将目标地址所在页的权限临时修改为PAGE_READWRITE或PAGE_READONLY,并保存原权限。 - 调用
ReadProcessMemory读取目标地址的内容。 - 读取完成后,再次调用
VirtualProtectEx恢复原内存页权限,避免破坏进程正常运行。
注意:操作需要足够权限(如管理员身份运行),且可能影响目标进程稳定性,需谨慎执行。
3. ReadProcessMemory 的遗漏点
之前的代码大概率只遍历了MEM_COMMIT状态的内存区域,未处理**预留(MEM_RESERVE)**区域。Python全局变量通常存放在解释器堆中,而堆包含大量预留未提交的地址空间,需要通过VirtualQueryEx遍历进程所有虚拟内存区域,再针对性处理。
具体操作步骤
- 使用
VirtualQueryEx遍历目标进程的所有虚拟内存区域,记录每个区域的基地址、大小、保护属性和状态。 - 定位包含目标地址
0x1e262366170的区域(即使是MEM_FREE/PAGE_NOACCESS状态)。 - 调用
VirtualProtectEx修改该区域权限为可读取,保存原权限。 - 调用
ReadProcessMemory读取目标地址内容。 - 恢复原内存页权限。
内容的提问来源于stack exchange,提问作者Nono RAM
相关产品推荐
相关产品推荐

