转自:https://xz.aliyun.com/t/3407
原文:https://medium.com/@MorteNoir/database-reverse-engineering-part-1-introduction-cd6e6a106a84
当今,逆向工程社区的研究重点主要集中在代码领域,他们关心的问题为“代码是如何工作的以及它们是如何处理数据的”?在本文中,我们将从另一个角度来进行逆向工程,所以,这里关注的问题是“代码所处理的数据是如何组织的”?
在此过程中,我们要面对的是专有文件格式和数据库分析、interfile格式、数据结构逆向分析方法,各种不借助反汇编和调试器的研究方法以及相关的数据解压方法。并且,通常无法借助于完整的源代码和SQL数据库。
文件格式逆向分析
数据库的逆向分析是以文件格式的逆向分析为基础的,并且,前者通常会比后者更为抽象。
<div align=center></div>
抽象层次
对于第一个抽象层次来说,我们的研究对象为与其他文件无关或仅在语义上与其他文件相关的单个文件,例如,文件夹中的一组.jpg文件。首先,我们需要给出文件、文件格式和二进制文件等术语的定义。
文件是根据某些规则组织在一起的数据。
文件格式是文件中数据的组织规则。
一个简单的例子是由几行文本构成的文件。该文件的格式可以视为由换行符进行分隔的UTF-8编码格式的文本。
For us, and for our tragedy,
Here stooping to your clemency,
We beg your hearing patiently.
二进制文件是用于存放原始字节和/或人类可读信息的文件。
假设有一个二进制文件,其中存储的是某些消息及其日期,具体如图所示。这个文件的格式比前面看过的格式要更规整一些:前4个字节是消息的长度(0xC),接下来的字节中存放的是一则消息("Some message"),其长度就是前面的长度字段指定的字节数,注意,这里的NULL字节不计数;后面的一个字节中存放的内容(0x6 = 6)表示月内的几号;接下来的一个字节中的内容(0xB = 11)描述是年内的月份,最后两个字节中的内容(0x7E1 = 2017)表示的是年份。
0C 00 00 00-53 6F 6D 65-20 6D 65 73-73 61 67 65 ♀ Some message
06 0B E1 07- - - ♠◙с•
当然,互联网上已经有几篇关于文件格式逆向工程的文章,但数量并不多。此外,目前已有一些用于描述文件格式的工具,不过,这些十六进制编辑器通常需要借助命令式脚本语言来增强其功能。在这些工具中,最先进的恐怕就是Kaitai Struct了,它支持用户以声明方式来描述二进制文件格式。
数据库逆向分析
当我们研究内部紧密相关的二进制文件集合时,我们就会进入第二个抽象层次。我们称这个集合为“数据库”。
数据库是一组存放结构化数据并且彼此交叉引用的二进制文件。
请注意,这里是数据库的非常抽象的定义。不过,就像目前的逆向工程过程仍然涉及众多细枝末节一样,数据库的逆向分析过程也不例外——我们很难绕过数据库内部运行机制的研究而直接着手数据处理。当然,在极少数的情况下,我们是无需进行逆向分析的。
假设我们有一个乐队数据库,其中包含3个二进制文件:Band.dat1是一个乐队列表,Album.dat2存放的是每个乐队的专辑,Image.dat3存放的是乐队成员照片和专辑封面。
Band.dat1
Album.dat2
Image.dat3
下面,我们来介绍一下Band.dat1。它是由下列元素组成,各个元素的结构如下所示:
- 一个机器字:乐队ID。
- 0x20个字节:乐队名称;未使用的字节被置零。
- 由机器字组成的列表,直到遇到终止符0xFFFF结束:专辑ID列表。
- 0xFFFF终止符。
- 由双字组成的列表,直到遇到终止符0xFFFFFFFF结束:照片ID列表。
- 0xFFFFFFFF终止符。
在这里,有两个依赖项:专辑ID(对Album.dat2的交叉引用)和照片ID(对Image.dat3的交叉引用)。
00 00 C9 07-08 55 6E 64-65 72 74 6F-77 02 00 00 ╔•◘Undertow☻
80 01 00 CC-07 06 41 65-6E 69 6D 61-03 00 00 80 А☺ ╠•♠Aenima♥ А
02 00 D1 07-09 4C 61 74-65 72 61 6C-75 73 04 00 ☻ ╤•○Lateralus♦
00 80 03 00-D6 07 0A 31-30 30 30 30-20 44 61 79 А♥ ╓•◙10000 Day
73 05 00 00-80 - - s♣ А
最后,我们来了解一下Image.dat3。它是一个包含6个元素的数组,数组长度为0x10字节,不依赖于其他文件,各个元素格式为:
- 一个双字:图片ID。
- 0xC个字节:图片(当然是虚构的)。
00 00 00 80-50 49 43 00-00 00 00 00-00 00 00 00 АPIC
01 00 00 80-50 49 43 00-00 00 00 00-00 00 00 00 ☺ АPIC
02 00 00 80-50 49 43 00-00 00 00 00-00 00 00 00 ☻ АPIC
03 00 00 80-50 49 43 00-00 00 00 00-00 00 00 00 ♥ АPIC
04 00 00 80-50 49 43 00-00 00 00 00-00 00 00 00 ♦ АPIC
05 00 00 80-50 49 43 00-00 00 00 00-00 00 00 00 ♣ АPIC
下图展示的是三个文件的格式及其依赖关系,这实际上是一种数据库架构。
数据库架构
因此,我们已经掌握了2个抽象层次——文件格式层次和数据库层次,从而为进一步研究数据库问题做好准备。
数据库逆向分析所要解决的问题,就是重建未知数据结构,并确定它们之间的依赖关系。
数据库的逆向分析是完成许多实际任务的必经之路,而非最终目标。经过这个阶段之后,就要开始处理数据:将数据转换为新型的、具有可能关系的数据库。该过程可以称为ETL(抽取,转换,加载),但它与数据库逆向分析无关。
目前,我没有找到与这个主题相关的任何文章。之所以出现这种情况,可能是因为专家没有将文件格式逆向分析和数据库逆向分析区别对待。另一个原因是数据库逆向分析是一个非常耗时的过程,通常需要在保密协议下进行的,所以,这一点也是有很大影响的。
小结
在本文中,我们为数据库给出了一个比较正式的定义,即一组文件,但在现实中,这个定义的外延并没有非常严格:如果我们主观认为某个数据集的元素是相互关联的,我们通常就会称之为数据库。研究数据如何关联是非常重要的,无论数据位于单个文件中还是分布在多个文件中。在这方面的研究过程中,还要面对巨大的复杂性:着手一项新任务时,我们通常会面临大量文件名和扩展名没有具体含义的文件,以及处理这些文件的程序。为此,我们需要使用十六进制编辑器逐个检查文件,并检测其异同,考察其可能的各种结构,检查是否存在文本文件,等等。之后,我们才会考察程序本身。当完成审查后,我们可能会得到一些独立的线索,重要的是,留下线索的人并不希望让我们搞清楚。在后面的文章中,我们将为读者具体介绍如何处理这些棘手的问题。