查找使用的校验和算法

11

我和其他人正在尝试为一个游戏制作一个存档编辑器,但我们遇到了一些问题。存档文件包含一种校验和,我们无法确定该校验和的类型。目前我们所知道的是:

  • 校验和为32位
  • 对于9个完全相同的存档数据,除了5个字节(分散在文件中),解析为无符号长整型后的校验和介于1834565-1851372之间。请注意,每次保存时,这5个字节都会以增加的数字保存(大多数情况下增加约8个),但校验和并没有线性增加。
  • 校验和似乎与位置有关,因为当更改2个字节时,游戏将其声明为损坏的文件。
  • 我尝试了一些校验和,并得出结论认为它似乎不是Sum32、addler32、DJB2和CRC32,因为它们中没有一个能接近存档中包含的校验和。它似乎最接近存档中包含的校验和的校验和方法似乎只是将所有字节添加到一个无符号长整型中,返回一个约为~2507737的值。

我想知道是否有更好的方法找出用于这些文件的校验和类型,或者是否有人知道任何提示来找出使用的校验和。我目前只是在C++程序中尝试一些我在不同网站上找到的校验和。也许还重要的是,这个游戏是从2004年开始的,在其他文件中它使用DJB2进行字符串哈希。据其他人称,.exe似乎正在使用CRC32检查。

编辑1:经过一段时间的努力,我成功获得了924个完全相同的文件版本,除了每次保存都会变化的2个字节,我还获取了这些文件的校验和以查看它们对这些更改的反应,并制作了一个列表。(请注意,我无法手动更改文件并且游戏只是为其生成一个校验和,每次保存文件时,它将+2添加到包含变量数字的无符号长整型中,因此我创建了这个列表。)

下面是该列表的一部分(其中包含50个记录,共924个记录):

>         The bytes         Checksum (as Hex and unsigned long)
>         -----------------------------
>         0x 0 0x18 0x 0    0x13DFA 81402
>         0x 0 0x19 0x 0    0x13F76 81782
>         0x 0 0x1A 0x 0    0x1406D 82029
>         0x 0 0x1B 0x 0    0x14114 82196
>         0x 0 0x1C 0x 0    0x13EC5 81605
>         0x 0 0x1D 0x 0    0x13790 79760
>         0x 0 0x1E 0x 0    0x143C1 82881
>         0x 0 0x1F 0x 0    0x13ED0 81616
>         0x 2 0x18 0x 0    0x13D02 81154
>         0x 2 0x19 0x 0    0x13ABD 80573
>         0x 2 0x1A 0x 0    0x14271 82545
>         0x 2 0x1B 0x 0    0x13E39 81465
>         0x 2 0x1C 0x 0    0x140FC 82172
>         0x 2 0x1D 0x 0    0x13FFE 81918
>         0x 2 0x1E 0x 0    0x1413B 82235
>         0x 2 0x1F 0x 0    0x13A5F 80479
>         0x 4 0x18 0x 0    0x138F2 80114
>         0x 4 0x19 0x 0    0x141AE 82350
>         0x 4 0x1A 0x 0    0x13E91 81553
>         0x 4 0x1B 0x 0    0x13F67 81767
>         0x 4 0x1C 0x 0    0x13C6C 81004
>         0x 4 0x1D 0x 0    0x13F4E 81742
>         0x 4 0x1E 0x 0    0x13BB8 80824
>         0x 4 0x1F 0x 0    0x1398D 80269
>         0x 6 0x18 0x 0    0x146C0 83648
>         0x 6 0x19 0x 0    0x139B5 80309
>         0x 6 0x1A 0x 0    0x13FAC 81836
>         0x 6 0x1B 0x 0    0x13E71 81521
>         0x 6 0x1C 0x 0    0x14162 82274
>         0x 6 0x1D 0x 0    0x13D55 81237
>         0x 6 0x1E 0x 0    0x13BE8 80872
>         0x 6 0x1F 0x 0    0x13B72 80754
>         0x 8 0x18 0x 0    0x142FE 82686
>         0x 8 0x19 0x 0    0x13E07 81415
>         0x 8 0x1A 0x 0    0x14923 84259
>         0x 8 0x1C 0x 0    0x13D3E 81214
>         0x 8 0x1D 0x 0    0x14420 82976
>         0x 8 0x1E 0x 0    0x13BEE 80878
>         0x 8 0x1F 0x 0    0x145F5 83445
>         0x 8 0x1F 0x 0    0x145F5 83445
>         0x A 0x18 0x 0    0x13CB6 81078
>         0x A 0x19 0x 0    0x142FB 82683
>         0x A 0x1A 0x 0    0x13EB2 81586
>         0x A 0x1B 0x 0    0x13C14 80916
>         0x A 0x1C 0x 0    0x13915 80149
>         0x A 0x1D 0x 0    0x14100 82176
>         0x A 0x1E 0x 0    0x14310 82704
>         0x A 0x1F 0x 0    0x13B34 80692
>         0x C 0x18 0x 0    0x142AE 82606
>         0x C 0x19 0x 0    0x14091 82065
我仍然无法看出这些不同的字节和校验和之间的模式,所以我想知道是否有其他人能够看出它们之间的模式?或者有没有一种找到它们之间模式的技巧。如果有人能帮我解决这个问题,我也可以发布完整列表的链接(以Microsoft Excel或TXT格式)。

