Decompile the imported module (for example with uncompyle2)

My task is to export the imported (compiled) module loaded from the container.

I have a Py.- Script importing module. After using print (module1), I see that it is a compiled python (pyc) file downloaded from the archive. Since I cannot access the archive, my idea was to import the module and decompile it using uncompyle2.

This is my minimal code:

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

      

However, this prints my error. If I replace module1 in the uncompyle argument with the actual path, it doesn't matter. I have successfully tried a piece of code where the pyc file was not loaded from the container but was one file in a directory and it worked.

Mistake:

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

      

Does anyone know where I am going wrong?

+3


source to share


2 answers


You will be wrong in your original guess:

Since I cannot access the archive, my idea was to import the module and decompile it using uncompyle2.

Unfortunately, it is not possible to compile an already loaded module. The loaded Python module is not a disk mirror of the file .pyc

on disk. Instead, it is a collection of objects created as a side effect of code execution in the .pyc

. After the code is executed, its byte code is discarded, and it (in the general case) cannot be recovered.

Consider the following Python module as an example:

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

      

Importing this module inside an application that starts the main GTK loop will bring up a window with some text as a side effect. The module will have a dict with two entries gtk

pointing to the module gtk

and w

pointing to the already created GTK window. There is no hint on how to create another GTK window of the sort, nor how to create another such module. (Remember that the created object could be arbitrarily complex and that creating it can be a very complex process.)



If so, you may ask, what is the content of the file pyc

? How did it boot up the first time? The answer is that the file pyc

contains in a module a ready-to-execute compilation with a byte in a module on disk. File creation is pyc

roughly equivalent to:

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")

      

On the other hand, loading a compiled module is roughly equivalent to:

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")

      

Note that after the code has been executed with the instruction exec

, the string and deserialized bytecode are no longer used and will be seen by the garbage collector. The only remaining loading effect pyc

is the presence of a new module with live functions, classes, and other objects that cannot be serialized, such as links to open files, network connections, OpenGL canvases or GTK windows.

Which modules like uncompyle2

do are function inverse compile

. You should have the actual module code (either serialized as in a file pyc

, or a deserialized code object as in the variable compiled

in the snippets above) that uncompyle2

will yield a fairly accurate representation of the original source.

+1


source


first pass the file name string and then file the file to write:

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

      

You can see the result:



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())

      

Output:

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

#Embedded file name: test.py


def foo():
    print 'hello world'

      

0


source







All Articles