递归查找二进制文件中的十六进制字节

问题描述 投票:0回答:3

我在 bash shell 中使用 grep 来查找文件中的一系列十六进制字节:

$ find . -type f -exec grep -ri "\x5B\x27\x21\x3D\xE9" {} \;

搜索工作正常,尽管我知道不使用仅返回结果的

-a
选项时匹配存在限制:

Binary file ./file_with_bytes matches

我想获取匹配结果的偏移量,可以吗?我愿意使用另一个类似的工具,我只是不确定它会是什么。

bash macos grep find
3个回答
5
投票

实际上 grep 中有一个选项可以使用

-b --byte-offset  Print the 0-based byte offset within the input file

使用此选项的简单示例:

$ grep -obarUP "\x01\x02\x03" /bin

打印出目录内匹配模式的文件名和字节偏移量

/bin/bash:772067:
/bin/bash:772099:
/bin/bash:772133:
/bin/bash:772608:
/bin/date:56160:

注意,

find
实际上是不需要的,因为选项
-r
已经处理了递归文件搜索


1
投票

不在电脑前,但使用:

od -x yourFile

xxd yourFile

将其转储为十六进制,并在左侧进行偏移。

有时可能找不到您的搜索字符串,因为字符不是连续出现的而是分成两行。不过,您可以将文件传递两次,第二次截掉前 4 个字节,以确保您的字符串在一次传递或另一次传递中都完好无损。然后重新添加偏移量并对偏移量进行排序和统一。


0
投票

在花费了比我想要的更多的时间尝试让macOS的

grep
(以及其他各种类似的工具,包括GNU
grep
)输出这样的二进制偏移量(和其他答案)之后,我偶然发现了
radare2
rafind2
命令,它正是我所需要的:

rafind2
– 文件中的高级命令行字节模式搜索

我们可以使用 Homebrew 在 macOS 上安装radare2:

brew install radare2

虽然

rafind2
不能用于递归搜索多个文件,但它非常强大,并且非常适合查找单个文件中的偏移量。

我们可以使用

-x
标志来搜索十六进制字符串:

-x [hex]
搜索十六进制字符串(
909090
)(可多次使用)

⇒ rafind2 -x "5B27213DE9" /path/to/the-bin
0xd0fdf

我们甚至可以通过在通过

.
传递的十六进制模式中使用
-x
来使用通配符占位符(完整字节或半字节):

⇒ rafind2 -x "5B..213.E9" /path/to/the-bin
0xd0fdf

我们知道

grep
可以在二进制文件中进行递归(
-r
)匹配:

⇒ grep -r '\x5B\x27\x21\x3D\xE9' ./path/to/bins
Binary file ./path/to/bins/aaa matches
Binary file ./path/to/bins/bbb matches
Binary file ./path/to/bins/ccc matches

通过使用

-rl
,我们可以让
grep
递归搜索,并输出匹配的文件名:

⇒ grep -rl '\x5B\x27\x21\x3D\xE9' ./path/to/bins
./path/to/bins/aaa
./path/to/bins/bbb
./path/to/bins/ccc

然后我们可以与

rafind2
结合来提取所有偏移量:

SEARCH_DIRECTORY="./path/to/bins"
GREP_PATTERN='\x5B\x27\x21\x3D\xE9'

# Remove all instances of '\x' from PATTERN for rafind2
# Eg. Becomes 5B27213DE9
PATTERN="${GREP_PATTERN//\\x/}"

grep -rl "$GREP_PATTERN" "$SEARCH_DIRECTORY" | while read -r file; do
  echo "$file:"
  rafind2 -x "$PATTERN" "$file"
done

这会导致输出如下:

./path/to/bins/aaa:
0x4b0060
./path/to/bins/bbb:
0x4b0060
./path/to/bins/ccc:
0x4bd1e0

我们也可以跳过

grep
,直接将
rafind2
find
/
fd
一起使用:

SEARCH_DIRECTORY="./path/to/bins"
PATTERN='5B27213DE9'

# Using find
find "$SEARCH_DIRECTORY" -type f -exec sh -c 'output=$(rafind2 -x "$1" "$2"); [ -n "$output" ] && echo "$2:" && echo "$output"' sh "$PATTERN" {} \;

# Using fd
fd --type f --exec sh -c 'output=$(rafind2 -x "$1" "$2"); [ -n "$output" ] && (echo "$2:"; echo "$output")' sh "$PATTERN" {} "$SEARCH_DIRECTORY"

两者都会输出如下:

./path/to/bins/aaa:
0x4b0060
./path/to/bins/bbb:
0x4b0060
./path/to/bins/ccc:
0x4bd1e0

要大致了解这些方法的性能,请使用

time
查看每个方法单次运行的以下输出:

⇒ time ./test-grep-and-rafind2
# ..snip..
./test-grep-and-rafind2  7.33s user 0.19s system 99% cpu 7.578 total

⇒ time ./test-find-and-rafind2
# ..snip..
./test-find-and-rafind2  3.24s user 0.72s system 98% cpu 4.041 total

⇒ time ./test-fd-and-rafind2
# ..snip..
./test-fd-and-rafind2  3.85s user 1.04s system 488% cpu 1.002 total
© www.soinside.com 2019 - 2024. All rights reserved.