Files
pynosaur/README.md
2025-06-20 18:39:30 +08:00

4.1 KiB
Raw Blame History

Pynosaur

简体中文 | English

👉 跳转到安装与用法小节

功能特性

高版本 CPython 字节码

是命令行程序,也是 Python 库

推测 Python 版本

如果传入 Marshal 产生的代码对象Code Object字节串Pynosaur 可以尽可能根据字节码指令推测出其对应的 Python 版本。这一特性对于 pyc 头丢失、只有反汇编文本等情况非常有用。

人为构造的代码对象

对于每个新的 Python 版本Pynosaur 首先尽可能实现对 CPython 编译器生成的字节码序列的支持。在此基础上,我们尝试在遇到 CPython 编译器通常情况下不会产生的字节码序列时,产生尽可能有用的结果。这样,就不会因为恶意构造的字节码而导致 Pynosaur 反编译失败。以下是一个仅用于描述的恶意构造的例子(其中的注释不是 Pynosaur 生成的,只是对例子的说明):

    LOAD_CONST               1 (1)
    LOAD_CONST               2 (2)
    COMPARE_OP             148 (bool(>))
    POP_JUMP_IF_FALSE       10 (to L1)         # 下一条指令代表 1 大于 2 的分支
    LOAD_GLOBAL           5678 (??? + NULL)    # globals 的第五千多项?越界!
    CALL                  1234                 # 从栈上弹出一千多个参数?
    POP_TOP

一种可能的反编译输出是 pass 并在后面的注释中提供无法处理的字节码指令。

文本格式

除 pyc 文件等二进制格式外Pynosaur 也接受以下输入形式或其片段:

  • 标准库 dis.dis 输出的反汇编字节码文本
  • 标准库 ast.dump 输出的抽象语法树文本
  • 标准库 tokenize 输出的词法单元文本
  • pycdas 输出的反汇编字节码文本
  • xdis 输出的反汇编字节码文本

版本转换

Pynosaur 还支持不同版本之间的字节码转换。例如,通过适当的命令行参数或脚本,可以用 Python 3.12 运行 Pynosaur 本身,传入文本格式的 Python 3.13 的字节码,输出可用于的 Python 3.11 的 pyc 文件。

与运行 Pynosaur 的 CPython 标准库或原生类型互操作

可转换的形式小结

衍生产品

  • Pynosaur UI: 一个可视化的字节码反编译、原地编辑、跨版本回编译工具。由 Pynosaur 开发者维护。
  • Pynosaur Duck: 只需一条命令,解包并递归反编译 PyInstaller 和 Py2exe 打包的可执行文件。由 Pynosaur 开发者维护。灵感来源于 Pydumpck

设计

没有历史包袱

不同于其他支持早期版本(甚至 2.x, 1.x的反编译器Pynosaur 从一开始就被设计为只支持最近几个 CPython 版本,目前支持 CPython 3.9 至 3.14 的字节码。

这样的好处在于可以专注于现代 Python 语言的特性和优化,而不必考虑向后兼容性的问题。例如,从 Python 3.6 开始CPython 字节码指令是定长的。由于不需要考虑旧版本的字节码Pynosaur 可以安全地假定字节码指令的长度是固定的,这使得反编译器的实现更简单、更高效。

新的 Python 版本发布时,针对不再受支持版本的反编译逻辑可能会被 Pynosaur 移除。如果发生这种情况Pynosaur 会发布新的主要版本。旧的主要版本仍然可用,但不再维护。这使得 Pynosaur 代码库可以保持简洁、灵活,在实现新的字节码时不需考虑过多兼容问题。

如果你需要处理 3.8 及更低版本的字节码,可以选择其他工具,见下文对比章节。

工作原理

与 Pycdc (Decompile++), Uncompyle6, PyLingual 的对比

安装

Pynosaur 本身是用纯 Python 编写的,运行在 Python 3.10 或更高版本上。使用 pip 安装:

pip install pynosaur

Pynosaur 本身不能在 Python 3.9 或更低版本上运行,因为它使用了 Python 3.10 引入的 match 语句、类型联合运算符如 int | list[int] | None 等。它目前可以反编译 Python 3.9 至 3.14 的字节码。

使用方法

运行测试

开发与贡献

许可证、致谢、贡献者、星标图