不,不,不,再说一遍不!

不,不,不,再说一遍不!

有谁知道在文件中某个特定偏移量处强制取值的方法吗?这是需要强制取的 4 个连续字节。我知道损坏文件的正确 SHA-1。因此,我想要做的是每次更改字节值时比较完整文件的 SHA-1。

我知道确切的 4 个字节被更改了,因为该文件是数据恢复专家给我的,作为恢复挑战。对于那些有兴趣了解的人来说,rar 文件中有 4 个字节是故意更改的。我被告知了更改的 4 个字节和原始 SHA-1 的偏移量。那个人说,一旦更改了 4 个字节,就不可能恢复存档中的确切文件。即使只有几个字节,而且您确切知道损坏的位置。因为它没有恢复记录。我正在尝试看看是否有办法正确填写这 4 个特定的字节,以便文件可以无错误地解压缩。文件大小约为 5mb。

例子

我上传了照片,这样可以更清楚地说明我到底想做什么。我相信有人可以在这里发布这些照片,让我获得更多的关注。

截图一

截图二

我关注的示例偏移量是0x78第一张图片显示的值,因为CA 我希望脚本将值增加 1,使其变为CB第二张图片所示。我希望它继续增加值1,然后每次比较整个文件的 SHA-1。仅对指定偏移量的那 4 个字节进行更改。

它会尝试CAC5C58A比较 SHA-1。如果不匹配,它会尝试CBC5C58A。然后一旦第一个值达到,FF它就会转到00C6C58A等等。基本上,我希望它能够从那里开始00000000-FFFFFFFF,但也可以选择你想要它从哪里开始和结束。我知道这可能需要一些时间,但我仍然想尝试一下。请记住,我知道损坏的字节的确切偏移量。我只需要正确的值。

如果您在 Google 上搜索:“如何通过强力修复损坏的文件”,有人编写了一个 Linux 程序。但是,它只针对程序中包含的文件起作用。我正在寻找某种方法对我的文件使用相同的过程。

答案1

这是一个小型 Python 程序,它可以完成您描述的操作。

#!/usr/bin/env python3
from hashlib import sha1

with open('binaryfile', 'rb') as bin:
    binary = bin.read()

base = 0x0078
# ... is not valid Python; add more sequences, or take it out (or see below)
for seq in [[0xCA, 0xC5, 0xC5, 0x8A], [0xCB, 0xC5, 0xC5, 0x8A], ...]:
    copy = binary[0:base]
    copy += bytes(seq)
    copy += binary[base+len(seq):]
    if sha1(copy).hexdigest() == '9968733ce3ff0893bbb0a19e75faaf2fb0000e19':
        print('success with bytes {0}'.format(seq))
        break
else:
    print('no success')

联合国仅短暂已测试;如果发现错别字,请通知我。

指定base尝试应用这四个字节的位置,长字符串'996873... 是预期 SHA1 的十六进制表示。行for seq in... 定义要尝试的字节;当然,将其替换'binaryfile'为您要尝试挽救的文件的路径。

您可以用某些东西替换文字列表[[0xCA, 0xC5,...]]来实际循环遍历所有可能的值,但它基本上只是一个更有用的东西的占位符,因为我不太确定您到底想要什么。

类似于for seq in itertools.product(range(256), repeat=4)):将循环遍历从 0 到 2 32 -1 的所有可能值。(然后您需要import itertools在顶部附近添加。)或者您可以简单地添加一个偏移量;更新脚本以将当前脚本替换for seq in为以下内容(再次需要import在主程序之前进行);

import struct

for n in range(2**32):
    val=(n+0x8AC5C5CA) % 2**32  # notice reverse order
    seq=list(reversed(struct.pack(">I", val)))
    copy = ...

