16

我正在尝试编写一个脚本,该脚本将从可执行二进制文件中提取字符串并将它们保存在文件中。让这个文件以换行符分隔不是一种选择,因为字符串本身可能有换行符。然而,这也意味着,使用 unix“字符串”实用程序不是一个选项,因为它只是打印出所有以换行符分隔的字符串,这意味着仅通过查看输出就无法判断哪些字符串包含换行符“字符串”。因此,我希望找到一个 python 函数或库来实现与“字符串”相同的功能,但它会将这些字符串作为变量提供给我,这样我就可以避免换行问题。

谢谢!

4

4 回答 4

24

这是一个生成器,它产生所有长度为 >= 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命令的性能。

于 2013-06-19T16:55:46.857 回答
6

引用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']

请注意,此解决方案需要将整个文件内容加载到内存中。

于 2013-06-19T16:28:31.893 回答
0

strings 命令允许您使用 更改输出分隔符--output-separator,因此您可以使用自定义字符串代替换行符(而不是换行符)(您不会期望在二进制文件中找到该字符串),并且包括换行符可以通过以下方式完成--include-all-whitepaces

$ strings --include-all-whitespace --output-separator="YOURSEPARATOR" test.bin

于 2021-12-18T20:50:25.037 回答
-1

您也可以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")
于 2021-12-12T15:08:57.143 回答