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

从内存地址定位x64可执行文件地址:如何确定基址?

已知x64进程内存地址,如何确定加载基址?

嘿,这个问题问到点子上了——x64 PE文件的基址逻辑确实和x86有相似但又有差异的地方,尤其是ASLR(地址空间布局随机化)普及之后,不能只盯着PE头里的默认值不放。

先明确PE头里的IMAGE_BASE字段

x64可执行文件的默认IMAGE_BASE确实是0x140000000,这是编译器(比如MSVC)默认设置的预设加载基址,就像x86的0x400000一样。但这个值只是理想状态下的加载地址,实际运行时能不能用上,得看程序有没有开启ASLR。

分两种情况确定实际加载基址

  • 未启用ASLR的程序:如果PE头的DLLCharacteristics字段没有设置IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE标记,系统会严格按照IMAGE_BASE的值加载程序,这时候实际基址就是0x140000000,和x86的逻辑完全一致。不过现在这种程序已经很少见了,毕竟ASLR是重要的安全防护机制。
  • 启用ASLR的程序(绝大多数x64程序):这时候系统会给程序随机分配一个加载基址,你得通过这些方式获取:
    • 调试器直接查看:用x64dbg、WinDbg这类调试工具,打开进程后看模块列表,主可执行文件的Base Address就是实际加载基址。比如x64dbg里,模块窗口的第一行通常就是主程序,直接看对应的基址列就行。
    • 编程获取:用Windows API就能拿到,比如调用GetModuleHandle(NULL),返回的句柄值就是当前进程主模块的实际加载基址;如果是要获取其他进程的基址,可以用EnumProcessModules枚举目标进程的所有模块,找到对应可执行文件的那一项,其起始地址就是基址。
    • 从进程内存推导:如果你已经有了一个进程内的内存地址,可以用VirtualQuery函数查询该地址所在的内存区域,返回的MEMORY_BASIC_INFORMATION结构体里的AllocationBase字段,就是该内存区域所属模块的基址。

补充:为什么x64默认基址是0x140000000?

这是因为x64的地址空间比x86大得多,微软把用户态程序的默认加载基址设到这个高位区域,一是避免和系统DLL(比如ntdll.dll、kernel32.dll)的加载地址冲突,二是给ASLR的随机化留了足够大的地址范围,提升安全防护的效果。

最后回到你的核心需求

当你要把进程内存地址转换成可执行文件内的指令偏移时,公式是:

  1. 先算出该内存地址对应的RVA:RVA = 进程内存地址 - 实际加载基址
  2. 找到这个RVA所在的节(查看PE头的节表,找VirtualAddress ≤ RVA < VirtualAddress + SizeOfRawData的节)
  3. 计算文件内偏移:文件偏移 = 节的PointerToRawData + (RVA - 节的VirtualAddress)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:47:42