コンパイルされたPythonバイナリ(exe、elf)を逆コンパイルする - .pycから取得
Reading time: 11 minutes
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
コンパイルされたバイナリから.pycへ
ELFコンパイルバイナリから**.pycを取得**することができます:
pyi-archive_viewer <binary>
# The list of python modules will be given here:
[(0, 230, 311, 1, 'm', 'struct'),
(230, 1061, 1792, 1, 'm', 'pyimod01_os_path'),
(1291, 4071, 8907, 1, 'm', 'pyimod02_archive'),
(5362, 5609, 13152, 1, 'm', 'pyimod03_importers'),
(10971, 1473, 3468, 1, 'm', 'pyimod04_ctypes'),
(12444, 816, 1372, 1, 's', 'pyiboot01_bootstrap'),
(13260, 696, 1053, 1, 's', 'pyi_rth_pkgutil'),
(13956, 1134, 2075, 1, 's', 'pyi_rth_multiprocessing'),
(15090, 445, 672, 1, 's', 'pyi_rth_inspect'),
(15535, 2514, 4421, 1, 's', 'binary_name'),
...
? X binary_name
to filename? /tmp/binary.pyc
python exe バイナリ でコンパイルされた場合、次のコマンドを実行することで .pyc を取得できます:
python pyinstxtractor.py executable.exe
.pycからPythonコードへ
.pycデータ("コンパイル済み" Python)については、元の Python コードを抽出しようとすることから始めるべきです:
uncompyle6 binary.pyc > decompiled.py
必ずバイナリが拡張子".pyc"を持っていることを確認してください(そうでない場合、uncompyle6は機能しません)
uncompyle6を実行していると、以下のエラーが発生することがあります:
エラー: 不明なマジックナンバー 227
/kali/.local/bin/uncompyle6 /tmp/binary.pyc
Unknown magic number 227 in /tmp/binary.pyc
これを修正するには、生成されたファイルの先頭に正しいマジックナンバーを追加する必要があります。
マジックナンバーはPythonのバージョンによって異なります。Python 3.8のマジックナンバーを取得するには、Python 3.8のターミナルを開いて実行する必要があります:
>> import imp
>> imp.get_magic().hex()
'550d0d0a'
この場合のpython3.8のマジックナンバーは**0x550d0d0a
です。次に、このエラーを修正するには、.pycファイルの先頭に次のバイトを追加**する必要があります: 0x0d550a0d000000000000000000000000
その後、そのマジックヘッダーを追加すると、エラーは修正されるはずです。
正しく追加された**.pyc python3.8マジックヘッダー**は次のようになります:
hexdump 'binary.pyc' | head
0000000 0d55 0a0d 0000 0000 0000 0000 0000 0000
0000010 00e3 0000 0000 0000 0000 0000 0000 0000
0000020 0700 0000 4000 0000 7300 0132 0000 0064
0000030 0164 006c 005a 0064 0164 016c 015a 0064
エラー: ジェネリックエラーのデコンパイル
他のエラーとして: class 'AssertionError'>; co_code should be one of the types (<class 'str'>, <class 'bytes'>, <class 'list'>, <class 'tuple'>); is type <class 'NoneType'>
が表示されることがあります。
これはおそらく、マジックナンバーを正しく追加していないか、正しいマジックナンバーを使用していないことを意味しますので、正しいものを使用していることを確認してください(または新しいものを試してください)。
前のエラーのドキュメントを確認してください。
自動ツール
python-exe-unpackerツールは、Pythonで書かれた実行可能ファイルのアンパックとデコンパイルを支援するために設計された、いくつかのコミュニティで利用可能なツールの組み合わせとして機能します。特に、py2exeおよびpyinstallerで作成されたものに対応しています。Pythonベースの実行可能ファイルを特定し、作成ツールを確認するためのYARAルールが含まれています。
ImportError: ファイル名: 'unpacked/malware_3.exe/pycache/archive.cpython-35.pyc' が存在しません
一般的な問題は、unpy2exeまたはpyinstxtractorを使用したアンパックプロセスの結果として不完全なPythonバイトコードファイルが発生し、その後Pythonバイトコードバージョン番号が欠落しているためにuncompyle6によって認識されないことです。これに対処するために、必要なPythonバイトコードバージョン番号を追加するprependオプションが追加され、デコンパイルプロセスを容易にします。
問題の例:
# Error when attempting to decompile without the prepend option
test@test: uncompyle6 unpacked/malware_3.exe/archive.py
Traceback (most recent call last):
...
ImportError: File name: 'unpacked/malware_3.exe/__pycache__/archive.cpython-35.pyc' doesn't exist
# Successful decompilation after using the prepend option
test@test:python python_exe_unpack.py -p unpacked/malware_3.exe/archive
[*] On Python 2.7
[+] Magic bytes are already appended.
# Successfully decompiled file
[+] Successfully decompiled.
Pythonアセンブリの分析
前のステップに従ってpythonの「オリジナル」コードを抽出できなかった場合は、アセンブリを抽出してみてください(ただし、あまり説明的ではありませんので、再度オリジナルコードを抽出してみてください)。ここで、.pyc バイナリを逆アセンブルするための非常にシンプルなコードを見つけました(コードフローを理解するのは大変かもしれません)。.pyc がpython2の場合は、python2を使用してください:
>>> import dis
>>> import marshal
>>> import struct
>>> import imp
>>>
>>> with open('hello.pyc', 'r') as f: # Read the binary file
... magic = f.read(4)
... timestamp = f.read(4)
... code = f.read()
...
>>>
>>> # Unpack the structured content and un-marshal the code
>>> magic = struct.unpack('<H', magic[:2])
>>> timestamp = struct.unpack('<I', timestamp)
>>> code = marshal.loads(code)
>>> magic, timestamp, code
((62211,), (1425911959,), <code object <module> at 0x7fd54f90d5b0, file "hello.py", line 1>)
>>>
>>> # Verify if the magic number corresponds with the current python version
>>> struct.unpack('<H', imp.get_magic()[:2]) == magic
True
>>>
>>> # Disassemble the code object
>>> dis.disassemble(code)
1 0 LOAD_CONST 0 (<code object hello_world at 0x7f31b7240eb0, file "hello.py", line 1>)
3 MAKE_FUNCTION 0
6 STORE_NAME 0 (hello_world)
9 LOAD_CONST 1 (None)
12 RETURN_VALUE
>>>
>>> # Also disassemble that const being loaded (our function)
>>> dis.disassemble(code.co_consts[0])
2 0 LOAD_CONST 1 ('Hello {0}')
3 LOAD_ATTR 0 (format)
6 LOAD_FAST 0 (name)
9 CALL_FUNCTION 1
12 PRINT_ITEM
13 PRINT_NEWLINE
14 LOAD_CONST 0 (None)
17 RETURN_VALUE
Pythonを実行可能ファイルに変換する
まず、payloadがpy2exeとPyInstallerでどのようにコンパイルされるかを示します。
py2exeを使用してpayloadを作成するには:
- http://www.py2exe.org/ からpy2exeパッケージをインストールします。
- payload(この場合、hello.pyと名付けます)には、図1のようなスクリプトを使用します。オプション「bundle_files」の値を1に設定すると、Pythonインタプリタを含むすべてが1つのexeにバンドルされます。
- スクリプトが準備できたら、「python setup.py py2exe」というコマンドを発行します。これにより、図2のように実行可能ファイルが作成されます。
from distutils.core import setup
import py2exe, sys, os
sys.argv.append('py2exe')
setup(
options = {'py2exe': {'bundle_files': 1}},
#windows = [{'script': "hello.py"}],
console = [{'script': "hello.py"}],
zipfile = None,
)
C:\Users\test\Desktop\test>python setup.py py2exe
running py2exe
*** searching for required modules ***
*** parsing results ***
*** finding dlls needed ***
*** create binaries ***
*** byte compile python files ***
*** copy extensions ***
*** copy dlls ***
copying C:\Python27\lib\site-packages\py2exe\run.exe -> C:\Users\test\Desktop\test\dist\hello.exe
Adding python27.dll as resource to C:\Users\test\Desktop\test\dist\hello.exe
PyInstallerを使用してペイロードを作成するには:
- pipを使用してPyInstallerをインストールします(pip install pyinstaller)。
- その後、「pyinstaller –onefile hello.py」というコマンドを発行します(‘hello.py’は私たちのペイロードです)。これにより、すべてが1つの実行可能ファイルにバンドルされます。
C:\Users\test\Desktop\test>pyinstaller --onefile hello.py
108 INFO: PyInstaller: 3.3.1
108 INFO: Python: 2.7.14
108 INFO: Platform: Windows-10-10.0.16299
………………………………
5967 INFO: checking EXE
5967 INFO: Building EXE because out00-EXE.toc is non existent
5982 INFO: Building EXE from out00-EXE.toc
5982 INFO: Appending archive to EXE C:\Users\test\Desktop\test\dist\hello.exe
6325 INFO: Building EXE from out00-EXE.toc completed successfully.
参考文献
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。