当我按下X函数 ( ) 上的 键 (list x-refs)sub_xyz
以查看哪些函数调用它时,我只看到了dd offset sub_xyz
两次,没有任何call sub_xyz
说明。
没有别的地方可以写 call sub_xyz
如何查看调用了哪些函数sub_xyz
?这只是 IDA 被混淆了吗?
当我按下X函数 ( ) 上的 键 (list x-refs)sub_xyz
以查看哪些函数调用它时,我只看到了dd offset sub_xyz
两次,没有任何call sub_xyz
说明。
没有别的地方可以写 call sub_xyz
如何查看调用了哪些函数sub_xyz
?这只是 IDA 被混淆了吗?
尽管 Nirlzr 的回答很好地解释了它,但这里有一个考虑 C++ 代码和 vtables 的示例。代码取自here
#include <iostream>
using namespace std;
class Vehicle {
public:
virtual void ApplyBreaks() { cout << "Vehicle Break" << endl; }
virtual void ApplyHorns() { cout << "Vehicle Horns" << endl; }
};
int main() {
Vehicle *v = new Vehicle();
v->ApplyBreaks(); // Calls vehicle ApplyBreak
v->ApplyHorns(); // Calls vehicle ApplyHorn
}
用 g++ 编译并在 IDA 引用中打开ApplyBreaks
就是这样。
这在 C++ 应用程序中很常见,在 vtables 中有函数引用。此外,Vehicle
正如您在此处看到的,此 vtable 中的init设置在对象中。
虽然在main
地址中调用此类的成员函数,但其访问方式类似于具有在编译时定义的偏移量的数组。
在main+48
第一(第0)构件ApplyBreaks
被访问并在main+71
ApplyHorns
被访问其旁边ApplyBreaks
。
如果没有其他引用,则表明没有call sub_xyz
(至少 IDA 已确定)。相反,IDA 仅识别到 的一个交叉引用sub_xyz
,并且该引用是数据变量中的硬编码偏移量。
通常,有一段代码可以访问该数据并间接调用该函数,因此您可以搜索对该数据区域的交叉引用。您应该注意引用不必引用sub_xyz
's 偏移它的位置。相反,sub_xyz
的偏移量可能是一个更大的结构(或一个数组,或一个结构数组)的一部分,它可以被枚举。您需要搜索指向该区域周围的引用(这些也可能是具有更高地址的区域的偏移量,然后将被减去)。
假设在查找交叉引用时,sub_xyz
您只找到了一个,地址00008540
如下所示。
unk_00008538
00008538 dd offset sub_foo
0000853c dd aFuncionFoo ; "Function Foo"
00008540 dd offset sub_xyz <- our sub_xyz reference
00008544 dd aFunctionXYZ ; "Function XYZ"
00008548 dd offset sub_abc
0000854c dd aFunctionABC ; "Function ABC"
你可以看到上面dd offset sub_xyz
(位于地址00008540
)你有一个偏移到另一个子程序sub_foo
(位于00008538
),并且,虽然是没有交叉引用dd offset sub_xyz
(在00008540
)有交叉引用dd offset sub_foo
(AT 00008538
)。
您还可以注意到在 处有另一个子例程偏移量00008548
,并且在每个子例程偏移量之后还有另一个偏移量,指向一个字符串,恰好在其中包含函数的名称。这显然是一个相对简单的例子,我们可以假设这些实际上是一个结构的三个实例,每个实例有两个成员,可以这样定义:
typedef struct FunctionDefinition
{
void* func_addr;
char* func_name;
} _FunctionDefinition;
我们也可以猜测我们找到了一个包含三个FunctionDefinition
结构实例的数组,并且有一段代码枚举了这个数组并遍历了所有的函数。
更复杂的示例可以包括,例如,函数数组及其网络消息标识符,其中,例如,根据接收到的消息类型来调度处理网络命令的函数。如果您正在处理 C++,甚至可能是函数虚拟表,您也可以找到任何类的全局对象。选项是无穷无尽的,您需要使用遇到的特定场景和可以收集的其他信息(例如,引用更大结构或数组的代码)来弄清楚。