【Python】pyinstallerで作成されたexeをpyファイルに戻したい

本ページはプロモーションが含まれています

pyinstallerで作成されたexeをpyファイルに戻す方法を調べると複数のパターンがあって、なかなかうまくいく方法に出会うことができませんでしたが、唯一なんとかなった方法を書き残します

ただ完全に復元できるわけではなく、かなり欠損もあり過度な期待はせず参考ソースが抽出できるぐらいでお願いします!!

exeからpycファイルを抽出する

pyinstxtractorを利用するのでGithubからインストール

https://github.com/extremecoders-re/pyinstxtractor

引数にpyファイルに戻したいexeファイルを指定してpyinstxtractor.pyを実行して・・・
なんですが、下部にあるリンク(pyinstxtractor-ng or pyinstxtractor-web)ならもっと簡単に利用できるので一旦省略

  • pyinstxtractor-ng: A standalone binary version of pyinstxtractor. This tool doesn’t require Python to run and can extract all supported versions of PyInstaller. It also supports encrypted pyinstaller executables.
  • pyinstxtractor-web: pyinstxtractor running in the web browser, powered by Go & GopherJS.
https://github.com/extremecoders-re/pyinstxtractor

pyinstxtractor-ng の場合

リンク先のGithubに目当てのファイルが・・無い!!

もう一つ先のリンクにあるので↓の通りreleasesへ遷移

最新版のところから「pyinstxtractor-ng.exe」をダウンロードしてくる

pyinstxtractor-ng.exeの使い方

使い方はとても簡単。exeファイルを「pyinstxtractor-ng.exe」へドラッグ&ドロップするだけ!

{exeファイル名}_extractedのフォルダが作成されて、その中にフォルダ&ファイルが多数ありますが、拡張子が.pycになっているexeファイルと同じ名前のファイルがあるのでこれを次工程へ

pyinstxtractor-web の場合

リンク名が”pyinstxtractor-web”なのWEBページへのリンクかと思いきや行き着く先はGo言語で構成するpyinstxtractorのGithubページへ ※私Goは全くわかりません・・

なんですが、大事なのは少し下にある今度こそWEBページのリンク

行き着く先はpyinstxtractor-ng.exeと同じことができるWEBページ

やることは簡単

“ファイルを選択”から対象のexeファイルを選択して”Process”をクリックするだけ

中央の枠にログが表示されて最終的に{exeファイル名}_extracted.zipがダウンロードされるので解凍すればあとは同じ

.pycファイルを.pyファルにする

次はpycdcを使うので再びGithubへ

GitHub - extremecoders-re/decompyle-builds: Precompiled Decompyle++ (pycdc) binaries for Windows & Linux
Precompiled Decompyle++ (pycdc) binaries for Windows & Linux - GitHub - extremecoders-re/decompyle-builds: Precompiled D...

pycdcように見えてじゃないけどここが正解

pyinstxtractor-ngの時と同じくreleasesのリンクへ

pycdc.exe」をダウンロードしてくる

pycdcの使い方

pyinstxtractor-ng.exeと違ってドラック&ドロップではできない

コマンドプロンプトとかで対象のpycファイルを引数にしてログ出力として実行する

cd {ファイルがあるフォルダ}
pycdc.exe {pycファイル}>{出力するpyファイル}
※2行目の各ファイルをフォルダ込みのフルパスで書くなら1行目の"cd {ファイルがあるフォルダ}"は不要

この出力したpyファイルがexeから戻した目的ファイル!

もとのpyファイルとどれくらい違うのか

細かいところは他にもあるけど影響大きそうなものはこんな感じ

“#WARNING: Decompyle incomplete”以下の欠損

これが一番ダメージデカい・・

この文字があると同一def内の以降のソースが消し飛ぶ

diffを取るとこんな感じ

コメントがなくなる

なくなるコメントは#で始まる一行コメントのみ

「”’」か「”””」で囲んだ複数行コメントは残ってる

引数が「**kwargs」になりがち

(これは動きそうなので見逃せそう)

# ↓これが
f = csv.DictReader(csv_file, delimiter=',', doublequote=True,
                               lineterminator='\r\n', quotechar='"', skipinitialspace=True)
# ↓こうなる
f = csv.DictReader(csv_file, ',', True, '\r\n', '"', True, **('delimiter', 'doublequote', 'lineterminator', 'quotechar', 'skipinitialspace'))

引数の解釈がおかしい時がある

そもそも型指定しなければ良いのかな・・?

# ↓これが
def findItemsAdvancedAPI(self, SellerId: str, page_no: int, ItemIdList: list):
# ↓こうなる
def findItemsAdvancedAPI(self = None, SellerId = None, page_no = None, ItemIdList = ('SellerId', str, 'page_no', int, 'ItemIdList', list)):

ネストされたifなどが(間違って?)まとめられる

元のソースが微妙な気もするけど・・

# ↓これが
if res['findItemsAdvancedResponse']['searchResult']['@count'] == '1':
    item = items
    if item['globalId'] == 'EBAY-US':
        if str(item['itemId']) not in ItemIdList:
            if self.GetItemDetail(str(item)) == 2:
                return 2
else:
    for item in items:
        if item['globalId'] == 'EBAY-US':
            if str(item['itemId']) not in ItemIdList:
                if self.GetItemDetail(str(item['itemId'])) == 2:
                    return 2
return 1 if totalPages > page_no else 0
# ↓こうなる
if res['findItemsAdvancedResponse']['searchResult']['@count'] == '1':
    item = items
    if item['globalId'] == 'EBAY-US' and str(item['itemId']) not in ItemIdList and self.GetItemDetail(str(item)) == 2:
        return 2
for item in items:
    if item['globalId'] == 'EBAY-US' and str(item['itemId']) not in ItemIdList and self.GetItemDetail(str(item['itemId'])) == 2:
        return 2
    if totalPages > page_no:
        return 1
    return None

あとがき

何もないよりは絶対に良いけどこれで復元と言うには少し微妙・・・

人様が作ったexeをデコンパイルして改修することは難しいってことですね

コメント

タイトルとURLをコピーしました