搞明白了import是怎么工作的,有一点看不懂。但是一切都井井有条。当我们在程序中调用某个函数时,这个函数的名字就是函数的地址。所以……如果我们写下这段代码:
std::cout << Beep << std::endl;
我们会Beep从加载的kernel32.dll库中得到函数的地址。但是这个地址是从哪里来的呢?程序怎么知道这个函数是在哪里加载的,或者更确切地说是它的地址呢?我知道地址可以从导入表,指的是FirstThunk结构字段_IMAGE_IMPORT_DESCRIPTOR,但是查看反汇编程序,函数的地址看起来像这样:qword ptr ds:[<&Beep>] 我正在阅读 ds 寄存器,它应该是指数据部分。我查看寄存器,我有它:DS 002B 从这一刻起我就陷入了死胡同。毕竟“002B”是什么偏移量,太小了,从哪里算起..我对函数的导入和链接机制非常不清楚。
代码输出
std::cout << Beep的不一定是函数的实际地址,原因在这里描述:函数的地址是什么?很可能,这只是一个反汇编程序错误,为什么函数的地址会在数据部分?我对 Beep 函数的调用在输出中变成了这个
dumpbin /disasm:指令代码 FF 15(考虑到操作码扩展)在这里的意思是“调用附近,绝对间接,在 r/m32 中给出的地址” - 即 在给定内存位置的地址处调用函数(请参阅https://c9x.me/x86/html/file_module_x86_id_26.html)。操作数 00 B0 41 00 是地址本身(反转)。这里的人类可读地址将是:0x41B000。我们查看 dumpbin 部分的输出:
也就是说,函数的地址预计会落入.idata部分,即导入表中。从输出
dumpbin /imports中更准确地找出:如您所见,41B000 是 KERNEL32.dll 模块的导入地址表的开头。该表在程序启动时由 OS 加载器填充,其中写入了加载模块中函数的真实地址。