x86_64近跳转地址计算疑惑:实际跳转地址为何不符?
问题背景
我用免费版IDA调试器学习Windows平台汇编,写了一段C++代码编译后调试:
#include <iostream> #include <Windows.h> int main() { SIZE_T size = 0; unsigned char data[10] = {}; ReadProcessMemory(GetCurrentProcess(), NULL, data, 10, &size); }
跟踪ReadProcessMemory的调用流程时,走到了0x00007FFBD508AE80这个地址,这里是一条7字节的jmp指令:
KERNEL32.DLL:00007FFBD508AE80 jmp cs:off_7FFBD50F1A08
指令编码是FF25816B0600,我知道FF25是近跳转的操作码,按公式计算:
0x00007FFBD508AE80 + 0x066B81 + 7 = 0x7FFBD50F1A08
结果和IDA显示的偏移完全一致,按理说应该跳转到这个地址,但按F7单步进入后,实际却跳到了KernelBase.dll的0x7FFBD29BAC90地址,这是哪里忽略了?
问题根源
这是Windows的API重定向机制导致的:
- Kernel32.dll里的
ReadProcessMemory只是个“跳板桩函数”,本身没有实际功能,唯一作用就是跳转到真正实现API逻辑的位置。 - 你计算出的
0x7FFBD50F1A08是Kernel32.dll中的一个内存地址,这个地址里存的不是最终跳转目标,而是指向KernelBase.dll真实函数入口的指针。 - 这条
jmp cs:off_7FFBD50F1A08是间接跳转——它会先读取0x7FFBD50F1A08地址里存储的值,再跳转到该值指向的位置,也就是你看到的KernelBase.dll的0x7FFBD29BAC90,这才是ReadProcessMemory真正干活的代码入口。
说白了,你算的是“存指针的地址”,而不是“指针指向的真实函数地址”,所以单步执行后会跳到KernelBase.dll的实际实现处。
内容的提问来源于stack exchange,提问作者sebastien dontneedtoknowthat
相关产品推荐
相关产品推荐

