linux 如何转储部分二进制文件

sg2wtvxw  于 2023-05-28  发布在  Linux
关注(0)|答案(7)|浏览(380)

我有二进制,并希望提取它的一部分,从已知的字节字符串(即FF D8 FF D 0)并以已知字节串(AF FF D9)结束
在过去,我使用dd从开始/结束处剪切二进制文件的一部分,但这个命令似乎不支持我的要求。
终端上的什么工具可以做到这一点?

e4eetjau

e4eetjau1#

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

$ 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
ct2axkht

ct2axkht2#

在单个管道中:

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]}捕获的,在那里我决定删除新文件。
注意,空文件也意味着没有找到任何东西。

xu3bshqb

xu3bshqb3#

这应该可以使用标准工具(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很快),而且编写起来肯定更复杂。

q3aa0525

q3aa05254#

请参阅this link了解执行二进制grep的方法。一旦有了开始和结束偏移量,就可以使用dd来获得所需的内容。

xcitsw88

xcitsw885#

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
8gsdolmq

8gsdolmq6#

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开始打印,直到文件结束。请注意,-e '1{N;N;N}'中的N需要与第一个模式中的字节数一样多减去1
第二个sed从文件的开头打印到aa ff d9。再次注意,-e '1{N;N}'中的N需要与第二个模式中的字节数一样多减去1
同样,需要测试以检查是否找到第二个模式,如果没有,则删除文件。
请注意,Q命令是sed的GNU扩展。如果你没有它,你需要在找到模式后丢弃文件的其余部分(在类似1st sed的循环中,但不打印文件),并在十六进制到二进制转换后检查new_file是否以wright模式结束。

bfnvny8b

bfnvny8b7#

您可以使用binwalk来执行此操作。该工具将自动检测输入二进制文件中的文件(偏移量)。
通过使用-e标志,它将提取您正在运行命令的同一目录中的所有文件。
它默认安装在最新的发行版中,但您可以使用sudo apt install binwalk轻松安装CLI工具。
下面是一个执行示例,其中我隐藏了一个zip文件,其内容是一个名为pass.txt的文本文件。整个过程都隐藏在.jgp图像中。

阅读手册以了解更多信息。

相关问题