我将如何反转这个 simple-looking 算法?

How would I reverse this simple-looking algorithm?

我有一些旧的 LED 板,您可以向其发送一些文本并将其挂在某个地方...它是 1994/95 年制造的,它通过串行端口进行通信,具有 16 位 MS-DOS 应用程序,您可以在其中输入一些文本。

因此,因为除了使用 DOSBox 或类似技巧,您可能无法在任何地方 运行 它,所以我决定用 C# 重写它。

在 port-monitoring 原来的 dos-exe 之后,我发现它真的对你重建它不感兴趣 - 必须以合适的、不同的字节回答请求,pre-sent "ping" 消息等...

也许您知道与我的 dos-exe 使用的校验和 routine/pattern 相似,或者您可以提供任何尝试 reverse-engineer 的提示...此外,因为我只熟悉编程,并没有花太多时间在逆向方法上 and/or 分析协议,如果这个话题有点愚蠢,请不要评判我 - 我会很高兴得到任何帮助...

真正包含应该显示的文本的消息是 143 字节长(之所以这么长是因为如果您没有用完所有 space 与您的文本),并且在该消息中我注意到以下模式:

一些例子:

到目前为止,我完全确定校验和确实取决于 header 中的第四个字节,因为如果它发生变化,显示的相同文本的校验和将完全不同。

这是一个完整的 143 bytes-string 显示“123”的示例,只是为了让您更好地定位:

02 86 04 0F 05 03 01 03 01 03 01 03 00 01 03 00   ...............
00 31 00 32 00 33 00 20 00 20 00 20 00 20 00 20   .1.2.3. . . . . 
00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20   . . . . . . . . 
00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20   . . . . . . . . 
00 20 00 20 00 20 00 20 00 20 00 FE 03 01 03 01   . . . . . .þ....
04 01 03 00 01 03 00 00 20 00 20 00 20 00 20 00   ........ . . . .
20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00    . . . . . . . .
20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00    . . . . . . . .
20 00 20 00 20 00 20 00 20 00 20 00 20 45 52

(文本信息从第2行第2个字节开始 "31 00 32 00 33 00 (...)"

不幸的是,在整个网络上,没有用户手册、文档,甚至没有真正的证据表明此信息 board-device 曾经存在过。

输入字符串 s 时得到的校验和,我会写成 F(s)。

观察到:

  • F("122") xor F("123") = 95 F4 xor 45 52 = D0 A6
  • F("132") xor F("133") = 55 FF xor 85 59 = D0 A6
  • F("123") xor F("124") = 45 52 xor 56 62 = 13 30
  • F("133") xor F("134") = 85 59 xor 96 69 = 13 30

所有这些都与具有以下 属性 的校验和一致,校验和经常具有:更改输入中的给定位总是用相同的东西对输出进行异或运算.

我预测,例如,F("210") = F("211") xor D0 A6 = 8D C5,同样地,F("222") = 3C A8 xor C5 C8 xor 95 F4 = 6C 94.

如果这是真的,那么如果你有一个黑盒子来为你计算校验和(显然你有),那么下面给你一个蛮力的方法来计算校验和:

  • 查找所有位为 0 的输入的校验和。将此称为 a
  • 对于每个位位置k,求除位k为1之外所有位均为0的输入的校验和. 调用这个 a XOR b(k).
  • 现在任意输入的校验和是 a XOR 每个 b(k)其中位 k 在输入中设置。

通常 b(k) 彼此密切相关——通常的模式是你在喂比特进入移位寄存器 - 所以上面的内容比你对算法的理解所需要的更暴力。但我希望它能工作,如果你能够输入任意选择的位模式。

如果没有,您可能仍然可以做到。例如,假设您实际选择的是 29 个 7 位 ASCII 字符值,位于输入的位置 17,19,...73。然后,您可以首先输入所有空格 (0x20),然后依次将每个空格与位置 0..6 中的 1 位进行 XOR。这不会给你所有的 b(k) 但它会给你足够的任意 29-ASCII 字符输入。