反向工程C++ - 最佳工具和方法

7
很抱歉 - C++源代码可以看作是一种设计的实现,而通过“逆向工程”我指的是重新获得这个设计。似乎大多数人都将其解读为从二进制文件中获取C++源代码。我在Understanding a C++ codebase by generating UML - tools&methology发表了一个更精确的问题。
我认为有很多工具可以进行C++(源代码)逆向工程,但通常很难理解所得到的内容。有人找到了好的方法吗?
例如,我想要看到GUI层以及它与其他部分的分离情况。我认为这些工具应该能够检测软件包,然后让我手动组织它们。

如果你有源代码,那么“逆向工程”在第一时间具体指什么? - SingleNegationElimination
你认为反汇编器或反编译器可以检测包,从非UI代码中提取UI元素,或类似的操作吗? - Falmarri
4个回答

10

据我所知,目前还没有可靠的工具可以反向工程编译后的C++代码。

此外,我认为构建这样的设备几乎是不可能的。编译后的C++程序只剩下机器语言指令。要知道这是如何映射到C ++结构的,您需要了解编译器、编译器设置、包含的库等等无限制的因素。

你为什么需要这样的东西?根据你想要它做什么,可能有其他方法可以实现你真正想要的结果。


1
即使给出编译器信息,它也不是一个双射:一旦有几个函数模板调用被内联,使用不同的类型进行实例化,就不可能知道它们真正来自同一个模板,而且可能极难猜测。当然,除非二进制文件有调试信息。 - Steve Jessop
基本上大家都认同,你无法真实地逆向工程C++。 - Puppy
你们假设的目标是恢复原始源代码,但实际上也有可能获得功能等效的东西(即使这意味着模板实例化看起来像独立的类型和函数)。然而,目前还没有能够很好地完成这项工作的工具。 - Evan Teran
@Evan Teran:看看Hex-Rays反编译器。 - Igor Skochinsky
@Igor:请阅读我的回答,我向原帖作者推荐了Hex-Rays。 - Evan Teran
1
我会说Hex-Rays在“获得功能等效物”方面做得很好(在用户的帮助下),而且这并不是“假设性的”。 - Igor Skochinsky

4
虽然它不是完整的解决方案,但你应该研究一下IDA ProHexrays。它更多地用于传统意义上的“逆向工程”。也就是说,它会让你对代码在类似C语言的语法中的样子有一个很好的了解,但它无法提供完全可运行的源代码。
它擅长于帮助你了解特定段落(通常是函数)的工作原理。它是“用户辅助”的,这意味着当实际上是一个结构体或类时,它经常会进行很多偏移量的解引用。此时,你可以提供一个结构体定义(类实际上只是带有额外内容如虚表等的结构体),然后它将使用新的类型信息重新分析代码。
正如我所说,它并不完美,但如果你想进行“逆向工程”,那么这是我所知道的最好的解决方案。如果你想要完整的“反编译”,那么你基本上是没有机会的。

3

您可以使用反汇编来抓取控制流,但永远无法获取数据类型...

汇编语言中只有整数(可能还有一些短整数)。想象一下,对象、数组、结构体、字符串和指针算术运算都属于同一类型!


3
“你永远无法获取数据类型” - 我在想。虚函数表可能是相当容易识别的,所有具有外部连接的事物都将具有可以解开名称的名称。您可能能够推断出许多类的合理数量,但您无法找到对该类的所有调用,因为一般来说某些调用会被内联。 - Steve Jessop
1
@Steve:这里没有名字了,只剩下内存地址。 - John Dibling
@Steve Jessop:内联函数实际上并不是问题,这只会在“反编译器”中显示为具有重复代码的多个函数。当然,它看起来不像原始源代码,但对于逆向工程来说,功能上等效可能更为重要。 - Evan Teran
@Evan:好的,但是基于这个前提,你可以通过将C++代码反编译为汇编或C来进行“逆向工程”。 - Steve Jessop
@John:那么为什么dlopen可以在程序上工作呢?我的意思不是这些名称在虚函数表中,只是它们可能在可执行文件的符号表中,因此,根据地址,您可以反向查找它们。当然,可执行文件可能已经剥离了外部符号。 - Steve Jessop
@Steve:当然,那可能是第一步,但汇编代码的读者必须足够熟练,才能知道他们正在查看什么。逆向工程的重点是开发对代码功能的理解。当然,这可以从汇编代码本身中提取出来。 - Evan Teran

1

OovAide项目在http://sourceforge.net/projects/oovaide/或Github上具有一些可能有帮助的功能。它使用CLang编译器从源代码中检索准确的信息。它扫描目录以查找源代码,并将信息收集到一个较小的数据集中,该数据集包含分析所需的信息。

一个概念称为区域图。它显示类之间的关系,因为每个类都显示为图表上的一个点,并且关系线连接它们。这允许图表显示数百或数千个类。OovAide程序区域图显示有一个名为“显示子区域”的选项,它将更接近彼此的目录中的类分组。还有目录筛选器,允许减少非常大型项目中显示在图表上的类的数量。这里展示了区域图及其工作原理的示例:http://oovaide.sourceforge.net/articles/ZoneDiagrams.html

如果在构建设置中为目录分配了组件类型,则组件图将显示组件之间的依赖关系。这甚至显示了哪些组件依赖于外部组件,如GTK或其他外部库。
下一级显示类似于UML类图,但显示所有关系而不仅仅是聚合和继承。它可以显示在方法内使用的类或作为方法参数传递的类。任何类都可以选择作为起点,在将类添加到图表之前,会显示一个列表,允许查看按关系类型显示的类。
最低级别显示序列图。这允许在显示包含方法的类的同时向上或向下导航调用树。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接