逆向工程合并 CRC/Command 字节

Reverse Engineering combined CRC/Command Byte

我有一个未知的 hash/CRC 字节,它是 4 位 random/crc/unknown 和 4 位控制标志。每次看到命令字节时,它总共可以有 16 种不同的字节形式。将有 16 个不同的小组。没有冲突,每个字节只见过一次。我正在对 Moshiboard/MS10105 激光控制板进行逆向工程。所以一些代码标志是可以猜到的。正如我可以逻辑地假设打开激光和关闭激光之间的差异应该是 bit-flip.

这似乎是一个坚实的谜题,但我真的想不通。有很多信息可供参考,但也有很多未知数。一些控制组从未出现,因此我没有。

1. 0A 0E 1A 1E 4A 4E 51 53 59 5A 5B 5E 71 74 79 7B
2. 00 01 03 04 09 0C 10 14 21 23 29 2B 40 44 50 54
3. 55 57 5D 5F 75 77 7D 7F 8A 8E 9A 9E CA CE DA DE
4. 05 07 0D 0F 25 27 2D 2F 80 84 90 94 C0 C4 D0 D4
5. AA AE BA BE D5 D7 DD DF EA EE F5 F7 FA FD FE FF
6. 15 17 1D 1F 35 37 3D 3F 88 8C 98 9C C8 CC D8 DC
7. 45 47 4D 4F 65 67 6D 6F 82 86 92 96 C2 C6 D2 D6
8. A2 A6 B2 B6 C5 C7 CD CF E2 E5 E6 E7 ED EF F2 F6

注意:这些按数字排序,因为它们的实际顺序未知。

有另一个命令代码范围的部分版本 08 0C 13 19 1B 1C 31 3B 48 58 5C ?? ?? ?? ?? ?? 我可以用更大的样本量计算出来。虽然我可能也可以通过模式来解决它。

1. Command header control byte. Followed by 1 int16_le. (Speed, Unk)
2. Position byte. Followed by 3 int16_le
3. Laser Off, X value, Y value. Followed by 2 int16_le
4. Termination byte. 0 int16_le
5. Laser On, X value, Y value. Followed by 2 int16_le
6. Laser Off, Y value. Followed by 1 int16_le
7. Laser Off, X value. Followed by 1 int16_le
8: Laser On, X value. Followed by 1 int16_le.

现在我可以合理地假设 3 和 5 有一点不同。 7和8有点不同。字节码中有很多模式。其中 4 位是随机的。它们可能是 CRC 或者实际上只是纯粹随机的,字节在组内均匀分布。所以 4 non-control 字节可能是均匀分布的。

鉴于我不知道散列,甚至不知道这些字节的位置。这可以解决吗?我认为如果有一种非常简单的方法来进行散列,那么这个位置是可以解决的。我对随机位一无所知。我只能对其他部分进行一些有根据的猜测。但是,模式 3、4、6 和 7 之类的东西非常相似,我可以清楚地说,如果你将 0x50 添加到 3 的前 8 个字节并从第二个 8 字节减去 0x0A,这些模式是相同的。或者,如果您为前 8 个字节添加 0x10 并从第二个 8 字节中减去 0x08,则 4 和 6 相同。

但是我无法解决它。由于上下文含义(3,5 和 7,8),我认为应该分开 1 位的部分看起来不太相似。我的意思是#5 的部分显然是#3 的 2x 部分。一些似乎被移位,其他似乎在高半字节和低半字节中的静态量。

这里有很多图案,它是 2013 系列激光板,所以它不会做一些高度处理器密集型的事情。


其他似乎不是高度相关的可用信息:https://github.com/meerk40t/moshi 项目,以及那里的 wiki。


所有数字均为十六进制。

这些都是激光切割机控制板解释的同一命令的不同形式。

这些是使用 wireshark 拦截的,运行 通过 USB 通道。然后将消息发送到 CH341 串行芯片。

X 和 Y 值是激光切割机要到达的位置。这些由 16 位小端值给出。发出的命令有某种标志,表明正在发送什么类型的值。 x 或 y 或两者和 y。这些是不同的命令,但每个命令有 16 种形式。

我的意思是在命令结构中,这 16 种形式之一的特定命令后跟一个小端形式的 16 位整数。

问题是我希望这些值是相同的值,通常用某些字节标记为打开或关闭,以从激光切割软件中解释此命令希望激光切割板执行的操作。但是,我有 16 个命令表示 1 个(我认为)事物,而不是 1 个命令表示 1 个事物。这看起来很奇怪。有一堆图案,但我真的不知道那个图案是什么。

