自动“蛮力”几个字节来恢复损坏的文件

Sbt*_*t19 35 repair data-recovery brute-force

有没有人知道在文件中的特定偏移量处蛮力值的方法?这是 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 程序。但是,它仅适用于程序中包含的文件。我正在寻找某种方法来对我的文件使用相同的过程。

tri*_*eee 28

这是一个小型 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')
Run Code Online (Sandbox Code Playgroud)

联合国只是简单测试;如果你发现错别字,请ping我。

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 = ...
Run Code Online (Sandbox Code Playgroud)

我颠倒了字节的顺序,使其自然地从 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 = ...
Run Code Online (Sandbox Code Playgroud)

但是如果你真的想检查所有这些,你需要确保自己的(start, end)rge覆盖了 0x00000000 和 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:]
Run Code Online (Sandbox Code Playgroud)