C++ PE文件中的跳转存根
最近我反汇编了一个DLL(用c/c++编写),发现代码段中有许多“跳转存根”。这些存根除了跳转到DLL中的函数外什么都不做 例如: 为什么编译器(Visual studio 2012)在二进制文件中包含这些函数存根C++ PE文件中的跳转存根,c++,windows,reverse-engineering,portable-executable,C++,Windows,Reverse Engineering,Portable Executable,最近我反汇编了一个DLL(用c/c++编写),发现代码段中有许多“跳转存根”。这些存根除了跳转到DLL中的函数外什么都不做 例如: 为什么编译器(Visual studio 2012)在二进制文件中包含这些函数存根 谢谢 这就是链接器和DLL的符号“混合在一起”的方式。它保证在符号表中使用正确类型的偏移量,可以由加载DLL的加载程序解析(从而更新DLL中函数的地址),并且编译后的代码仍然可以处理例如函数指针: void (*fptr)() = foo; 如果foo只是对DLL中某个位置的引用,
谢谢 这就是链接器和DLL的符号“混合在一起”的方式。它保证在符号表中使用正确类型的偏移量,可以由加载DLL的加载程序解析(从而更新DLL中函数的地址),并且编译后的代码仍然可以处理例如函数指针:
void (*fptr)() = foo;
如果
foo
只是对DLL中某个位置的引用,则此地址的解析方式将取决于加载程序。解决这个问题要比解决“这是一个foo()入口点,它可以让你找到真正的foo”的问题复杂得多 在所有存根之后是否有大量0xCC字节?如果是这样的话,您将看到在启用增量链接的情况下编译的代码(调试构建的默认设置)
编译增量链接时,编译器为每个函数创建一个存根,并确保所有调用都通过存根进行。如果需要用更新的代码替换函数,则可以在末尾添加新代码,并且只需要修补跳转-所有现有调用都将重定向到新代码。额外的CCs保留用于更多存根,以防添加新功能
有关更多背景信息,.DLL是可重新定位的,这意味着它们可能会在内存中的任何位置结束。这意味着对它们的所有调用都必须重写。通过将所有这些调用放在一个小的jumptable中,在重新定位的情况下只需要重写一个页面。这很重要,因为可以跨进程共享未更改的代码页,但每个进程都有自己的修改页副本。DLL=shared library。是的,我们说的是
foo
是mydll.dll
的一部分,而不是myprog.exe
。是的,在这些声音之后有一个0xcc字节的buch。这些恶作剧只出现在发布版本中。
void (*fptr)() = foo;