如何grep十六进制数据区域

how to grep a hex data area

我有一个 hex 文件,我需要将它的一部分提取到一个文本文件中

起始范围:

目标范围:

我需要输出: AC:E4:B5:9A:53:1C

我尝试了很多但并不是真正正确的要求,输出:Binary file filehex matches

grep "["'\x9f\x87\x6f\x11'"-"'\x9f\x87\x70\x11'"]" filehex > test.txt

希望有人能帮助我

使用-a强制输入的文本解释。

使用-o只输出匹配的部分

您使用的表达方式没有多大意义。它匹配集合 \x9、\x87、\x6f 中的任何字符,然后是范围 \x11-\x9f,等等

您对以 \x9\x87\x6f\x11 开头并以 \x9f\x87\x70\x11 结尾的内容比较感兴趣,可以是介于两者之间的任何内容。

您可以使用 cut 删除前导和尾随 4 个字节。

grep -oa $'\x9f\x87\x6f\x11.*\x9f\x87\x70\x11' hexfile | cut -b5-21

如果您知道字符串的长度始终为 17 个字节,则可以使用 .\{17\} 而不是 .*

好的,我已经随机构建了一个二进制文件 $file 用你的 string 在一个位置使 hd 命令分割它们。

注: 关于 k314159' comment, 我使用 hd 生成类似于 CentOS 的 hexdumphexdump 输出]工具。

一次拍摄使用 :

hd $file |sed -e 'N;/ 9f \+\(|.*\n[0-9a-f]\+ \+\|\)87 \+\(|.*\n[0-9a-f]\+ \+\|\)6f \+\(|.*\n[0-9a-f]\+ \+\|\)11 /p;D;'
000161c0  96 7a b2 21 28 f1 b3 32  63 43 93 ff 50 a6 9f 87  |.z.!(..2cC..P...|
000161d0  6f 11 0d 7a a5 a9 81 9e  32 9d fb 71 27 6d 60 f2  |o..z....2..q'm`.|
0002c3a0

解释:

  • N当前缓冲区合并下一行

  • \(|.*\n[0-9a-f]\+ \+\|\) 匹配 | 后跟任何内容和 newline (\n),然后是十六进制数字和 space 或什么都没有。

  • p 打印当前缓冲区(两行)

  • D 当前缓冲区 中删除最多 newline,为下一个 sed 循环保留最后一行。 最后的十六进制00028d2a对应我二进制的大小$file:

    printf "%x\n" $(stat -c %s $file)
    

使用 + :

printf -v var "\x9f\x87\x6f\x11" 
IFS=: read -r offset _ < <(grep -abo "$var" $file)
hd $file | sed -ne "$((offset/16-1)),+4p"
000161a0  b7 8f 4a 4d ed 89 6c 0b  25 f9 e7 c9 8c 99 6e 23  |..JM..l.%.....n#|
000161b0  3c ba 80 ec 2e 32 dd f3  a4 a2 09 bd 74 bf 66 11  |<....2......t.f.|
000161c0  96 7a b2 21 28 f1 b3 32  63 43 93 ff 50 a6 9f 87  |.z.!(..2cC..P...|
000161d0  6f 11 0d 7a a5 a9 81 9e  32 9d fb 71 27 6d 60 f2  |o..z....2..q'm`.|
000161e0  15 86 c2 bd 11 d0 08 90  c4 84 b9 80 04 4e 17 f1  |.............N..|

在哪里可以读取字符串:

000161c0                                             9f 87  |              ..|
000161d0  6f 11                                             |o.              |

为了测试,我通过以下方式构建了测试文件:

dd if=/vmlinuz bs=90574 count=1 of=/tmp/testfile
printf '\x9f\x87\x6f\x11' >>/tmp/testfile 
dd if=/vmlinuz bs=90574 count=1 >>/tmp/testfile
file=/tmp/testfile

使用 grep 搜索原始二进制文件,而不是十六进制转储。在您的模式中扩展 , I think you may have problems with grep trying to interpret your search pattern as UTF-8 or some other encoding. You should temporarily set the environment variable LC_ALL=C for grep to treat each byte individually. Also, you can use the -P option to enable use of lookbehind and lookahead。所以你的命令变成:

LANG=C grep -oaP $'(?<=\x9f\x87\x6f\x11).*(?=\x9f\x87\x70\x11)' binary-file > test.txt

它有效的证明:

$ echo $'BEFORE\x9f\x87\x6f\x11AC:E4:B5:9A:53:1C\x9f\x87\x70\x11AFTER' | LANG=C grep -oaP $'(?<=\x9f\x87\x6f\x11).*(?=\x9f\x87\x70\x11)'
AC:E4:B5:9A:53:1C
$