使用寄存器而不是二进制中的地址调用什么类型的函数?如何静态查找地址?

逆向工程 二元分析 x86 二进制
2021-06-11 11:23:11

所以我现在正在尝试编写一个反向工具并尝试制作一个 CALL 图

我遇到的问题是有些电话就像 Call *eax 而不是 Call 'address'

我可以使用绝对调用轻松生成调用图,但不能使用这些调用

所以我有三个问题:

  1. 使用寄存器而不是绝对函数调用什么类型的函数?我只想为主程序中的函数而不是库等生成调用图,我是否需要担心寄存器调用或这些仅用于特殊函数?如果是这样,为什么?(即使这些仅用于库函数,我也不明白为什么它们不能在重定位期间转换为绝对地址??)

  2. 如果我想通过读取寄存器来检查被调用的函数是什么,这是否可以使用静态分析或我必须进行动态分析?

  3. 我可以使用静态分析制作一个像样的调用图,意思是只读取二进制文件吗?像 IDA 这样的流行工具是否也使用静态来生成调用图?或者如果我这样做我会面临真正的问题吗?

1个回答
  1. 在 C++ 中,与对象关联的方法的指针存储在称为 vtable 的东西中。为了调用特定的方法,您需要获得指向该虚表的指针并获得正确的函数。最后,即使函数调用不是来自外部库,您也会以“调用 eax”结束。

  2. 嗯,这真的取决于你的情况。您可以使用符号执行等技术来解析跳转目标。这种技术的想法是将“符号值”(即变量)与寄存器相关联并计算由程序集生成的方程。然后您可以求解您的方程以获得您正在寻找的寄存器的最终值。

    这适用于简单的方程,但如果您的代码被混淆(意味着代码自愿复杂),您可能无法在没有动态分析的情况下求解方程并找到调用目的地。(顺便说一句,如果您没有找到执行“call eax”的执行路径,则也可能不会为您提供呼叫目的地)。

  3. 在 IDA 中,调用图是通过执行静态分析生成的。但是,如果跳转比“loc_addr + offset”更复杂,IDA 不会解析动态调用。这是一个“安全”的选择,因为如果您的代码被混淆,您最终可能会执行非常复杂的操作。工具通常做的是找到一种启发式方法:这种技术不适用于所有问题,但它在某些情况下有效(就像 IDA 解决方案一样)。