我正在尝试编写一个脚本,该脚本将从可执行二进制文件中提取字符串并将它们保存在文件中。让这个文件以换行符分隔不是一种选择,因为字符串本身可能有换行符。然而,这也意味着,使用 unix“字符串”实用程序不是一个选项,因为它只是打印出所有以换行符分隔的字符串,这意味着仅通过查看输出就无法判断哪些字符串包含换行符“字符串”。因此,我希望找到一个 python 函数或库来实现与“字符串”相同的功能,但它会将这些字符串作为变量提供给我,这样我就可以避免换行问题。
谢谢!
我正在尝试编写一个脚本,该脚本将从可执行二进制文件中提取字符串并将它们保存在文件中。让这个文件以换行符分隔不是一种选择,因为字符串本身可能有换行符。然而,这也意味着,使用 unix“字符串”实用程序不是一个选项,因为它只是打印出所有以换行符分隔的字符串,这意味着仅通过查看输出就无法判断哪些字符串包含换行符“字符串”。因此,我希望找到一个 python 函数或库来实现与“字符串”相同的功能,但它会将这些字符串作为变量提供给我,这样我就可以避免换行问题。
谢谢!
这是一个生成器,它产生所有长度为 >= min
(默认为 4)的可打印字符字符串,它在 中找到filename
:
import string
def strings(filename, min=4):
with open(filename, errors="ignore") as f: # Python 3.x
# with open(filename, "rb") as f: # Python 2.x
result = ""
for c in f.read():
if c in string.printable:
result += c
continue
if len(result) >= min:
yield result
result = ""
if len(result) >= min: # catch result at EOF
yield result
您可以对其进行迭代:
for s in strings("something.bin"):
# do something with s
...或存储在列表中:
sl = list(strings("something.bin"))
strings
我已经对此进行了非常简短的测试,它似乎给出了与我选择的任意二进制文件的 Unix 命令相同的输出。然而,它非常幼稚(一开始,它会将整个文件一次读入内存,这对于大文件来说可能很昂贵),并且不太可能接近 Unixstrings
命令的性能。
引用man strings
:
STRINGS(1) GNU 开发工具 STRINGS(1) 姓名 字符串 - 打印文件中可打印的字符串。 [...] 描述 对于给定的每个文件,GNU 字符串打印可打印字符 至少 4 个字符长的序列(或用 下面的选项),后跟一个不可打印的字符。经过 默认,它只打印初始化和加载的字符串 目标文件的部分;对于其他类型的文件,它会打印 来自整个文件的字符串。
您可以通过使用匹配的至少 4 个可打印字符来获得类似的结果。regex
像这样的东西:
>>> import re
>>> content = "hello,\x02World\x88!"
>>> re.findall("[^\x00-\x1F\x7F-\xFF]{4,}", content)
['hello,', 'World']
请注意,此解决方案需要将整个文件内容加载到内存中。
strings 命令允许您使用 更改输出分隔符--output-separator
,因此您可以使用自定义字符串代替换行符(而不是换行符)(您不会期望在二进制文件中找到该字符串),并且包括换行符可以通过以下方式完成--include-all-whitepaces
:
$ strings --include-all-whitespace --output-separator="YOURSEPARATOR" test.bin
您也可以strings
直接调用,例如:
def strings(bytestring: bytes, min: int = 10) -> str:
cmd = "strings -n {}".format(min)
process = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
process.stdin.write(bytestring)
output = process.communicate()[0]
return output.decode("ascii")