包含精灵的逆向工程文件

逆向工程 二进制格式
2021-06-16 20:47:24

我正在尝试对包含精灵的文件进行逆向工程。我想从文件中提取精灵。到目前为止,我已经设法找到了某种行尾序列,因此我已经能够确认精灵在文件中:

文件的单色转储

我正在使用 C++ 和 SDL。我将文件作为一系列字符加载,然后在字符>128 时绘制一个白色像素,如果字符<128 则绘制一个黑色像素。它非常粗糙,我不知道如何进行。如何找到存储颜色的位置?还是 alpha 通道?或者标题里有什么?等等。

如果您知道任何可能有用的在线资源,请告诉我。我有点不知从何开始。这些是我试图逆向工程的文件中的前几个字节,也许这会有所帮助:

文件的十六进制转储

游戏是战争状态。重制这款游戏是我儿时的梦想。我目前正在重新制作,但我正在使用占位符图形。这就是为什么我需要精灵。我不会将其用于商业目的。

有两种精灵文件。*.tsp 文件,以及一个很大的 sprites.data 和 sprites.info 文件。我在这里上传了一些文件

2个回答

你起步很好;将未知数据绘制为像素立即向您显示这确实是图形数据,未压缩(至少按钮不是),并且按可用的 RGB 顺序排列。我猜是缺少 RGB 格式阻碍了你;现在您知道了,您可以编写一个简单的程序来绘制彩色图并显示图像的偏移量和宽度。有了这些信息,您就可以检查图像之前(也可能是之后)的未知字节,并得出它们的含义。


总体概述

该文件001_buttons.tsp由一系列图像组成,没有通用文件头,但每个图像都有一个头。

这个头的第一个长字(4个字节,小端格式)是后面数据的字节大小,不包括头本身(这个长度可能是0)。然后按照宽度和高度作为单词。接下来的 12 个字节是 3 个字大小的 x,y 对;第一对是图像的中心。坐标是带符号的字,它们环绕在0xFFFF/2. 其他对仍然用于未知目的。

之后,您有 (height) 乘以words 中下一个图像扫描行的偏移量,从起点偏移 4(因此 4+2*offset = 下一行)。

这些偏移指向的每条扫描线都经过行程编码 (RLE) 压缩。透明运行仅由要跳过的水平像素数表示;不透明的运行可以直接复制到屏幕上。这些图像中没有 alpha 透明度。解压缩后,每条扫描线正好填充宽度像素。

像素格式打包为 16 位 RGB: RRRR.RGGG.GGGB.BBBB,可以通过以下(未优化)方式转换为 24 位 RGB:

putpixel (x,y, (((val >> 8) & 0xf8)<<16) | (((val >> 3) & 0xfc)<<8) | ((val & 0x1f)<<3) );

whereval只是下一个词:data[c]+(data[c+1]<<8)

样品转储


行程编码格式

rle 解压后的图像

下文提到的所有值都是大小(2 个字节,小端)。
每个扫描行都以该行的命令数和一个标志开始,该标志指示是以“跳过”还是“复制”开始。如果命令数后的标志字是0000,则该行以“跳过”开始,如果是0001,则该行以“复制”开始。
之后,“跳过”和“复制”命令交替进行,直到填满整个扫描线。每个命令是要跳过或复制的像素数;对于“复制”,实际像素值紧随其后。

所有行都应该完全填充——如有必要,命令列表以一些要跳过的“空”像素结束。

新游戏叠加


并非所有对象sprites.data 都是这种格式的精灵。至少有两种不同的类型:

  1. 单色遮罩对象,使用相同的 RLE 压缩方案但没有像素数据——它只包含每次运行的长度。这可能是绘制蒙版、覆盖颜色或帮助选择像素完美的对象。

  2. 未知用途的带符号单词对列表。

