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

时间:2015-05-17 19:29:58

标签: 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

有谁知道我哪里出错了?

2 个答案:

答案 0 :(得分:1)

你最初的假设出了问题:

  

由于我无法访问存档,我的想法是导入模块和   用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的应用程序中导入此模块将弹出一个窗口,其中包含一些文本作为副作用。该模块将有一个带有两个条目的dict,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画布的引用,或者GTK窗口。

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

答案 1 :(得分:0)

首先传递文件名 string ,然后传递文件对象以写入:

with open("out.txt","w") as f:
    uncompyle2.uncompyle_file('path_to.pyc',f)

您可以看到输出:

with open("/home/padraic/test.pyc","rb") as f:
    print(f.read())
with open("out.txt","r+") as f:
    uncompyle2.uncompyle_file('/home/padraic/test.pyc',f)
    f.seek(0)
    print(f.read())

输出:

�
d�ZdS(cCs   dGHdS(Nshello world((((stest.pytfoosN(R(((stest.pyt<module>s

#Embedded file name: test.py


def foo():
    print 'hello world'
相关问题