我真的很难弄清楚,现在谁能帮我逆向工程这个校验和?

逆向工程 串行通讯 CRC
2021-07-09 10:36:56

我有一个设备在工作,但没有关于它的校验和计算的文档。我知道每条消息的最后一个字节是校验和,并且大多数发送到设备的消息都需要正确的校验和。

我认为这很容易弄清楚,可能是一些 CRC 或其他什么,但我真的无法弄清楚。

我有一些消息(来自设备),只有一个字节发生变化,以便更容易找到模式。

每条消息的最后一个字节是校验和。

这些消息中的倒数第二个字节递增:

00h 5Ch A2h 00h 04h D2h 38h
00h 5Ch A2h 00h 04h 57h BDh
00h 5Ch A2h 00h 08h AEh 1Ch
00h 5Ch A2h 00h 00h 01h 7Fh
00h 5Ch A2h 00h 00h 02h 80h
00h 5Ch A2h 00h 00h 03h 81h
00h 5Ch A2h 00h 00h 04h 82h
00h 5Ch A2h 00h 27h 0Fh BCh

第 4 个字节递增:

00h 5Ch A2h 00h 00h 01h 7Fh
00h 5Ch A2h 01h 00h 01h 63h
00h 5Ch A2h 02h 00h 01h 67h
00h 5Ch A2h 03h 00h 01h 6Bh 
00h 5Ch A2h 04h 00h 01h 6Fh

我希望那里有人可以提供帮助,这对我来说真的很受欢迎。

编辑 - 添加了更多示例

00h 5Ch A2h 01h 01h 01h 65h
00h 5Ch A2h 01h 01h 02h 66h
00h 5Ch A2h 01h 01h 03h 67h
00h 5Ch A2h 01h 01h 04h 68h

00h 5Ch A2h 01h 01h 01h 65h
00h 5Ch A2h 01h 01h 02h 66h
00h 5Ch A2h 01h 01h 03h 67h
00h 5Ch A2h 01h 01h 04h 68h
00h 5Ch A2h 02h 01h 01h 69h
00h 5Ch A2h 02h 01h 02h 6Ah
00h 5Ch A2h 02h 01h 03h 6Bh

同一消息的另一个示例,其中最后 3 个字节是 00h:

00h 5Ch A2h 00h 00h 00h 7Eh

第二次编辑 - 向大量其他示例添加了 Pastebin 链接,所有示例都具有相同的消息类型

它是一条不同的消息,但有很多示例: Pastebin 中有很多示例消息

2个回答

关键是获得大量样本,以便分析有依据。如果您可以将样本保存在可以交互查询的数据库表或字典中,例如从某种脚本外壳中查询那真的很有帮助Python 应该可以很好地工作,但我对它没有太多经验,因为在过去的二十年里,我一直在使用 Visual FoxPro 进行交互式探索。

一旦您准备好要查询的样本,您就可以测试各种简单的假设并通过找到反例来反驳它们。例如,以下示例似乎表明第四个字节的差异导致校验和的四倍差异:

00h 5Ch A2h 00h 00h 01h 7Fh
00h 5Ch A2h 01h 00h 01h 63h
00h 5Ch A2h 02h 00h 01h 67h
00h 5Ch A2h 03h 00h 01h 6Bh 
00h 5Ch A2h 04h 00h 01h 6Fh

关键是找到仅在当前“工作”列和校验和中不同的样本,以研究工作列中的更改对校验和的影响。例如,给定上面的输入,我们可以记4 * b[3]下第四个字节的初步术语,然后在示例数据库中查询反例,如果这不起作用。也就是说,您选择仅在第四个字节和校验和上不同的样本对,并计算成功和失败的次数

delta(checksum) mod 256 == 4 * delta(byte[3]) mod 256.

反正就是这个想法。是什么样的事情delta(checksum) mod 256实际上看起来像取决于你的脚本外壳,效果显着。使用 VFP 将是

mod(256 + asc(substr(right, 7, 1)) - asc(substr(left, 7, 1)), 256)

上面测试的完整表达式会很长,因此您通常会编写很少的辅助函数。使用名为的助手将byte_delta()其结果规范化到 [0, 255] 范围内,您可能有

select le.sample as left, ri.sample as right ;
   from all_samples le, all_samples ri ;
   where stuff(left(ri.sample, 6), 4, 1, "") == stuff(left(le.sample, 6), 4, 1, "") ;
      and le.sample <> ri.sample ;
   into cursor byte_3_pairs

select byte_delta(right, left, 7) == mod(4 * byte_delta(right, left, 4), 256) as ok, count(*) ;
   from byte_3_pairs ;
   group by 1

