如何正确的对Windows软件进行逆向工程(翻译/转载)

文章目录
  1. 1. 0x00 前言
  2. 2. 0x01 什么是逆向工程?
  3. 3. 0x01 逆向工程需要什么?
  4. 4. 0x02 理论知识-软件逆向工程过程
  5. 5. 0x03 逆向工程Windows软件的实用工具
    1. 5.1. 反汇编工具
    2. 5.2. Windows Sysinternals
    3. 5.3. 网络监控工具
    4. 5.4. 调试器
  6. 6. 0x05 如何对驱动程序进行反向工程
  7. 7. 0x06 结论

0x00 前言

你有没有想过要拆开某个机械装置了解它的工作原理呢?嗯,谁没有呢。这种欲望也是是逆向工程的主导力量,逆向对于分析产品安全性、在不运行可疑的.exe文件的情况下查明其用途、恢复丢失的文档、开发基于旧软件的新解决方案等非常有用。

在本文中,我们讨论执行逆向工程所需的知识结构、逆向工程的基本原理、Windows软件、反汇编器和工具。我们还提供了对一个程序进行逆向工程的步骤示例。

0x01 什么是逆向工程?

逆向工程是发现硬件或软件背后的原理(例如其体系结构和内部结构)的过程。简单来说逆向工程就是搞清楚程序是如何工作的。
显然,如果您有文档,那么整个过程将变得更加简单。但是经常会发生这样的情况:没有文档,您需要通过另外的途径来学习某个软件的工作方式。
您什么时候需要对软件进行逆向工程,逆向工程对你有什么帮助?
逆向工程在计算机科学领域有许多用途,包括:

  • 研究网络通讯协议
  • 查找恶意软件中使用的算法,例如计算机病毒,特洛伊木马,勒索软件等。
  • 研究用于存储任何类型信息的文件格式,例如电子邮件数据库和磁盘映像
  • 检查您自己的软件抵抗逆向工程的能力
  • 改善软件与系统和第三方软件的兼容性
  • 使用未文档化的系统功能
    逆向工程的合法性取决于其目的以及软件的使用方式。假设您已合法获得该软件的副本,则上述所有目的都是完全合法的。但是,例如,如果您打算对软件某些闭源功能进行逆向工程,然后在另一个软件中使用,则可能会遇到麻烦。

关于法律文件,最终用户许可协议(EULA)通常禁止进行逆向工程。但是美国数字千年版权法案规定,如果为了提高与其他产品的兼容性而逆向某个软件是合法的。
法律要求因国家/地区而异,因此请在开始之前花点时间研究一下。
现在,让我们看看如何对软件进行逆向工程。

0x01 逆向工程需要什么?

要开始逆向软件,您需要:

  • 1.您想要使用逆向工程领域的知识
  • 2.一些能够再反汇编一个软件时应用你专业知识的工具
    让我们考虑一个与软件不相关的例子。假设您有一只手表,想确定它是机械的、石英的还是自动的。
    拥有该领域的知识意味着您应该知道有三种类型的手表。此外,您应该知道,如果有电池,它应该在手表内部,打开手表就可以看到它。您还应该了解手表的内部结构,电池的外观以及打开表壳所需的工具的基本知识。拥有可以验证知识的工具,意味着您需要一把螺丝起子或其他专用工具,才能打开手表。
    就像对手表进行逆向工程需要特定的技能和工具一样,逆向工程软件也需要其自身在特定领域的知识和工具。

0x02 理论知识-软件逆向工程过程

对于不同的软件逆向工程任务,您需要不同类型的知识。当然,有一些常识可以帮助您完成大多数逆向工程任务:常见的应用程序结构,编程语言,编译器等知识。但是,如果没有特定的理论知识,就无法完成具体的逆向工程任务。

逆向任务 你需要的基础知识
对有网络行为的软件进行逆向工程 进程间通信、网络的结构、连接、网络数据包等
逆向加密算法 密码学及最常使用的密码学相关算法
逆向文件结构 基本文件概念以及不同的系统或组件如何使用文件

在逆向分析某些软件时使用一些技巧可以节省大量时间。对于有文件交互的软件,可以输入一些比较特殊的数据,然后记录实际存储时候的数据的大小和偏移,这些信息有助于你发现这些文件的内部结构。
进行逆向工程过程时,软件开发人员通常使用反汇编程序来查找适当的算法和程序逻辑。有许多不同的可执行文件格式,编译器(提供不同的输出)和操作系统,因为这种多样性,很难通过单一的技术去逆向各种类型的软件。
要理解反编译的代码,您需要一些有关汇编语言,函数调用约定,栈结构,堆栈框架等方知识。
了解不同语言的汇编程序输出可能有助于您发现原始功能。让我们来看一些Windows x86平台的示例。
假设我们有以下代码:

1
2
3
4
5
6
int count = 0;
for (int i = 0; i < 10; ++i)
{
count++;
}
std::cout << count;

