python - 反编译导入的模块(例如使用 uncompyle2)

标签 python reverse-engineering

我的任务是导出从容器加载的导入(编译)模块。

我有一个导入模块的 Py.-Script。使用 print(module1) 后,我可以看到它是一个已编译的 python (pyc) 文件,从存档中加载。由于我无法访问存档,我的想法是导入模块并使用 uncompyle2 对其进行反编译。

这是我的最低代码:

import os, sys
import uncompyle2
import module1
with open("module1.py", "wb") as fileobj:
uncompyle2.uncompyle_file(module1, fileobj)

但是,这会打印出一个错误。如果我将 uncompyle 参数中的 module1 替换为实际路径,则不会有任何区别。当 pyc 文件不是从容器中加载而是目录中的单个文件并且它工作时,我成功地尝试了代码片段。

错误:

Traceback (most recent call last):
File "C:\....\run.py", line 64, in <module>
  uncompyle2.uncompyle_file(module1, fileobj)
File "C:\....\Python\python-2.7.6\lib\site-packages\uncompyle2\__init__.py", line 124, in uncompyle_file
  version, co = _load_module(filename)
File "C:\.....\Python\python-2.7.6\lib\site-packages\uncompyle2\__init__.py", line 67, in _load_module
  fp = open(filename, 'rb')
TypeError: coercing to Unicode: need string or buffer, module found

有谁知道我哪里出错了?

最佳答案

你最初的假设是错误的:

As I cannot access the archive, my idea was to import the module and have it decompiled with uncompyle2.

不幸的是,无法反编译已经加载的模块。加载的 Python 模块不是 .pyc 文件在磁​​盘上表示的镜像。相反,它是 对象 的集合,作为执行 .pyc 中代码的副作用而创建。一旦代码被执行,它的字节码就会被丢弃,并且(在一般情况下)无法重构。

例如,考虑以下 Python 模块:

import gtk
w = gtk.Window(gtk.WINDOW_TOPLEVEL)
w.add(gtk.Label("A quick brown fox jumped over the lazy dog"))
w.show_all()

将此模块导入恰好运行 GTK main loop 的应用程序中将弹出一个带有一些文本的窗口作为副作用。该模块将有一个包含两个条目的字典,gtk 指向 gtk 模块,w 指向一个已经创建的 GTK 窗口。没有提示如何创建另一个 GTK 窗口,也没有提示如何创建另一个这样的模块。 (请记住,创建的对象可能非常复杂,而且它的创建可能是一个非常复杂的过程。)

你可能会问,那么,如果是这样,那么pyc文件的内容是什么?第一次是怎么加载的?答案是 pyc 文件包含模块中字节编译代码的磁盘再现,准备执行。创建一个 pyc 文件大致等同于执行如下操作:

import marshal
def make_pyc(source_code, filename):
    compiled = compile(source_code, filename, "exec")
    serialized = marshal.dumps(compiled)
    with open(filename, "wb") as out:
        out.write(serialized)

# for example:
make_pyc("import gtk\nw = gtk.Window(gtk.WINDOW_TOPLEVEL)...",
         "somefile.pyc", "exec")

另一方面,加载已编译的模块大致等同于:

import sys, marshal, imp
def load_pyc(modname):
    with open(modname + ".pyc", "rb") as in_:
        serialized = in_.read()
    compiled = marshal.loads(serialized)
    module = sys.modules[modname] = imp.new_module(modname)
    exec compiled in module.__dict__

load_pyc("somefile")

请注意,一旦使用 exec 语句执行了代码,字符串和反序列化的字节码就不再使用,将被垃圾收集器清除。已加载 pyc 的唯一剩余影响是存在一个新模块,其中包含事件函数、类和其他无法序列化的对象,例如对打开文件、网络连接、OpenGL 的引用 Canvas 或 GTK 窗口。

uncompyle2 这样的模块所做的是compile 函数的逆操作。您必须拥有模块的实际代码(序列化为 pyc 文件或反序列化代码对象,如片段中的 compiled 变量上面),uncompyle2 将从中产生原始来源的相当忠实的表示。

关于python - 反编译导入的模块(例如使用 uncompyle2),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30291230/

相关文章:

python - Flask中 "Flaskr"教程微博app运行单元测试

python - 在快速排序中弄错递归

sql-server - 在 Visio 中对我的数据库进行逆向工程时无法添加 View

java - 黑客对 jar 文件进行校对

python - 对字符串进行切片并返回拼接后的字符串

python - 使用 Python (pywin32) 或 VBA 更改 Excel 中的 Microsoft Query

python / Selenium : How can I emulate extensions such as uBlock or AdBlock using a headless Chrome driver?

matlab - 了解 RAW 图像文件

c++ - 在 C++ 中 Hook 调用函数?

php - 将标识符嵌入可执行文件以供下载