在考虑的情况下,您将获得此查询的混合图片(请参阅上面第一个和第二个示例之间的区别,即 E4 而不是 4)。通常你会先做一些选择差异,只是为了感受一下。“差异”可以是算术差异,按位异或,等等。

这就是为什么你需要一个像 Python 或 VFP 这样的交互式 shell;对于编译语言的编辑-编译-运行循环,这将是相当麻烦的。我已经给出了 VFP 示例,因为具有数据库支持的脚本语言可以使这里的事情变得容易得多。

对于像 ISBN 之类的东西中通常的“人类可计算”校验和这样的简单加权和,这可以提供相当快的结果。我已经使用这种方法从不同数量的样本中确定了德国健康保险号码中使用的所有校验位方案——这些方案大多没有记录(或者至少在当时没有记录)。当然,在那种情况下,我的优势在于方案的基本类型 - 加权数字总和 - 是已知的,并且样本已经驻留在数据库表中......

正在讨论的案例比较困难,因为基本方案尚不清楚。这就是为什么查看位模式以了解事物很重要的原因。例如,冒泡进位表示加法函数。这在主题反转简单消息 + 校验和对(32 字节)中有更详细的解释,其中还显示了一些更改模式示例。

PS:除了尝试梳理特定位或字节变化的校验和差异之外,当样本被填充到某种可查询的表/字典/映射中时,还有很多其他的事情可以做。第一件事通常是使用现有的标准函数运行一系列测试,如直接字节和、直接字节异或、各种 CRC 等,以观察校验和的差异(算术和异或)。将结果显示为位模式 - 如链接文章中所示 - 通常有助于辨别在十六进制或十进制格式中不太明显的规律。

更新目前样本太相似(前三个字节没有差异),而且样本太少,无法快速丢弃假设。换句话说,适合现有数据的潜在函数太多了……

例如,以下简单的 Fox 函数正确预测了原始少数样本的校验和,除了少数情况下它偏离了 0x20:

function f (s)

   local x, i

   x = 0
   for i = 1 to len(m.s) - 1
      x = bitand(bitlshift(m.x, 1) + asc(substr(m.s, m.i, 1)), 0xFF)
   next i

   return bitand(m.x + 0x8E, 0xFF)

这可能是因为它是旋转而不是移位,或者涉及一些异或,或者与每个字节的位数重叠以在第四个字节和校验和之间创建两位距离的其他移位(相对于 8 为素数)。轮换 5 将做到这一点。然而,还有很多其他的可能性……这就是我们需要更多样本的原因。;-)

分析PasteBin 上样本表明,校验和之前最后一个字节位置的差异始终等于校验和的差异。这意味着可以从样本库中删除最后一个字节及其对校验和的影响。这增加了仅在一个字节位置上不同的样本数量,这意味着有更多容易实现的分析结果......

例如样品

00 5C A0 00 00 00 00 00 06 00:69
00 5C A0 00 00 00 00 00 06 01:6A
...
00 5C A0 00 00 00 00 00 06 FF:68

all 映射到新样本(点表示已删除的字节,这里只是为了说明):

00 5C A0 00 00 00 00 00 06 . 69

缩短的样本库立即显示了“二的幂”规则不起作用的情况(这里的最后一个字节最初是倒数第二个):

00 5C A0 00 00 00 00 00 00 . 7D
00 5C A0 00 00 00 00 00 01 . 7F
00 5C A0 00 00 00 00 00 02 . 61  <- difference -0x20 to predicted delta 2
00 5C A0 00 00 00 00 00 03 . 63
00 5C A0 00 00 00 00 00 04 . 65
...
00 5C A0 00 00 00 07 00 00 . B5 
00 5C A0 00 00 00 08 00 00 . BD
00 5C A0 00 00 00 09 00 00 . A5  <- difference -0x20 to predicted delta 8
00 5C A0 00 00 00 0A 00 00 . AD
00 5C A0 00 00 00 0B 00 00 . D5  <- back on track with the earlier sequence

我想知道您是否在校验和解码方面取得了更多进展。我有一个非常相似的问题,我认为你的方法也适用于我的情况。这些是我想弄清楚校验和方法的数据,在早期的开发中丢失了很长时间:

00 8a 51 0b a0 b8 a1 00 8a 51 0b a1 b8 a3 00 8a 51 0b a2 b8 23 00 8a 51 0b a3 b8 25 00 8a 51 0b a4 b8 a3 00 5 0 8 5 b 8 a3 00 5 0 8 5 8 5 8a 51 0b a7 b8 27

如果您能更多地讨论您的进展,这可能有助于解决这个问题,我们将不胜感激。另外,我发现我可以交换半字节并且它也具有相同的校验和。提前谢谢你。