如何根据起始和结束十六进制字符串提取二进制文件的一部分

如何根据起始和结束十六进制字符串提取二进制文件的一部分

我有一个很大的二进制文件(几百 GB),我想从中提取一段。我知道起点和终点的十六进制字符串。

答案1

一种可能的解决方案(假设您可以复制文件)可以使用以下示例

  1. 假设起始模式为十六进制 4f 0f 87 82
  2. 假设结束模式为十六进制 fb 8c e2 a0
  3. 假设输入文件被调用tf且长度为 5000 字节

然后

将其复制tf到一个新文件blah,并改变起始模式

$ LC_ALL=C sed 's/'`printf "\x4f\x0f\x87\x82"`'/'`printf "AAAA"`'/'  <tf > blah

tf现在找到和不同的位置blah注意 - sed 在修改后的文件末尾写入一个包含换行符的额外字节,因此我们将其与原始文件的长度进行比较。tf生成的文件blah应该长一个字节)。

$ cmp -n 5000 -b tf blah

这将给出文件不同的字节偏移量 bs,例如,

tf blah differ: byte 4337, line 10 is 117 O 101 A

现在对结束模式做同样的事情

 $ LC_ALL=C sed  's/'`printf "\xfb\x8c\xe2\xa0"`'/'`printf "AAAA"`'/'  < tf > blah2
 $ cmp -n 5000 -b tf blah2
 tf blah2 differ: byte 4433, line 10 is 373 ? 101 A

现在用来dd提取感兴趣的部分

dd if=tf skip=4336 bs=1 count=100 > fbit

一些额外的说明:

  1. 某些版本的 sed 支持-b将输入文件视为二进制的选项。其他版本则支持-z用 NUL 字符分隔行的选项。无论匹配包含新行的模式还是拆分为新行,都尚未经过测试。

  2. count=100将取决于匹配模式的长度以及匹配模式是否包含在提取物中(问题中没有明确说明)。一般公式是计数 = (结束偏移量) − (起始偏移量) + (结束模式的大小)。特定示例的片段为 4433-4337+1,共计 97 个字节。即从开始模式的开头到结束模式的第一个字节(包括第一个字节)。然后在此示例中添加额外的 3 个字节,共计 100 个字节,因为最终模式有四个字节,并且示例包含最终模式。如果不需要最终模式,则为count=96值。

  3. 可以使用一种对换行更稳健的方法,并使用 hexdump 命令。我还没有完全测试过这种方法。它本质上是使用 hexdump 和一些 sed、grep 和 tr 将原始二进制文件转换为 ASCII 格式的十六进制。然后可以应用相同的过程,但需要更复杂的算术等。所需的 hexdump 命令将是

    hexdump -v -x tf | sed s/'^[0-9]*\(.*\)/\1/' | sed s'/ *//g' | grep '[0-9]' | tr -d '\n' > tf.txt

  4. 完成此步骤后,可以采用hexdump相同的过程。要匹配的模式必须更新为使用十六进制转储 ascii 字符,而不是原始十六进制打印。sedcmp

  5. 这种方法还应该处理换行符。

  6. LC_ALL=C默认情况下,OSX 上似乎需要它。如果没有它,sed命令会给出错误RE error: illegal byte sequence。这可能不适用于所有平台和/或操作系统发行版。

相关内容