我已经逆向工程了由过去是同一家公司。在前一个版本中,我能够从
8051
转储EPROM
微控制器程序并将其反汇编。这是我在C中的工作代码,注释中带有原始8051
的反汇编:unsigned char CalculateChecksum(void) {
unsigned char r1 = 0; // MOV R1,#0
unsigned char r2, r3, c, a;
for (r2=1; r2<4; r2++) { // MOV R2,#07
a = out_buffer[r2]; // MOV A,@R0
r3 = a; // XCH A,R1
a = r1;
r1 = r3;
c = 0; // CLR C
if (a & 0x80) {
c = 1; // FAKE CARRY
}
a = a << 1; // RLC A
if (c == 1) { // JNC 0x03E8
a = a ^ 0x19; // XRL A,#19
}
a = a ^ r1; // XRL A,R1 (0x03E8)
r1 = a; // MOV R1,A
printf("%d: 0x%x ", r2, a);
}
return a;
}
问题是此功能在此较新的系统上不起作用。我已经尝试了所有255个可能的多项式,所以不清楚算法是否在不同系统之间共享(也许进行了一些修改?),但是我认为算法之间存在联系。
这里是从一个单元捕获一些已传输消息的信息:
7E 00 12 03 00 50 FB 01 60
7E 00 12 03 00 50 FB 01 60
7E 00 12 03 00 50 FB 01 60
7E 00 12 03 00 50 FB 01 60
7E 00 12 03 00 51 FB 01 61
7E 00 12 03 00 51 FB 01 61
7E 00 12 03 00 51 FB 01 61
7E 00 12 03 00 51 FF 01 65
7E 00 12 03 00 51 03 00 69
7E 00 12 03 00 51 09 00 6F
0x7E似乎是一个前同步码,后跟7个字节的数据,然后是校验和字节。有人能弄清楚吗?
#1 楼
这个问题似乎比您预期的要简单。由于如OP所述,代码与所讨论的系统中使用的验证机制无关,因此我将忽略它。确实是无关紧要的,如下所示。
由于每个消息中的第一个字节确实看起来像是一个序言,我们将忽略它。我们的目标是恢复功能,当该功能应用于给定的第1-8个字节(即,除了第一个和最后一个字节之外的所有字节)时,将提供最后一个字节。
让OP接收OP提供的第一个消息:
00 12 03 00 50 FB 01 60
因此,我们需要找到
f
,使得f(00 12 03 00 50 FB 01) = 60
以下3条消息相同。这很好,它揭示了验证字节对于消息字节而言是确定性的事实,否则无效。
我们将跳至第五条消息,并将其与第一条消息进行比较:
f(00 12 03 00 50 FB 01) = 60
f(00 12 03 00 51 FB 01) = 61
这很好,我们知道一点点消息的第5个字节中的增量更改会导致输出完全相同的更改。将第五个字节加一个也将使输出也加一。
最后两个消息也是如此:
f(00 12 03 00 51 03 00) = 69
f(00 12 03 00 51 09 00) = 6F
9-3 = 6 = 6F-69
时间具有不同的字节并具有更大的增量。
我们可能愿意假定此关系对于所有字节和所有增量均得以保留,我们将是正确的。
如果直到现在还不清楚,答案就摆在我们面前:最后一个字节是所有消息字节的总和,取模257。
在python中,给定
m = ['00', '12', '03', '00', '51', '09', '00']
,以下代码将提供正确的0x6F
值:hex(sum(map(lambda x: int(x, 16), m))%257)
对于所有提供的输入,此行为均正确。
评论
感谢您的帮助!我尝试了您的Python代码,它对于示例中的数据正常工作,但是如果您使用m = ['00','12','03','00','50','FB','01 ']结果为0x61,应为0x60。我在这里做错什么了吗?
–约翰·沃尔兹(John Voltz)
16-9-29在14:19
实际上,它使用mod 257而不是mod 256可以完美地与所有输入配合使用。感谢您的帮助,我不知道自己是否可以解决这个问题。
–约翰·沃尔兹(John Voltz)
16-9-29在15:35