这些对象和实际精灵一开始都没有可识别的标识符,因此您只能通过反复试验找出哪个是哪个(例如:如果报告的图像“大小”是负数或大于整个数据文件,您知道它毕竟不能是 RLE 压缩的图像)。


精灵索引文件

索引文件sprite.info被混淆了,但不是很多。它具有以下格式:

4 x some byte flag (all `01` in this file)
long  total number of objects (377, in this file)
377 x
      0-terminated "filename" (obfuscated)
      long offset in 'sprite.data'
      long length in 'sprite.data'

通过向10每个字符添加常量混淆文件名解码这个,你会得到一个包含 377 个项目的列表:

__extras\compplay.ps6                | 00000000 000000C0
__extras\dim1.ps6                    | 000000C0 00000BC4
__extras\dim2.ps6                    | 00000C84 00000EB4
...
units\tur_05_blue.ps6                | 01FAC346 00013E12
units\tur_05_gren.ps6                | 01FC0158 00013E12
units\turrets_shadow.ps6             | 01FD3F6A 00013C9C

这是某种通用索引,因为显然并非所有图像都被列出。它必须只列出动画集的第一个;“长度”是该特定集合中所有文件的总长度。文件扩展名是对其内容的一种提示:以.ps6all结尾的文件至少包含一个图像(并且可能包含更多),以 结尾的文件.msk可能是单色蒙版和.sha阴影。这些文件包含坐标对。.podigit

如果您真的想了解文件的每个字节,那么正如 Jason 指出的那样,您必须获得读取它的程序并对其进行逆向工程。

当然,这可能介于困难和不可能之间,而且也非常耗时。所以问题是你想做什么。从文件中提取某个精灵?改变一些精灵的颜色?将游戏翻译成其他语言?可能,您不需要为了您的目的理解整个文件。

看来您已经建立了文件似乎未压缩,并且每个像素似乎有一个字节。还是那两个字节?十六进制转储包含很多 00,因此这些可能是 16 位字,其中仅使用低字节。

整个“每像素一个字节”表明调色板颜色表。您可能会尝试用相同的值替换其中一个精灵的每个像素(= 十六进制值)。启动游戏,检查精灵的颜色。用不同的值重复。您也许能够算出哪个值对应于哪种颜色。

该图像表明精灵具有不同的宽度。您可以计算像素(宽度和高度)并在十六进制转储中搜索这些计数。这可能会帮助您确定每个精灵前面的标题结构。

如果您知道每个精灵的大小(以字节为单位),您可以在十六进制转储或文件头中检查这些大小。或者,标题可能包含精灵的数量,以及文件中起始位置的数组。

所以,总结一下:

  • 写下你知道的可以用整数表示的任何东西。在文件中搜索这些整数。
  • 当您认为您对文件中的某个字节有所了解时,请想一想如果将该字节更改为其他字节会发生什么。更改该字节,启动原始程序,并检查其更改后的行为是否符合您的假设。
  • 根据需要重复。

另一个建议:当您在此处发布任何内容时,请包含尽可能多的信息。例如,在版权许可的情况下,发布整个 sprite 文件,而不是其十六进制转储的图像 - 您可以假设如果有人感兴趣,他们可以自己将文件下载到十六进制查看器。如果您有部分源代码,请发布指向该源代码的链接。很多逆向工程都是经验,比如“我以前见过类似的东西——那一次,它是 XXX”。有人可能只是看看你的来源并记住了一些东西。或者,有人可能有想法并将问题视为“拼图挑战”。如果您当前的源代码可用,则测试这个想法会容易得多。

有一次,我在文件格式方面遇到了类似的问题,谷歌为我找到了一个 7 年前的论坛帖子,来自一个做了一些研究的人,发布了他的结果,没有进一步并失去兴趣。这帮助我开始,我联系了那个人,我们一起终于得到了一些结果。所以,即使现在没有人能帮到你,你永远不知道未来会发生什么。

(当然,如果你发布游戏名称,别人在谷歌上找到你的帖子的机会就会增加很多......)