繁体   English   中英

如何转储部分二进制文件

[英]How to dump part of binary file

我有二进制文件,想要提取部分内容,从知道字节字符串(即FF D8 FF D0)开始,以已知字节字符串结尾(AF FF D9)

在过去,我使用dd从开始/结束切割部分二进制文件,但这个命令似乎不支持我的要求。

终端上的什么工具可以做到这一点?

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

$ 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

在一个管道中:

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

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

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

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

这应该适用于标准工具(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}

注意:上面的脚本使用临时文件来防止二进制>十六进制转换两次。 空格/时间权衡是将xxd的结果直接传递给两个grep 单透明也是可能的,但是以清晰度为代价。

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

有关二进制grep的方法,请参阅此链接 一旦你有开始和结束偏移量,你应该能够用dd来获得你需要的东西。

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

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 in -e '1{N;N;N}'因为第一个模式中的字节数少于1

第二个sed从文件的开头打印到aa ff d9 再次注意,你需要尽可能多的N in -e '1{N;N}'因为你的第二个模式中的字节少了一个

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

请注意, Q命令是sed的GNU扩展。 如果你没有它,你需要在找到模式后丢弃文件的其余部分(在第一个sed类的循环中,但不打印文件),并在hex到二进制转换后检查new_file以怀特模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM