返回介绍

23.1 Hex-Rays

发布于 2024-10-11 21:05:49 字数 4034 浏览 0 评论 0 收藏 0

Hex-Rays 可能是所有 IDA 插件的“始祖”,它是一个反编译器插件,能够为已编译的 ARM 或者 32 位 x86 二进制文件中的函数生成“类似 C 语言的伪代码”1 。Hex-Rays 是一个商业插件,由开发 IDA 的公司创建和销售。这个反编译器只能在 32 位版本的 IDA 上使用。Hex-Rays 仅以二进制格式发布,要安装这个插件,只需将提供的插件文件复制到<IDADIR>/plugins 目录即可。用户可以在线下载2 一个有关 Hex-Rays 用法的手册,该手册提供 Hex-Rays 用法的详细概要,并且包含了一些用于创建反编译器插件的 Hex-Rays SDK3 的文档。

1. 参见 http://www.hex-rays.com/decompiler.shtml
2. 参见 http://www.hex-rays.com/manual/
3. 参见 http://www.hexblog.com/?p=107 。请不要将它与 IDA SDK 相混淆。

安装完毕后,你可以通过 View▶Open Subviews▶Pseudocode (热键 F5)激活这个反编译器,反编译包含光标的函数,或者使用 File▶Produce File▶Create C File(热键 CTRL+F5)反编译数据库中的所有文件,并将它们保存到一个文件中。

为一个函数生成伪代码时,IDA 将打开一个新的包含反编译函数的子视图(标签式窗口)。代码清单 23-1 显示了一个伪代码实例,它使用 Hex-Rays 生成,用于查看“Defcon 15 夺旗赛”二进制文件。每次你为某个函数生成伪代码,Hex-Rays 都会打开一个新的选项卡式窗口来显示结果。

代码清单 23-1 Hex-Kays 输出示例

signed int __cdecl sub_80489B4(int fd)  
{  
  int v1; // eax@1  
  signed int v2; // edx@1  
  char buf; // [sp+4h] [bp-208h]@2  
  char s; // [sp+104h] [bp-108h]@2  

  v1=sub_8048B44(fd,(int)"Hans Brix ? Oh no ! Oh , herro . Great to see you again , Hans ! " , 0 );
  v2 = -1;  
  if ( v1 != -1 )  
  {  
    recv(fd, &buf, 0x100u, 0);  
    snprintf(&s, 0x12Cu, "Hans Brix says: \"%s\"\n", &buf);  
    sub_8048B44(fd, (int)&s, 0);  
    v2 = 0;  
  }  
  return v2;  
}

注意,虽然 Hex-Rays 对参数( a1a2 等)和局部变量( v1v2 )使用的哑命名约定与 IDA 中使用的约定略有不同,但是它们区分函数参数与局部变量的能力相同。如果你更改了反汇编代码清单中变量的名称,那么 Hex-Rays 反编译器(参见表 23-1 )将使用这些名称,而不是内部生成的哑名。

表 23-1 Hex-Rays 反编译器

名称Hex-Rays 反编译器
作者Ilfak Guilfanov、Hex-Rays.com
发布仅二进制
价格2239 美元
描述由编译的 ARM 或 32 位 x86 函数生成类似 C 语言的伪代码
信息http://www.hex-rays.com/decompiler.shtml

Hex-Rays 利用 IDA 采用的线索来推断数据类型。但是,如果用在某个操作中的数据类型不符合 Hex-Rays 的期待,你会注意到,为了强制进行类型转换,可能会有更多的类型转换发生。为了方便,你可以通过单击右键并选择 Hide Casts 菜单项,要求 Hex-Rays 隐藏所有类型转换。

打开伪代码窗口后,你就可以将它作为源代码编辑器和导航器使用。在伪代码窗口中进行导航和编辑,与在标准的 IDA 反汇编窗口中进行导航和编辑非常相似。例如,双击某个函数名称,将立即在伪代码窗口中反汇编该函数。上下文菜单提供了许多编辑功能(如图 23-1 所示),包括更改变量和函数名称及其类型。

enter image description here

图 23-1 Hex-Rays 反汇编器编辑选项

此外,你对变量名称、函数名称和数据类型所作的更改将传播回 IDA 的反汇编窗口。通过重复应用“重命名”(Rename)、“设置类型”(Set Type)以及隐藏转换类型,可以将代码清单 23-1 轻松转换为以下代码。

signed int __cdecl sub_80489B4(int fd)  
{  
  int length; // eax@1  
  signed int error; // edx@1  
  char buf[256]; // [sp+4h] [bp-208h]@2  
  char s[264]; // [sp+104h] [bp-108h]@2  

  length=write_string(fd,"Hans Brix?Oh no!Oh,herro.Great to see you again, Hans!",0);  
  error = -1;  
  if ( length != -1 )  
  {  
    recv(fd, buf, 256u, 0);  
    snprintf(s, 300u, "Hans Brix says: \"%s\"\n", buf);  
    write_string(fd, s, 0);  
    error = 0;  
  }  
  return error;  
}

请记住,在编译过程中一些信息会丢失。同时也没有必要为任何非外部符号保留符号信息,编译器优化会删除冗余并简化代码。因此,除自由使用类型转换外,与人为生成的 C 代码相比,你在生成的伪代码中会看到更多的 goto 语句。这并不意外,因为要将编译器生成的控制流完全还原成原始的 C 语言格式,往往会非常困难。不过, Hex-Rays 能够识别复杂的 C 结构,如 switch 语句,并付出了巨大的努力来识别各种 C 编译器使用的标准代码序列。

鉴于其提供的各种功能,我们不建议你过于依赖 Hex-Rays 。与对应的汇编代码相比,C 源代码确实更具可读性,也更加简明,但反编译并不完美。在阅读 Hex-Rays 伪代码的过程中,你认为自己看到的是基础汇编代码的可信表示形式,同时 Ilfak 也尽其所能来确保 Hex-Rays 的准确性,但仍然存在一些特例,证明 Hex-Rays 有时会出问题。因此,我们强烈建议你对照基础汇编代码来验证你通过阅读 Hex-Rays 伪代码得出的任何结论。最后,请注意,虽然 Hex-Rays 可用于处理用 C++ 代码编译的二进制文件,但它只能生成 C 代码,并且生成的代码缺乏任何特定于 C++ 代码的特性。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文