如何转储部分二进制文件

时间:2012-02-26 09:16:09

标签: linux bash terminal dump

我有二进制文件并希望从已知字节字符串(即FF D8 FF D0)开始并以已知字节字符串(AF FF D9)结束提取部分内容

过去我曾使用dd从开始/结束中删除部分二进制文件,但此命令似乎不支持我的要求。

终端上的哪个工具可以做到这一点?

6 个答案:

答案 0 :(得分:7)

找到开始/结束位置,然后提取范围。

$ xxd -g0 input.bin | grep -im1 FFD8FFD0  | awk -F: '{print $1}'
0000cb0
$ ^FFD8FFD0^AFFFD9^
0009590
$ dd ibs=1 count=$((0x9590-0xcb0+1)) skip=$((0xcb0)) if=input.bin of=output.bin

答案 1 :(得分:3)

在一个管道中:

xxd -c1 -p file |
  awk -v b="ffd8ffd0" -v e="aaffd9" '
    found == 1 {
      print $0
      str = str $0
      if (str == e) {found = 0; exit}
      if (length(str) == length(e)) str = substr(str, 3)}
    found == 0 {
      str = str $0
      if (str == b) {found = 1; print str; str = ""}
      if (length(str) == length(b)) str = substr(str, 3)}
    END{ exit found }' |
  xxd -r -p > new_file
test ${PIPESTATUS[1]} -eq 0 || rm new_file

我们的想法是在两个awk之间使用xxd来选择所需文件的一部分。找到第一个模式后,awk将打印字节,直到找到第二个模式并退出。

必须考虑找到第一个图案但不是第二个图案的情况。它在END脚本的awk部分完成,返回非零退出状态。这是由bash的{​​{1}}抓住的,我决定删除新文件。

请注意,空文件也意味着没有找到任何内容。

答案 2 :(得分:2)

这应该适用于标准工具(xxd,tr,grep,awk,dd)。这正确地处理了“跨行的模式分割”问题,也寻找仅在字节偏移(不是半字节)处对齐的模式。

file=<yourfile>
outfile=<youroutputfile>
startpattern="ff d8 ff d0"
endpattern="af ff d9"
xxd -g0 -c1 -ps ${file} | tr '\n' ' ' > ${file}.hex 
start=$((($(grep -bo "${startpattern}" ${file}.hex\
    | head -1 | awk -F: '{print $1}')-1)/3))
len=$((($(grep -bo "${endpattern}" ${file}.hex\
    | head -1 | awk -F: '{print $1}')-1)/3-${start}))
dd ibs=1 count=${len} skip=${start} if=${file} of=${outfile}

注意:上面的脚本使用临时文件来防止二进制&gt;十六进制转换两次。空格/时间权衡是将xxd的结果直接导入两个grep。单线也是可能的,但代价是清晰。

还可以使用tee和命名管道来防止必须存储临时文件并将输出转换两次,但我不确定它会更快(xxd很快)并且写入肯定更复杂

答案 3 :(得分:1)

请参阅this link了解二进制grep的方法。获得开始和结束偏移后,您应该能够dd获得所需内容。

答案 4 :(得分:1)

awk解决方案的变体,假设您的二进制文件一旦用十六进制转换为空格,就会适合内存:

xxd -c1 -p file |
  tr "\n" " " |
  sed -n -e 's/.*\(ff d8 ff d0.*aa ff d9\).*/\1/p' |
  xxd -r -p > new_file

答案 5 :(得分:1)

sed中的另一个解决方案,但使用的内存较少:

xxd -c1 -p file |
  sed -n -e '1{N;N;N}' -e '/ff\nd8\nff\nd0/{:begin;p;s/.*//;n;bbegin}' -e 'N;D' | 
  sed -n -e '1{N;N}' -e '/aa\nff\nd9/{p;Q1}' -e 'P;N;D' |
  xxd -r -p > new_file
test ${PIPESTATUS[2]} -eq 1 || rm new_file

第一个sedff d8 ff d0打印到文件末尾。请注意,N-e '1{N;N;N}'需要sed,因为第一种模式中的字节数少于一个

第二个aa ff d9从文件开头打印到N。请再次注意,-e '1{N;N}'Q需要sed,因为第二种模式中有字节少一个

同样,需要进行测试以检查是否找到第二个模式,如果不是,则删除该文件。

请注意,sed命令是{{1}}的GNU扩展。如果你没有它,你需要在找到模式后丢弃文件的其余部分(在第1 {{1}}之类的循环中,但不打印文件),并在十六进制到二进制转换后检查new_file以wright模式结束。