【问题标题】:Python equivalent of unix "strings" utilityPython 等效于 unix“字符串”实用程序
【发布时间】:2013-06-16 06:20:20
【问题描述】:

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

谢谢!

【问题讨论】:

  • @FredrikPihl,这是关于二进制和文本表示之间的转换。这是关于从二进制可执行文件中提取字符串。令人困惑的重用术语,但不同的问题。不过,感谢您的捕获;很高兴知道这是否是一个重复。
  • 你说得对,这是我今天误解的第三个问题;需要睡觉:-)

标签: python string executable


【解决方案1】:

这是一个生成器,它生成所有可打印字符的字符串 >= 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"))

我对此进行了非常简短的测试,它似乎给出了与我选择的任意二进制文件的 Unix strings 命令相同的输出。但是,它非常幼稚(一开始,它会将整个文件一次读入内存,这对于大文件来说可能代价高昂),并且不太可能达到 Unix strings 命令的性能。

【讨论】:

  • 这很好。额外的挑战:你能弄清楚如何只读取目标文件的初始化和加载部分吗? ;)
  • @joshlf13 哪种格式的目标文件?精灵? XCOFF? Windows 便携式可执行文件?根据格式,您可以找到专门的 Python 库来提取各个部分。如果您对该主题感兴趣,请发布其他问题。
  • @joshlf13 不是没有增加我对目标文件结构的了解,从“根本没有”到“根本没有”,不;-) 除非它们比我想象的要简单得多, 在任何情况下,这都会使代码变得更加复杂(在某种程度上,你最好寻找一个库来解析它们)。
  • @SylvainLeroux,我主要是在开玩笑。但实际上,是的,这些都是合理的担忧。
  • @ZeroPiraeus,正如你所知,我最终下载了字符串源并将其修改为用空字符而不是换行符分隔。考虑到所有因素,这非常容易。
【解决方案2】:

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

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

【讨论】:

  • 您也可以使用 [ -~]{4,} 获得相同的结果
【解决方案3】:

strings 命令允许您使用--output-separator 更改输出分隔符,因此您可以使用自定义字符串代替新行字符(您不希望在二进制文件中找到该字符串),包括换行符可以用--include-all-whitepaces:

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

【讨论】:

    【解决方案4】:

    您也可以直接拨打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")
    

    【讨论】:

    • 这实际上并不能解决换行问题。
    猜你喜欢
    • 2010-12-30
    • 1970-01-01
    • 2015-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-07
    • 2022-08-17
    • 1970-01-01
    相关资源
    最近更新 更多