Grep 二进制文件中匹配之前的字节数?

Grep 二进制文件中匹配之前的字节数?

我经常用来grep -ao ...word file.bin查找文本内容(“单词”)及其前面的几个字符;提醒一句:

   -a, --text
          Process a binary file as if it were text; this is equivalent to the --binary-files=text option.
   -o, --only-matching
          Print  only  the  matched  (non-empty) parts of a matching line, with each such part on a separate
          output line.

正确的;所以刚才,我意识到它的行为是这样的:我尝试首先查找字符串war及其前面的一个字符:

$ grep -ao .war myfile.zip
/war
9war
$war
ʆwar

好的,所以我在这里得到了 4 次点击。现在,如果我想查找字符串war及其前面的两个字符:

$ grep -ao ..war myfile.zip
>$war

那么,现在,由于某种原因,我只得到一个结果?!

我的猜测是,在三个缺失的情况下,“前面两个字符”的值是 0x00(C 字符串的结尾),因此grep不会输出该匹配项 - 否则我仍然期望 4 个结果(除非之前的第一个匹配项位于文件开头,否则我会得到 3 个结果)。

我可以以某种方式说服grep简单地“忽略”匹配中的空字节(或用点或其他东西替换它们)并仍然打印可能包含它们的匹配吗?如果没有grep,还有其他工具可以做到这一点吗?

答案1

您的方法至少存在两个(最好是三个)问题。

即使使用非标准-o,也是grep基于行的,因为它会找到o每行上所有与输出匹配的内容,行是由换行符分隔的字符序列(在基于 ASCII 的系统上值为 10 / 0x0a 的字节)。

所以:

grep -o ..war

只会返回war2 之后的实例人物(不是字节,这是这里的三个问题之一)除了换行符。

例如,在类似 的输入中<0x0a>Xwar,0x0a 字节分隔上一行,下一行Xwar从 之前只有一个字符的位置开始war

在 UTF-8 语言环境中,在类似 的输入上<0xff><0xc3><0xa9>war,两个字节<0xc3><0xa9>形成é字符,但前面的 0xff 字节无效,因此无法形成字符。

grep一般来说,仅适用于文本,因此根据grep实现的不同,使用 NUL 字符或过长的行或不以换行符结尾的输入可能会给工作带来麻烦。

然后,在 中xxwarwargrep -o会找到xxwar,但之后继续搜索更多匹配项,因此不会找到arwar

这些问题可以通过使用以下方法来解决perl

perl -l -0777 -ne 'print "$1$2" while m{(?<=(..))(war)}sg'

我们发现实例war前面有任何 2 个字节(不是用户区域设置中的字符),对这些前面的字节使用后向运算符,以免消耗输入。使用-0777,它将记录分隔符设置为不可能的事情,我们处理整个输入,而不是输入中的每一行。

答案2

另一种方法是将二进制转换为十六进制并匹配:

hexdump -v -e '/1 "%02X" " "' file.bin | grep -o ".. .. $(printf "war" | hexdump -v -e '/1 "%02X" " "')"

对于字符串之前要匹配的..每个字节,您都需要一个。.缺点是它比 grep 或 perl 的直接匹配慢,并且不会像warwarperl 解决方案那样在连续模式中找到后续匹配

结果将打印为十六进制值。如果您想将结果打印为字符串,请像这样将字节转换回来

hexdump -v -e '/1 "%02X" " "' file.bin | \
    grep -o ".. .. $(printf "war" | hexdump -v -e '/1 "%02X" " "')" | \
    xargs -d '\n' -n 1 bash -c '<<<"$1" xxd -r -p -; echo' bash

但请注意\n\r字符串之前的 和许多其他控制字符会弄乱输出

您还可以通过不在每个字节后打印空格来加快搜索速度,但需要注意的是,由于十六进制字符串在字节中间匹配,可能会出现误报。这样你就可以匹配..而不是..每个.

hexdump -v -e '/1 "%02X" ""' file.bin | \
    grep -o "....$(printf "war" | hexdump -v -e '/1 "%02X" ""')" | \
    xargs -d '\n' -n 1 bash -c '<<<"$1" xxd -r -p -; echo' bash

相关内容