如何基于PE镜像基址在运行时内存中正确定位全局变量?
解决方法:从IDA虚拟地址到运行时实际地址的转换
你犯的典型错误是把IDA里显示的变量地址直接当成了相对虚拟地址(RVA),但实际上IDA里的qword_ED10是虚拟地址(VA),它等于PE文件默认基址加上RVA。要在运行时找到这个变量,得按以下步骤来:
步骤1:计算变量的相对虚拟地址(RVA)
在IDA里操作:
- 先找到当前模块的默认基址(即PE文件头里的
ImageBase,64位程序通常默认是0x140000000,32位是0x00400000) - 查看
qword_ED10的完整虚拟地址(比如IDA里显示该变量地址为0x14000ED10) - 用公式计算RVA:
RVA = 变量VA - 模块默认基址
举个例子,若变量VA是0x14000ED10,默认基址是0x140000000,那RVA就是0xED10——这时候你的初始想法才成立;但如果IDA里的变量VA不是基址加ED10,就得重新计算这个RVA。
步骤2:获取运行时PE镜像的实际加载基址
在Windows平台,可通过以下方式获取:
- 当前进程模块:直接调用
GetModuleHandle(NULL),返回值就是实际加载基址(注意根据程序位数转成64位或32位指针) - 其他进程模块:遍历目标进程的PEB,或用
GetModuleHandleEx获取模块基址
步骤3:计算变量的运行时实际地址
用公式计算:实际地址 = 运行时加载基址 + 步骤1算出的RVA
拿到地址后,直接读取对应长度的内存(64位读8字节,32位读4字节),得到的就是SystemTable的指针值。
额外提醒
- ASLR影响:如果程序开启了地址空间布局随机化,运行时加载基址会和IDA里的默认基址不同,这也是你直接用ED10偏移找不到变量的核心原因
- 段权限检查:确保变量所在的段(比如.data段)是可读写的,避免读取时触发内存访问错误
内容的提问来源于stack exchange,提问作者Louis Bernard
相关产品推荐
相关产品推荐

