2015-05-17 23 views
3

我的任務是導出從容器加載的導入(編譯)模塊。反編譯導入的模塊(例如使用uncompyle2)

我有一個導入模塊的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 

有誰知道我要去的地方錯了嗎?

回答

1

你你的初步假設出錯了:

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畫布或GTK窗口的引用。

uncompyle2 do這樣的模塊是compile函數的反函數。您必須具有模塊的實際代碼(或者在pyc文件中進行序列化,或者在上面的代碼片段中對compiled變量進行反序列化的代碼對象),其中uncompyle2將生成對原始源的相當忠實的表示。

+0

感謝您提供詳盡,完整的答案。我學到了很多!不過,我想一定有另一種方式。我只需要找到另一種方式來訪問文件,然後再導入。任何建議,看看哪個方向是高度讚賞。 – lammy

+0

@lammy如何導入文件?存檔位於何處,其內容是什麼? – user4815162342

+0

Hej用戶。該文件使用zipimport模塊導入,然後使用「import ... from」加載。但是,我無法用任何典型的壓縮軟件打開該文件。 Linux和TrID上的File命令只能看到原始數據。我不知道如何繼續。謝謝你的幫助! – lammy

0

傳遞文件名第一,然後將該文件對象寫入:

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' 
+0

我想你使用XPath =模塊1 .__ FILE__ 開放的建議( 「out.txt」, 「W」)爲f: uncompyle2.uncompyle_file(XPath中,F)但奇怪的運行時,我得到IO錯誤: [Errno 2]沒有這樣的文件或目錄:'C:\\ ..... \\ modul1.enc \\ modul1 \\ modul1.pyc' – lammy

+0

@lammy,你傳遞一個'.pyc'文件是嗎? –

+0

@ Padauc坎寧安。當我使用打印模塊.__文件___時,它顯示了上述pyc文件的路徑。 – lammy

相關問題