pom*_*nto 6 python bytecode reverse-engineering
有什么方法可以从使用 获得的反汇编中创建代码对象吗dis.dis?
例如,我使用编译了一些代码co = compile('print("lol")', '<string>', 'exec'),然后使用打印反汇编dis.dis(co),现在我想将反汇编“编译”回代码对象(因为它保存所有相同的数据并且没有丢失任何内容)。
令人惊讶的是,是的——有点。
但是,您需要了解许多注意事项。第一个需要注意的是,Python 字节码以及扩展的汇编指令可以更改每个版本。第二个需要理解的警告是,仅以文本形式发出的信息dis.dis()对于 Python 解释器的需要来说是不完整的。因此,您需要一种方法来填补缺失的信息。
我编写了一个字节码汇编器,它将类似于上面的文本文件程序集转换为 python 字节码。
在您的示例中,您有一个代码对象,而不是创建字节码文件所需的完整信息,但在使用xasm字节码文件中所需的附加信息将其写出之前,当然会创建代码对象。这是在https://github.com/rocky/python-xasm/blob/master/xasm/assemble.pycreate_code()的函数中完成的
为了了解代码对象中的内容以及它如何适合 Python 字节码文件之间的区别,我将使用您的示例,然后完成如何创建字节码文件。
如果我在 Python 3.6.10 中运行你的示例,我会得到:
1 0 LOAD_NAME 0 (print)
2 LOAD_CONST 0 ('lol')
4 CALL_FUNCTION 1
6 POP_TOP
8 LOAD_CONST 1 (None)
10 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
但是,如果我将你的Python代码放入一个文件中,比如说foo.py,使用字节编译它py_compile.compile(source, bytecode, source)并使用xdis的跨版本Python反汇编程序,pydisasm我得到:
# pydisasm version 4.2.4
# Python bytecode 3.6 (3379)
# Disassembled from Python 3.6.10 (default, Jan 23 2020, 16:43:38)
# [GCC 7.4.0]
# Timestamp in code: 1586703495 (2020-04-12 10:58:15)
# Source code size mod 2**32: 13 bytes
# Method Name: <module>
# Filename: foo.py
# Argument count: 0
# Kw-only arguments: 0
# Number of locals: 0
# Stack size: 2
# Flags: 0x00000040 (NOFREE)
# First Line: 1
# Constants:
# 0: 'lol'
# 1: None
# Names:
# 0: print
1: 0 LOAD_NAME 0 (print)
2 LOAD_CONST 0 ('lol')
4 CALL_FUNCTION 1
6 POP_TOP
8 LOAD_CONST 1 (None)
10 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
请注意,在字节码文件中,有一些严格意义上不属于代码对象的附加信息:
现在让我们把它放到一个像foo2.pyasm. 要将其写入字节码文件,只需运行pyc-xasm:
$ pyc-xasm foo2.pyasm
Wrote foo2.pyc
$ python foo2.pyc
lol
Run Code Online (Sandbox Code Playgroud)
我在PyColumbia 2018 的 2018 年照明演讲中演示了所有这一切
xasm我应该指出,在和的下一个版本之前xdis,Python 3.7 及更高版本无法工作,但 3.6 及更早版本可以。