如何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 的 hexdump
的 hexdump 输出]工具。
一次拍摄使用 sed:
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)
使用bash + grep:
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
$
我有一个 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 的 hexdump
的 hexdump 输出]工具。
一次拍摄使用 sed:
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)
使用bash + grep:
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 搜索原始二进制文件,而不是十六进制转储。在您的模式中扩展 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
$