逆向工程一个奇怪的 24 位可能不是 CRC 校验和

逆向工程 CRC
2021-06-12 10:43:05

是的,它就是其中之一!

我有一个 199mumble Brother 集成文字处理器,具有非常奇怪的非 PC 软盘格式。我已经构建了一个软盘控制器并成功地从磁盘读取了通量,解码两种 GCR,并将结果重新组合成磁盘映像。但是我需要能够检查扇区中的校验和以了解我是否做得对。(眼珠子看起来不错。)

每个扇区是 256 字节,后跟三个字节,这取决于扇区的内容——相同的扇区产生相同的值,所以我假设它是一个校验和。有趣的是,全零扇区产生全零校验和,因此我怀疑它不是常规 CRC。

我有 100 个不同的示例,但其中可能有一些不正确的结果(由于误读扇区);完整列表位于https://pastebin.com/0HZrUVPR但这里有一些选定的示例,希望采用 reveng 格式,因此校验和位于最后三个字节:

00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005750314120464c4f505059080000000000000000000000000000000000000000616161616161616120202020000000000000000000000000000002000a5d000064656d6f20202020a4ca1a
414141414141414141410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008b38af
414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141de6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738394141414141414141414141414141414141414141414141414141414141de4141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141de4141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141415a6ea1
41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141de4141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141de6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738394141414141414141414141414141414141414141414141414141414141de41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141413362ac

请注意,最后两个包含相同的数据,向右旋转了整数个字节。

所以,我很难过。有一些 24 位 CRC,但它们似乎非常罕见。reveng 什么都没有,但我不完全确定我是否正确驾驶它——它似乎比任何进行蛮力搜索的东西都执行得更快。我尝试了一些微不足道的求和方法,但简单的方法不起作用,而且有太多变化只能猜测。

我将如何解决这个问题?

1个回答

一旦您了解了 CRC 是什么,答案就会变得非常简单

它类似于 CRC——校验和是输入除以具有截断表示的多项式时的余数0x000201

我写了一个快速的 Python 脚本来验证校验和:

def crc(data, poly):
    # width = 24 bit
    # data len = 2048 bit
    assert poly<(1<<24)
    for i in range(2048-1,24-1,-1):
        if data>>i&1:
            data^=1<<i
            data^=poly<<(i-24)
    assert i==24
    assert data<(1<<24)
    return data

import sys
for line in sys.stdin.read().splitlines():
    line = int(line,16)
    print(crc(line>>24,0x000201) == line&~(-1<<24))

在线试试吧!

crc函数可用于生成缺失的校验和值。

如何?

首先,我假设校验和函数满足属性:对于所有xy,我们有checksum(x) xor checksum(y) == checksum(x xor y)

对提供的数据使用高斯消元法,我可以推断出 的散列000000...000000bb0301bb0301看起来很合理。

然后,我阅读了现有的哈希函数并查看它们使用的方法。我注意到 CRC 使用多项式余数 mod 2,所以我猜散列是作为多项式的输入,模数为 25 的多项式(因为输出有 24 位)。

用简单的蛮力,我得出结论,多项式是000201测试表明它是正确的。

reveng 什么都没有,但我不完全确定我是否正确驾驶它——它似乎比任何进行蛮力搜索的东西都执行得更快。

为什么复仇执行得这么快?

这是因为只有 2 个可能的宽度多项式。reveng 只需要很少的时间来尝试每个多项式。在这种情况下,width = 24,因此只有 1048576 个多项式,这对于计算机来说不是很大。

为什么复仇不返回任何输出?这和CRC有什么区别?

CRCwidth在计算多项式余数之前(在这种情况下 - 24)位附加到输入,但该算法不会。