如果我们将此代码编译为可执行文件,则会在反汇编程序中看到以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
004113DE loc_4113DE:
004113DE mov eax, [ebp-14h]
004113E1 add eax, 1
004113E4 mov [ebp-14h], eax
004113E7 loc_4113E7:
004113E7 cmp [ebp-14h], 0Ah
004113EB jge short loc_4113F8
004113ED mov eax, [ebp-8]
004113F0 add eax, 1
004113F3 mov [ebp-8], eax
004113F6 jmp short loc_4113DE
004113F8 loc_4113F8:
004113F8 mov ecx, ds:?cout@std
004113FE push eax
00411400 call ds:basic_ostream@operator<<(int)
00411404 xor eax, eax
00411406 retn

如上,for循环最后变成了由比较和跳转语句组成的汇编代码,注意这里的汇编代码并未使用ecx作为循环计数器,另外这里的局部变量时[ebp-14h]和[ebp-8]。
让我们看看使用release模式编译会汇编代码会有什么变化:

1
2
3
4
5
6
7
00401000 main     proc near
00401000 mov ecx, ds:?cout@std
00401006 push 0Ah
00401008 call ds:basic_ostream@operator<<(int)
0040100E xor eax, eax
00401010 retn
00401010 main endp

这段代码看起来与之前的代码完全不同。这是因为代码被优化了。删除了该循环,因为除了将count变量增加到10之外,循环没有做任何其他事情,因此优化程序决定仅保留count变量的最终值,并将该值直接作为count输出运算符的参数。
目前,我们使用的编译器非常擅长优化代码。这就是为什么在进行逆向工程时,最好理解代码背后的思想(代码原理),而不是尝试获取原始代码本身。如果您了解代码背后的原理,则只需编写适合原始任务的原型即可。
如果您编译不同的运算符,结构和其他语言构造,那么你就知道汇编代码将非常有用。了解最终的汇编代码是开始C++逆向工程过程的一种好方法,但是我们在这里不介绍它的技术细节。

0x03 逆向工程Windows软件的实用工具

在我们的应用程序架构研究中,我们已经描述了几种逆向工程工具,包括ProcessMonitor和ProcessExplorer。这些工具对于逆向工程绝对是必不可少的。
在本节中,我们将回顾最受欢迎的反汇编程序以及用于逆向工程项目的其他一些工具。
您可以在有关最佳软件逆向工程工具的文章中获得更多详细信息和用法示例。

反汇编工具

反汇编程序是将可执行文件转换为汇编语言的程序。最受欢迎的是IDA Pro
IDA Pro


IDA Pro

IDA Pro是一种方便而强大的反汇编工具。由很多功能,可让您快速反汇编一个软件。它可以显示函数调用树,解析可执行文件的导入和导出,并显示有关它们的信息。它甚至可以用C语言显示代码。它还支持多种CPU架构,因此可以使用IDA Pro对ARM,AVR,M68k和许多其他架构进行逆向工程。

Radare

Radare

Radare反汇编工具是IDA的替代产品。它基本上具有IDA的所有功能。虽然没有那么强大和稳定。但是它是免费和开源的。Radare本身是一个控制台工具,但是它具有Cutter前端,这使其成为IDA的可选替代。

Windows Sysinternals

Windows Sysinternals实用程序通常用于Microsoft Windows环境的管理,诊断,故障排除和监视。但它们也适用于逆向Windows软件。
TCPView是一个网络嗅探器,它显示来自所有进程的有关TCP/UDP数据包的所有信息。该工具对于逆向网络协议很有用。
PortMon是一个物理系统端口监视器。它监视串行和并行端口以及通过它们的所有流量。
WinObj以分层结构显示系统中的所有全局对象。当逆向使用同步对象(例如互斥量和信号量)的应用程序以及内核模式驱动程序时,此工具很有用。

网络监控工具

Wireshark


Wireshark

Wireshark是功能最强大的网络嗅探器之一。它不仅允许您捕获网络流量,而且还包含针对各种网络协议的解析器,这些解析器从诸如以太网,TCP和IP的真正底层开始,到诸如WebSockets和XMPP的特定于应用程序的协议。

Fiddler


Fiddler

Fiddler是一个Web代理,它记录来自浏览器的流量,并允许您分析HTTP/HTTPS请求。与Wireshark不同,它显示HTTP会话而不是单独的网络数据包。Fiddler还允许您在监视SOAP,REST和AJAX请求时分析通过HTTP发送的压缩数据,并分析JSON和XML数据(译者注:搭配proxifier使用更强大)。

API Monitor


API Monitor

API Monitor是非常实用的工具,用于发现应用程序调用了哪些API以及应用程序从这些API期望的行为。该工具具有功能强大的数据库,可让您看到对不仅是kernel32和ntdll的大量API函数的调用,而且还包括对COM,托管环境等的调用。此外,API Monitor提供了方便的过滤机制。

调试器

对于任何开发人员来说,调试器对于查看程序现在正在做什么时无可替代的。逆向应用程序时从调试中获得的好处与调试实时应用程序时获得的好处相同。
最受欢迎的调试器是OllyDbg,WinDbg和Windbg Preview。

OllyDbg


OllyDbg

