为什么 JMP 与 CALL 一起使用?

逆向工程 拆卸 恶意软件 部件
2021-06-22 04:05:47

我正在尝试分析 OllyDbg 中的旧恶意软件样本。它有格式说明CALL <JMP.&KERNEL32.SetUnhandledExceptionFilter>

我不是大会的专家。我知道 CALL 用于调用子程序,JMP 用于跳转到内存中的特定地址,但是将 CALL 与 JMP 一起使用的结果是什么?有人可以澄清一下吗?即使是指向我在哪里可以找到答案的指针也会非常有帮助。谢谢。

3个回答

看到表单中的调用CALL <JMP.&KERNEL32.SetUnhandledExceptionFilter>表明二进制文件是使用 Visual C++ 的/INCREMENTAL选项编译的,因此是跳转 thunk 表。

... 增量链接的可执行 (.exe) 文件或动态链接库 (DLL):

...

  • 可能包含跳转 thunk 来处理函数到新地址的重定位。

...

你是对的,它可以直接调用,而不是在调用后跳转。

但是,如果 API 的地址只被引用一次,那么它会更容易,并且这个单一的引用应该是 a JMP(否则,它会改变堆栈)。

因此,只有一个对 API 的内存引用,通过单个JMP. 每次API被使用时,这个JMPCALL-ed,所以执行是透明的,在API的最后,调用者的原始地址还在栈上,调用者会被透明地返回到。

原因是为了加载性能 - 跳转被收集到一个临时可写的单个区域中,以便放置 API 地址,并且通常只有一个页面大小。这避免了加载程序对 VirtualProtect() 的多次调用,以便将整个代码空间写入对任何给定 API 的每个引用。