在PE文件中跳转存根

时间:2013-06-06 08:59:12

标签: c++ windows reverse-engineering portable-executable

最近我反汇编了一个DLL(用c / c ++编写)并注意到有很多"跳转存根"在代码段内。这些存根只会跳转到DLL中的函数。

例如:

jmp foo() 
jmp foo2()
...

为什么编译器(Visual Studio 2012)在二进制文件中包含这些函数存根?

谢谢!

3 个答案:

答案 0 :(得分:6)

所有存根之后是否有一大堆0xCC字节?如果是这样,您将查看已启用增量链接编译的代码(调试版本的默认设置)。

编译增量链接时,编译器会为每个函数创建一个存根,并确保所有调用都通过存根进行。如果需要用更新的代码替换函数,则可以在末尾添加新代码,并且只需要修补跳转thunk - 所有现有调用将被重定向到新代码。如果添加新功能,额外的CC将保留用于更多存根。

有关更多背景信息,请see MSDN

答案 1 :(得分:3)

这就是链接器和DLL的符号如何“混合在一起”。它保证在符号表中使用正确类型的偏移量,可以通过加载DLL的加载器解析(从而更新DLL中函数的地址),并且编译后的代码仍然可以处理例如函数指针:

void (*fptr)() = foo;

如果foo只是对DLL中某个位置的引用,那么该地址的解析方式将取决于加载器。解决这个问题要复杂得多,而不是解决“这里是一个foo()入口点的问题,让你进入真正的foo”。

答案 2 :(得分:1)

DLL是可重定位的,这意味着它们可能最终在内存中的任何位置。这意味着必须重写对它们的所有调用。通过将所有这些调用保持在一个小的跳转表中,在重定位的情况下只需要重写一个页面。这很重要,因为可以跨进程共享未更改的代码页,但每个进程都有自己的已修改页的副本。