当涉及软件逆向工程时,OllyDbg(及其后继x64dbg)可能是最好的调试器。它是专门为满足逆向需求而开发的,并具有用于此目的的所有功能:

- 内置的反汇编程序,能够分析和识别关键数据结构
- 导入和导出分析功能
- 内置的assembling和patching引擎
解析API函数及其参数的能力使逆向系统的交互变得容易。堆栈视图提供了大量有关调用堆栈的信息。另一个重要的优点是,可以实用OllyDbg调试有调试保护的应用程序,而普通的调试器却无能为力。

WinDbg

Windbg

尽管界面简单,但WinDbg具有强大的调试工具。它具有内置的反汇编程序,各种命令,可让您几乎了解要调试的进程/系统的所有内容,并具有内核模式调试的能力,这可能是最有价值的功能。对于逆向驱动程序,尤其是内核模式驱动程序,这是一个很大的优势。

Windbg Preview


Windbg Preview

Windbg Preview是Microsoft开发的Windbg的新版本。它仅通过Windows应用商店分发。它具有经典Windbg的所有功能以及新的UI和一些新功能。这些新功能之一是Time Travel Debugging,它使您可以记录一段程序执行时间,然后根据需要重复调试多次。这样您可以通过逐步执行代码中所关心的部分,而不必担心意外运行某些代码并丢失上下文或所有数据。

## 0x04 现实中的软件逆向工程示例

现在,我们将看到一个示例,说明如何对软件进行逆向工程。假设您有一个可疑的可执行文件。您需要了解该程序的功能以及对用户而言是否安全。考虑到这种情况,最好不要在工作计算机上运行此可执行文件,而要使用虚拟机。让我们在虚拟机中启动应用程序。

Process creates a service

如我们所见,该文件创建一个名为TestDriver的Windows服务,为内核类型,因此我们知道它是一个驱动程序。但是从哪里获取驱动程序文件才能运行?我们可以使用Sysinternals Suite中的ProcessMonitor进行查找。打开ProcessMonitor时,我们可以设置过滤器以仅向我们显示感兴趣的文件活动。其活动日志如下所示:

FileMon information

驱动程序文件是由我们所要进行的逆向的程序创建的,该程序将该文件放置在用户的temp目录中。无需在temp文件夹中查找文件,因为我们发现该过程会在使用后立即将其删除。那么该文件干了什么呢?如果将文件解压缩,我们可能会尝试在流程的资源部分中找到它,因为这是存储此类数据的常用位置。让我们看看那里。我们将使用另一个工具-Resource Hacker-检查资源。运行它:


使用Resource Hacker检查资源

找到了,我们在资源文件中找到了,这可能是Windows可执行文件,因为它以MZ签名开头并且具有字符串“This program cannot be run in DOS mode”。让我们检查一下它是否是我们的驱动程序文件。为此,我们使用Resource Hacker提取资源,然后在反汇编程序中将其打开。




众所周知,DriverEntry是Windows系统中内核模式驱动程序的入口点。似乎我们找到的时一个驱动程序文件,因此我们可以继续进行研究。

0x05 如何对驱动程序进行反向工程

要开始对驱动程序进行逆向工程,我们逐一检查从DriverEntry调用的函数。转到sub_14005,没有发现任何有趣的事情,因此我们继续进行sub_110F0并找到以下代码:




为了简单起见,此处省略了一些信息。
在第一个代码清单中,创建了一个unicode字符串,该字符串指向路径C:\hello.txt。之后,结构OBJECT_ATTRIBUTES填充了常规值;我们知道在调用ZwCreateFile之类的函数时通常需要此结构。
在第二个清单中,我们看到确实调用了ZwCreateFile,这使我们非常确定驱动程序已创建文件-并且我们知道该文件在创建之后的位置。
从第三和第四代码清单中可以看到,驱动程序采用unicode字符串并将其写入缓冲区(这在sub_11150函数中发生),然后将使用ZwWriteFile函数将缓冲区写入文件。最后,驱动程序使用ZwClose API关闭文件。
让我们总结一下。我们发现原始程序从其资源中提取了驱动程序文件,并将其放入当前用户的临时文件夹中,为此驱动程序创建Windows服务并运行它。之后,程序将停止并从temp目录中删除服务和原始驱动程序文件。从这种行为和对反汇编的分析来看,驱动程序除了在C盘中创建一个名为hello.txt的文件并写入字符串“Hello from driver”外,什么都不做。




精彩!我们已经对该简单程序进行了逆向工程,现在我们知道它可以安全使用。我们可以通过许多不同的方式实现此结果-使用调试或API Mon,编写测试等。您可以找到自己的方式来对适合您的软件进行逆向工程。

0x06 结论

Windows软件逆向工程需要扎实的教育背景和编程经验。为了开始逆向工程,您需要结合汇编,网络监控,调试,API集成,多种程序语言,编译器等方面的技能。在逆转软件时还必须非常小心,以免违反版权法或损害版权及你的操作系统。

原文地址:https://www.apriorit.com/dev-blog/364-how-to-reverse-engineer-software-windows-in-a-right-way