我反转了字节的顺序,这样它自然地从 0x8AC5C5CA 递增到 0x8AC5C5CB,但下一个增量将是 0x8AC5C5CC 等。魔术struct是将其转换为字节序列(必须从中查找https://stackoverflow.com/a/26920983/874188)。它将从 0x8AC5C5CA 开始,到 0xFFFFFFFF,然后绕回到 0x00000000 并爬回到 0x8AC5C5C9。

如果你有多个候选范围,你想按特定顺序检查,也许像

for rge in [(0x8AC5C5CA, 0x8AFFFFFF), (0x00C6C58A, 0x00FFFFFF),
        (0x00000000, 0x00C6C589), (0x01000000, 0x8AC5C5C9)]:
    for val in range(*rge):
        seq=list(reversed(struct.pack(">I", val)))
        copy = ...

但你需要确保自己(开始,结束)如果你真的想检查所有空间,那么 中的对将覆盖rge0x00000000 和 0xFFFFFFFF 之间的所有空间。(再次注意,范围增加了最后的字节并seq根据您所规定的要求反向应用值的字节。)

如果您想使用两个不同的base地址,那么您很快就会遇到一生中用蛮力所能及的极限;但是,例如,您可以将 4 字节数字拆分为两个 2 字节部分,并将它们应用于不同的偏移量。

base1 = 0x1234
base2 = 0x2345

for seq in range(whatever):
    copy = binary[0:base1]
    copy += bytes(seq[0:1])
    copy += binary[base1+2:base1+base2]
    copy += bytes(seq[2:3])
    copy += binary[base2+2:]

答案2

不,不,不,再说一遍不!

你得到的答案很少会不符合你的预期。

向您提问一些问题:

  • 有可能专家不知道是否可以强行破解一串字节并迭代尝试 SHA-1 直到它收敛?
  • 他有可能忘记了吗?
  • 您是否无法对 rar 文件执行此操作?
  • 另一个答案错了吗?绝对错了

所以呢?... 时间。

关键在于您只需改变很少的字节...仅 4 个!

这是什么意思?256 4即 256x256x256x256 种可能性,一个非常非常大的数字。
如果你的计算机能够处理每秒 1 次操作(在文件 + sha1 中替换)...
你应该等136年以上,或者如果您愿意,可以超过 49710 天。

你很幸运,在旧电脑上,一个 5MB 的预缓存文件(已加载到内存和缓存中)只需要大约 0.03 秒(最少 0.025 秒)。这将你的预期时间缩短到 1242-1492 天(超过 3 年)。

确实如此,顺便说一句,从统计学上来说,一半的时间你应该会得到肯定的答案。尽管如此,您还是应该等到尝试了所有可能性之后再确定只有 1 个替换会给您相同的 SHA-1 校验和...

现在不可能的听起来“不可能值得多少时间”。


如何进行

对您的技术问题更恰当的回答是:当您谈到蛮力时,它不一定是盲目的蛮力。

  • 另一个答案的评论中只是指出,您不需要计算损坏前部分的 sha1 校验和。您只需第一次计算,就可以节省每次迭代的时间(可能是 2 倍,具体取决于位置)。

  • 可以改变努力毫无价值的事情是写一篇并行代码将在 GPU 上运行。如果您有一块好的显卡,您可能有大约 1000 个核心可以为您并行计算(甚至更多,但它们的频率低于 CPU,但仍然很多)。如果您能够将时间从 1400 天缩短到 1.4 天,也许您甚至可以做到。

  • A不同的方法可以让你更快地找到解决方案。
    你说这是一个 rar 文件。rar 文件结构被分成块。如果你计算一下,你就能知道损坏发生在何处。如果它在数据部分,在标题部分,或者两者都有。那么你可以采取相应的行动。为了简单起见,我们假设它是在数据上:
    你可以对偏移量进行强力攻击,检查该块的每个正 CRC,如果它是正的,则检查整个文件的 SHA1。同样,你可以执行并行代码。

最后说明

如果它们是 6 个字节而不是 4 个字节,那么使用现有技术你就已经出局了。

相关内容