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

AWSハッキングを学び、練習する:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングを学び、練習する:HackTricks Training GCP Red Team Expert (GRTE)

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

In a python exe binary compiled you can get the .pyc by running: python exe バイナリ をコンパイルすると、次のコマンドを実行することで .pyc を取得できます:

python pyinstxtractor.py executable.exe

From .pyc to python code

.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'

The magic number in this case for python3.8 is 0x550d0d0a, then, to fix this error you will need to add at the beginning of the .pyc file the following bytes: 0x0d550a0d000000000000000000000000

Once you have added that magic header, the error should be fixed.

This is how a correctly added .pyc python3.8 magic header will look like:

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.

Analyzing python assembly

もし前の手順に従って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 to Executable

最初に、payloadがpy2exeとPyInstallerでどのようにコンパイルされるかを示します。

py2exeを使用してpayloadを作成するには:

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

  2. payload(この場合、hello.pyと名付けます)には、図1のようなスクリプトを使用します。値が1のオプション“bundle_files”は、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.

References

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

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)

HackTricksをサポートする

Last updated