用于为目标生成签名统计信息(针对所有签名)的 IDA 插件/脚本?

逆向工程 艾达 idapro插件 调情签名
2021-07-05 04:29:25

我有超过 40 个不同的 IDA 签名文件(除了内置的),有时我不想去检查哪些签名可能与给定目标相关。相反,我只想应用所有签名,一次一个,然后让 IDA 告诉我哪些签名在目标中匹配最多。手动执行此操作非常乏味,因为

  1. IDA 只允许在每个应用操作中应用 1 个签名
  2. 签名的应用顺序会影响给定签名生成的匹配数。例如,当应用 sig A 时,它可能意味着 sig B 错过了 A 在其之前匹配的一些匹配项。

我想插件/脚本会做这样的事情:将 sig A 应用到目标数据库,计算匹配项,然后删除 sig A 的应用程序并应用 B,计算匹配项,然后删除应用程序并应用 C 等等。

没有其他人有过这个想法吗?我一直无法找到执行此操作的插件或脚本,如果已经存在,我宁愿不编写自己的插件或脚本。

3个回答

如果您正在谈论 IDA FLIRT 签名,不幸的是,您迟早会遇到它们的局限性,或者,如果您想要高精度,就会对结果感到沮丧。

首先,您可以在此处详细了解 IDA 的系统:https : //www.hex-rays.com/products/ida/tech/flirt/in_depth.shtml

如您所见,它只匹配函数的前 32 个字节。然后它使用 CRC16,因此发生冲突的可能性很大。

FLIRT 的最大问题是它非常模糊。
它容易出现错误匹配。并且,或者,如果匹配函数的前 32 个字节没有改变,但其余部分仍然匹配。这通常是一件好事,但随后的行为是不可预测的。此外,IDA 中的系统除了最小的 UI 之外还缺少任何东西。例如,如果 IDA 跟踪并向您显示匹配和不匹配的列表(如果您想要的话),那就太好了。尽管据说是在 6.4 中,他们对设置进行了大修和更新,因此它可能已经得到改进。

现在它并不可怕;这比什么都没有好,而且总体上非常有用。但是由于这些问题,您可能想要自己制作。

我制作了自己的签名系统,它遍历源签名目标的每个函数并复制所有非相关字节(即它跳过来自 JMP、MOV、CALL 指令等的偏移字节)并制作整个 64 位哈希事物。我只保存唯一的用户命名函数并跳过小的函数(低于字节计数截止点)。保存冗余签名没有意义。

通过这种方式,我知道以后如果我有匹配项,那么它很可能是一个很好且独特的匹配项。它更加准确,并且几乎没有出现错误和冗余匹配的可能性。此外,它是通过一个插件完成的,该插件与 IDA 自己的 sig 系统一样快,如果不快的话。它还允许我添加我想要的匹配、非匹配、统计信息等的 UI 列表。

您可以使用快照从插件中实现这一点。我认为 IDC 或 IDAPython 中没有公开数据库快照功能。

新打开的数据库上的通用算法将类似于

libs_before = iterate over all functions to determine initial count of library functions
snapshot_t ss;
::qstrncpy(ss.filename, "tempsnap", 9);
qstring errmsg;
take_database_snapshot(&ss, &errmsg);
//use platform directory iterator on IDA sigs directory
for i in list_of_sig_files
   int signum = plan_to_apply_idasgn(i);
   while (i--) {
      apply_idasgn(1);  //may need to play around with this
   }
   libs_after = iterate over all functions to determine count of library functions after sigs applied
   msg("%d signatures matched from %s\n", libs_after - libs_before, i);
   restore_database_snapshot(&ss), mycb, NULL);

其中最小值mycb是:

void idaapi mycb(const char *errmsg, void *ud) {}

显然有一些代码需要你填写,但这个想法是在二进制文件中获取库函数的初始计数并拍摄快照。接下来遍历所有 sig 文件的名称并依次应用每个文件。在应用每个签名文件之后,在数据库中生成新的库函数计数。新计数和原始计数之间的差异是签名匹配的数量。最后恢复到您在应用 sig 时回滚所做更改的快照。

您可以通过迭代所有函数(请参阅get_next_func)并对每个返回的函数进行func_t *f检查来计算库函数的数量(f->flags & FUNC_LIB) != 0

希望这能让你走上正轨

有一个插件叫BinDiff

如果您在一个 IDA 数据库中重命名了 Sub_Routines,则可以在当前数据库和尚未重构的新数据库之间运行 BinDiff。唯一的缺点是对于 30mb+ 大小的二进制文件来说有点耗时。

http://i.imgur.com/dTPEyHq.png