2
不要忘记有许多CRC变体。此外,您应该以二进制或十六进制编写校验和,以使任何位运算都变得明显。 - phihag
3
最简单的方法是获取用于计算校验和的函数的反汇编代码(当然这可能说起来比做起来容易)。你能否以某种方式系统地更改保存文件中的值(比如说你的生命值/金钱/物品数量)?如果可能,请获取生命值从0到255(或任何可能的值)的游戏存档文件,并查看它们如何改变校验和,然后与其他可能的变量结合起来。 - user786653
3
如果你无法反汇编函数,这可能会很困难。我自己写了校验和以防止数据篡改,永远不会使用标准哈希函数,因为它可能被猜测。相反,我编写自己的定制哈希函数并将其与标准哈希组合以获得“雪崩效应”,然后进行混淆处理。如果程序的作者按照我所说的做法,反向工程哈希函数几乎是不可能的,除非进行反汇编。 - Mysticial
1
现在您已经拥有了这些数据点,我建议选择一些相似的数据并将它们列在表格中。开始删除所有相同的部分。个人而言,我会使用带有0x13开头的校验和的所有值来减少变量数量,并可能暴露出子模式。 - ccozad
1
我开始根据相似性进行一些分析,然后再次阅读了您的描述。您说不同文件之间不同的字节是分散的吗?它们总是在相同的位置吗?您能否发布两个二进制文件? - ccozad
显示剩余7条评论
1个回答

7
最简单的方法可能是使用调试器(例如OllyDbg)定位校验和代码并进行反向工程。这并不意味着这很容易,因为它可能会相当困难。但在我看来,仅通过查看数字尝试反向工程即使是简单的校验和也几乎是不可能的,除非你有一个高机能的自闭症朋友具备超人类的模式识别能力 - 甚至那样也不一定成功。
如果你运气好,可能会找到一个使用标准且众所周知的校验和算法来检测损坏的游戏。但如果他们的目标是防止篡改(这可能相当可能),那么如果他们有任何头脑,就不会使用标准校验和算法。
这是我正在玩耍的Crackme中的校验和算法: checksum algorithm 我肯定无法仅通过查看输出来猜出这段代码。
uint sum = 0;
for (uint i = 0; i < 478; i++)
    sum = rol((((buf[i + 22] | 0xFFFFFF00u) + i) ^ (478 - i)) - sum + 0x272E4745u, 3);

在这段代码中,有一个单独的校验和算法,它使用符号扩展而没有完全销毁它通过一个 or 0xFFFFFF00 操作 - 您是否在搜索中考虑过这样的操作?搜索空间太大了,无法猜测...


感谢您的回答,我的评论有些晚了,但我花了相当长的时间来研究它。通过观察汇编代码,我发现了一些规则,这些规则似乎表明删除文件开头的标头和文件末尾的校验和也可以起作用,而且确实如此。因此,通过删除标头和校验和,我实际上绕过了查找校验算法的需要。感谢所有帮助过我的人! - Joey

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