分析 Python(混淆)字节码的工具有哪些?

逆向工程 工具 Python
2021-07-04 01:53:23

最近在Reddit ReverseEngineering 上,我偶然发现了Python 中自修改代码查看Github存储库很有启发性,我发现了以 CFG 形式公开的 Python 字节码程序的图片:

在此处输入图片说明

我想知道是否有工具可以对 Python 字节码程序进行静态分析,并具有一些不错的功能(例如生成 CFG 或允许操作代码,...)?

4个回答

Maynard是由 Python 核心成员和 Python 3.4 的发布管理器编写的 Python 字节码的(反)汇编器。阅读材料在这里这里我不知道有一种公共工具(除了你链接的那个)可以像这样进行 CFG 可视化,但你当然可以在 Maynard 之上构建一个。

有几个专门用于 Python 字节码逆向的工具:

  • 取消编译取消编译2

    'uncompyle' 将 Python 字节码转换回等效的 Python 源代码。它只接受 Python 2.7 版的字节码。生成的源代码非常易读:文档字符串、列表、元组和散列得到了漂亮的打印。

    'uncompyle' 还可以通过编译和比较两个字节码来验证生成的源的等效性。“uncompyle”基于 John Aycock 的通用小语言编译器“ spark ”和他之前在“decompyle”方面的工作。

  • pyREtic,这是一个比简单程序更强大的框架

    pyREtic 是一个可扩展的框架,用于协助执行 Python 语言项目的各种逆向工程任务。它帮助逆向工程师从字节码 (.pyc's) 中获取源代码 (.py's),特别是当被逆向的代码已经付出一些努力试图停止使用标准工具集的反编译时,它会提供帮助。

  • pycdc,它比 uncompyle 效果更好,并且比 pyRetic 更易于使用

    Decompyle++ 旨在将编译后的 Python 字节码转换回有效且人类可读的 Python 源代码。虽然其他项目取得了不同程度的成功,但 Decompyle++ 的独特之处在于它寻求支持来自任何 Python 版本的字节码。

    Decompyle++ 包括一个字节码反汇编器 (pycdas) 和一个反编译器 (pycdc)。

  • 专用于 Python3Manyard框架

来自Immunity Sec 的pyREtic还可以在查看原始源代码和执行修改方面提供一些帮助。

您可能有兴趣查看本文档中的工具功能: Rich Smith [PDF] 的pyREtic, In memory reverse engineering for obfuscated Python bytecode

编写提取 python 字节码控制流的工具的一个挑战是有很多 Python 字节码版本可供选择,现在大约有 25 个左右(如果包括 pypy 变体)。

示例图中的字节码JUMP_IF_FALSE后跟一些POP_TOPs 和PRINT_NEWLINE指令,反映了 Python 2.7 之前的版本。

然而,来自 Flare_bytecode_graph 的评论之一中的示例POP_TOP_IF_FALSE是 2.7。Python 3 删除了该PRINT_ITEM指令。

任何编写此类工具的人都必须掌握这一点;或者对生活在单一版本的 Python 感到满意,2.7 可能是最受欢迎的选择。或者,您可以确保您正在运行的 Python 版本与您要分析的字节码相匹配,并使用Python 提供的当前disopcode模块。但即使在这里,这些模块也会随着时间的推移而变化,至少不是特定的字节码指令。

为那些想要跨所有版本的 Python 字节码工作,并且不想使用字节码所需的相同版本的 Python 的人编写了一个名为xdis的 python 包

在这项工作中,您可能想要做的下一件事是将指令分类为可以分支和不能分支以及分支是否有条件的类别。

Python 有一些列表涵盖了其中的一些内容(“hasjrel”、“hasjab”),但遗憾的是它没有最有用的类别。并且由于可能的历史原因,类别是列表而不是集合。但是 xdis 再次在这里进行救援;它用“CONDITION_OPS”、“JUMP_UNCONDITIONAL”和“JUMP_OPS”集填充这些信息。

使用它,我编写了https://github.com/rocky/python-control-flow,它使用 xdis 并有一些基本代码,可以为大多数 Python 字节码创建控制流图和支配树。有一些代码可以创建点文件,我使用 graphviz 来显示它。我注意到 Python 可以创建很多死代码。

该包的预期用途是重建高级 Python 控制结构。有一些基本的控制结构检测,尽管这需要更多的工作。当包含 try/while/for “else” 子句和“finally” 子句时,Python 控制结构非常丰富。即便如此,基本块的带注释的控制流也非常有助于手动重建结构化控制流。

完成后,我可以替换uncompyle6 中许多hacky 代码

这让我看到了接受的答案中提到的反编译器列表......

如前所述,uncompyle 和 uncompyle2 的那些特定版本仅处理 Python 2.7。正如所建议的,有一些旧版本可以处理多个 Python 版本 1.5 到 2.3 或 2.4 左右。也就是说,如果您有一个 Python 2.3 或 2.4 解释器来运行它。

但是这些项目都没有得到积极维护在 uncompyle 中,目前有25 个左右的代码问题,我在 uncompyle6 中修复了许多问题。这是针对不再更改的 Python 版本!(公平地说,虽然 uncompyle6 中存在一些在 uncompyle2 中不存在的错误。为了解决这些问题,我真的需要实施更好的控制流分析)

只需执行 uncompyle6 所做的相同操作,就可以轻松修复 uncompyle 中的许多错误,而且我认为我在问题中已经注意到了其中的一些错误。在这一点上uncompyle2比uncompyle好很多,如果你只对Python 2.7感兴趣,那是最准确的。

至于 pycdc,虽然它相对较小的尺寸(与 uncompyle6 相比)相当不错,但它也没有保持到需要跟上 Python 变化的水平。所以它在 Python 3.4 左右很弱,并且在以后的版本中逐渐变弱。Uncompyle6 也是如此,但目前不太像。pycdc 已经记录了 60 多个问题,我怀疑这些问题会很快得到解决。他们中有些人不认为难以解决。我自己(可能是倾斜的)对这两个反编译器的比较是https://github.com/rocky/python-uncompyle6/wiki/pycdc-compared-with-uncompyle6