如何在Python中读取超出RAM容量的内存地址?
使用Python通过mmap读取/dev/mem中的非RAM物理地址
当然可以用Python实现!你遇到的问题本质是os.lseek+os.read的方式没法处理超出RAM范围的物理地址——因为内核会把这类地址判定为无效,但mmap就刚好能解决这个问题,和你用C写的memhack工具原理完全一致。
为什么原来的方法会报错?
/dev/mem虽然看起来像普通文件,但它是物理内存的镜像。当你用os.lseek定位到超过系统RAM容量的地址时,内核找不到对应的物理内存页,自然会返回无效地址错误。而你要访问的0xFED01004属于内存映射I/O(MMIO)地址,是硬件寄存器的映射,本来就不在RAM范围内,所以必须用mmap来直接映射这个地址区间到用户空间。
Python实现代码
下面是对应你需求的实现,核心就是用mmap模块完成物理地址到虚拟地址的映射:
import os import mmap def read_mmio_address(phys_addr, length): # 获取系统页大小(通常是4096字节) page_size = os.sysconf(os.sysconf_names['SC_PAGE_SIZE']) # 计算页起始地址(必须页对齐) page_start = phys_addr & ~(page_size - 1) # 计算目标地址在页内的偏移 offset = phys_addr - page_start # 以读写模式打开/dev/mem(需要root权限) with os.open("/dev/mem", os.O_RDWR | os.O_SYNC) as fd: # 映射目标物理页到用户空间 # MAP_SHARED表示和内核共享映射,PROT_READ表示只读权限(如果需要写可以加PROT_WRITE) with mmap.mmap( fd, page_size, mmap.PROT_READ, mmap.MAP_SHARED, offset=page_start ) as mem: # 读取指定长度的内容 data = mem[offset:offset+length] return data if __name__ == "__main__": # 目标物理地址0xFED01004(十进制4275048452),读取2字节 target_addr = 0xFED01004 result = read_mmio_address(target_addr, 2) print(f"读取到的数据: {result.hex()}") print("操作完成")
关键细节说明
- 页对齐要求:
mmap的offset参数必须是系统页大小的整数倍,所以我们需要先把目标地址向下对齐到最近的页起始地址,再通过偏移量定位到具体寄存器位置。 - 权限问题:运行这个脚本必须使用
root权限(比如sudo python3 your_script.py),因为/dev/mem是特权设备,普通用户没有访问权限。 - 映射权限:如果需要写入寄存器,可以把
mmap.PROT_READ改成mmap.PROT_READ | mmap.PROT_WRITE。 - 资源释放:用
with语句自动管理文件描述符和mmap对象,避免资源泄漏。
验证效果
这个方法不需要扩展RAM到4GB,直接就能访问MMIO地址,和你用C写的memhack工具效果完全一致。运行后就能读取到0xFED01004地址的2字节寄存器内容了。
内容的提问来源于stack exchange,提问作者austinc
相关产品推荐
相关产品推荐

