Decompile compiled python binaries (exe, elf) - Retreive from .pyc

htARTE(HackTricks AWS Red Team Expert) でAWSハッキングをゼロからヒーローまで学ぶ

HackTricksをサポートする他の方法:

バグバウンティのヒント: Intigritiサインアップして、ハッカーによって作成されたプレミアムバグバウンティプラットフォームに参加しましょう!https://go.intigriti.com/hacktricksで今すぐ参加し、最大**$100,000**のバウンティを獲得しましょう!

コンパイルされたバイナリから .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から実行可能ファイルへ

まず、ペイロードがpy2exeとPyInstallerでコンパイルされる方法を示します。

py2exeを使用してペイロードを作成する方法:

  1. http://www.py2exe.org/ からpy2exeパッケージをインストールします。

  2. ペイロード(この場合、hello.pyと名前を付けます)を作成するには、図1に示すようなスクリプトを使用します。オプション"bundle_files"の値を1に設定すると、Pythonインタプリタを含むすべてが1つのexeにバンドルされます。

  3. スクリプトが準備できたら、コマンド"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を使用してペイロードを作成する方法:

  1. pipを使用してPyInstallerをインストールします(pip install pyinstaller)。

  2. その後、コマンド「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.

参考

バグバウンティのヒント: Intigritiサインアップ してください。これは、ハッカーによって作成されたプレミアム バグバウンティプラットフォーム です!https://go.intigriti.com/hacktricks で今すぐ参加し、最大 $100,000 のバウンティを獲得しましょう!

**htARTE (HackTricks AWS Red Team Expert)** で**ゼロからヒーローまでAWSハッキングを学ぶ** こちら

HackTricks をサポートする他の方法:

Last updated