def swizzle(b, p7, p6, p5, p4, p3, p2, p1, p0):
    return ((b >> 0) & 1) << p0 | ((b >> 1) & 1) << p1 | \
           ((b >> 2) & 1) << p2 | ((b >> 3) & 1) << p3 | \
           ((b >> 4) & 1) << p4 | ((b >> 5) & 1) << p5 | \
           ((b >> 6) & 1) << p6 | ((b >> 7) & 1) << p7

def convert(q):
    if q & 1:
        return swizzle(q, 7, 6, 2, 4, 3, 5, 1, 0)
    else:
        return swizzle(q, 5, 1, 7, 2, 4, 3, 6, 0)

适用于将代码行变成:

['50', '51', '52', '53', '54', '55', '56', '58', '59', '5a', '5b', '5c', '5d', '5e', '5f', '8e']
['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a', '0c', '0d', '0e', '0f', '18']
['70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7a', '7b', '7c', '7d', '7e', '7f']
['20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2a', '2b', '2c', '2d', '2e', '2f']
['f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'fa', 'fb', 'fc', 'fd', 'fe', 'ff']
['30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3a', '3b', '3c', '3d', '3e', '3f']
['60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6a', '6b', '6c', '6d', '6e', '6f']
['e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'e9', 'ea', 'eb', 'ec', 'ed', 'ee', 'ef']

根据位奇偶校验,使用的模式略有不同。第一行和第二行中有一个不符合模式的错误数字。在这两种情况下,这个数字都会比 one 预测的数字增加 1。这至少是可用的。可能有不同的算法导致 swizzling 进位错误导致向下舍入 0x0C 不是 0x0B 和 0x74 不是 0x73。

这也预测了其他看不见的模式是:

['00', '01', '40', '03', '10', '21', '50', '23', '04', '09', '44', '0b', '14', '29', '54', '2b']
['08', '11', '48', '13', '18', '31', '58', '33', '0c', '19', '4c', '1b', '1c', '39', '5c', '3b']
['80', '05', 'c0', '07', '90', '25', 'd0', '27', '84', '0d', 'c4', '0f', '94', '2d', 'd4', '2f']
['88', '15', 'c8', '17', '98', '35', 'd8', '37', '8c', '1d', 'cc', '1f', '9c', '3d', 'dc', '3f']
['02', '41', '42', '43', '12', '61', '52', '63', '06', '49', '46', '4b', '16', '69', '56', '6b']
['0a', '51', '4a', '53', '1a', '71', '5a', '73', '0e', '59', '4e', '5b', '1e', '79', '5e', '7b']
['82', '45', 'c2', '47', '92', '65', 'd2', '67', '86', '4d', 'c6', '4f', '96', '6d', 'd6', '6f']
['8a', '55', 'ca', '57', '9a', '75', 'da', '77', '8e', '5d', 'ce', '5f', '9e', '7d', 'de', '7f']
['20', '81', '60', '83', '30', 'a1', '70', 'a3', '24', '89', '64', '8b', '34', 'a9', '74', 'ab']
['28', '91', '68', '93', '38', 'b1', '78', 'b3', '2c', '99', '6c', '9b', '3c', 'b9', '7c', 'bb']
['a0', '85', 'e0', '87', 'b0', 'a5', 'f0', 'a7', 'a4', '8d', 'e4', '8f', 'b4', 'ad', 'f4', 'af']
['a8', '95', 'e8', '97', 'b8', 'b5', 'f8', 'b7', 'ac', '9d', 'ec', '9f', 'bc', 'bd', 'fc', 'bf']
['22', 'c1', '62', 'c3', '32', 'e1', '72', 'e3', '26', 'c9', '66', 'cb', '36', 'e9', '76', 'eb']
['2a', 'd1', '6a', 'd3', '3a', 'f1', '7a', 'f3', '2e', 'd9', '6e', 'db', '3e', 'f9', '7e', 'fb']
['a2', 'c5', 'e2', 'c7', 'b2', 'e5', 'f2', 'e7', 'a6', 'cd', 'e6', 'cf', 'b6', 'ed', 'f6', 'ef']
['aa', 'd5', 'ea', 'd7', 'ba', 'f5', 'fa', 'f7', 'ae', 'dd', 'ee', 'df', 'be', 'fd', 'fe', 'ff']

按字节顺序给出而不是排序。