我有二进制,并希望提取它的一部分,从已知的字节字符串(即FF D8 FF D 0)并以已知字节串(AF FF D9)结束在过去,我使用dd从开始/结束处剪切二进制文件的一部分,但这个命令似乎不支持我的要求。终端上的什么工具可以做到这一点?
dd
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
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]}捕获的,在那里我决定删除新文件。注意,空文件也意味着没有找到任何东西。
xxd
awk
END
bash
${PIPESTATUS[1]}
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}
grep
也可以使用tee和命名管道来避免存储临时文件和两次转换输出,但我不确定它会更快(xxd很快),而且编写起来肯定更复杂。
tee
q3aa05254#
请参阅this link了解执行二进制grep的方法。一旦有了开始和结束偏移量,就可以使用dd来获得所需的内容。
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
8gsdolmq6#
sed中的另一种解决方案,但使用较少的内存:
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
第一个sed从ff 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模式结束。
ff d8 ff d0
-e '1{N;N;N}'
N
aa ff d9
-e '1{N;N}'
Q
bfnvny8b7#
您可以使用binwalk来执行此操作。该工具将自动检测输入二进制文件中的文件(偏移量)。通过使用-e标志,它将提取您正在运行命令的同一目录中的所有文件。它默认安装在最新的发行版中,但您可以使用sudo apt install binwalk轻松安装CLI工具。下面是一个执行示例,其中我隐藏了一个zip文件,其内容是一个名为pass.txt的文本文件。整个过程都隐藏在.jgp图像中。
binwalk
-e
sudo apt install binwalk
阅读手册以了解更多信息。
7条答案
按热度按时间e4eetjau1#
定位开始/结束位置,然后提取范围。
ct2axkht2#
在单个管道中:
其思想是在两个
xxd
之间使用awk
来选择所需的文件部分。找到第一个模式后,awk
打印字节,直到找到第二个模式并退出。必须考虑找到第一个图案但没有找到第二个图案的情况。这是在
awk
脚本的END
部分完成的,它返回一个非零的退出状态。这是由bash
的${PIPESTATUS[1]}
捕获的,在那里我决定删除新文件。注意,空文件也意味着没有找到任何东西。
xu3bshqb3#
这应该可以使用标准工具(xxd、tr、grep、awk、dd)。这正确地处理了“跨行分割模式”的问题,也可以查找仅在字节偏移(而不是半字节)处对齐的模式。
xxd
的结果直接通过管道传输到两个grep
。以清晰度为代价,一行也是可能的。也可以使用
tee
和命名管道来避免存储临时文件和两次转换输出,但我不确定它会更快(xxd很快),而且编写起来肯定更复杂。q3aa05254#
请参阅this link了解执行二进制grep的方法。一旦有了开始和结束偏移量,就可以使用
dd
来获得所需的内容。xcitsw885#
awk
解决方案的一个变体,它假设您的二进制文件一旦转换为十六进制并带有空格,就适合内存:8gsdolmq6#
sed
中的另一种解决方案,但使用较少的内存:第一个
sed
从ff d8 ff d0
开始打印,直到文件结束。请注意,-e '1{N;N;N}'
中的N
需要与第一个模式中的字节数一样多减去1。第二个
sed
从文件的开头打印到aa ff d9
。再次注意,-e '1{N;N}'
中的N
需要与第二个模式中的字节数一样多减去1。同样,需要测试以检查是否找到第二个模式,如果没有,则删除文件。
请注意,
Q
命令是sed
的GNU扩展。如果你没有它,你需要在找到模式后丢弃文件的其余部分(在类似1stsed
的循环中,但不打印文件),并在十六进制到二进制转换后检查new_file是否以wright模式结束。bfnvny8b7#
您可以使用
binwalk
来执行此操作。该工具将自动检测输入二进制文件中的文件(偏移量)。通过使用
-e
标志,它将提取您正在运行命令的同一目录中的所有文件。它默认安装在最新的发行版中,但您可以使用
sudo apt install binwalk
轻松安装CLI工具。下面是一个执行示例,其中我隐藏了一个zip文件,其内容是一个名为pass.txt的文本文件。整个过程都隐藏在.jgp图像中。
阅读手册以了解更多信息。