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

Support HackTricks

Bug-Bounty-Tipp: Melde dich an bei Intigriti, einer Premium-Bug-Bounty-Plattform, die von Hackern für Hacker erstellt wurde! Schließe dich uns heute an unter https://go.intigriti.com/hacktricks und beginne, Belohnungen von bis zu $100.000 zu verdienen!

Von kompiliertem Binary zu .pyc

Von einem ELF kompilierten Binary kannst du die .pyc mit:

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 einer python exe-Binärdatei können Sie die .pyc erhalten, indem Sie Folgendes ausführen:

python pyinstxtractor.py executable.exe

Von .pyc zu Python-Code

Für die .pyc-Daten ("kompilierte" Python) sollten Sie versuchen, den ursprünglichen Python-Code zu extrahieren:

uncompyle6 binary.pyc  > decompiled.py

Stellen Sie sicher, dass die Binärdatei die Erweiterung ".pyc" hat (wenn nicht, wird uncompyle6 nicht funktionieren)

Beim Ausführen von uncompyle6 könnten Sie die folgenden Fehler feststellen:

Fehler: Unbekannte magische Zahl 227

/kali/.local/bin/uncompyle6 /tmp/binary.pyc
Unknown magic number 227 in /tmp/binary.pyc

Um dies zu beheben, müssen Sie die richtige Magic-Nummer am Anfang der generierten Datei hinzufügen.

Magic-Nummern variieren mit der Python-Version, um die Magic-Nummer von Python 3.8 zu erhalten, müssen Sie ein Python 3.8-Terminal öffnen und ausführen:

>> import imp
>> imp.get_magic().hex()
'550d0d0a'

Die magic number in diesem Fall für python3.8 ist 0x550d0d0a, dann müssen Sie, um diesen Fehler zu beheben, die folgenden Bytes am Anfang der .pyc-Datei hinzufügen: 0x0d550a0d000000000000000000000000

Sobald Sie diesen magic header hinzugefügt haben, sollte der Fehler behoben sein.

So sieht ein korrekt hinzugefügter .pyc python3.8 magic header aus:

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

Fehler: Decompiling generische Fehler

Andere Fehler wie: class 'AssertionError'>; co_code sollte einer der Typen sein (<class 'str'>, <class 'bytes'>, <class 'list'>, <class 'tuple'>); ist Typ <class 'NoneType'> können auftreten.

Das bedeutet wahrscheinlich, dass Sie die magische Zahl nicht korrekt hinzugefügt haben oder dass Sie nicht die richtige magische Zahl verwendet haben, also stellen Sie sicher, dass Sie die richtige verwenden (oder versuchen Sie eine neue).

Überprüfen Sie die vorherige Fehlermeldungsdokumentation.

Automatisches Werkzeug

Das python-exe-unpacker Tool dient als Kombination mehrerer in der Community verfügbarer Werkzeuge, die Forschern helfen sollen, ausführbare Dateien, die in Python geschrieben wurden, insbesondere solche, die mit py2exe und pyinstaller erstellt wurden, zu entpacken und zu dekompilieren. Es enthält YARA-Regeln, um zu identifizieren, ob eine ausführbare Datei auf Python basiert, und bestätigt das Erstellungswerkzeug.

ImportError: Dateiname: 'unpacked/malware_3.exe/pycache/archive.cpython-35.pyc' existiert nicht

Ein häufiges Problem besteht darin, dass eine unvollständige Python-Bytecode-Datei aus dem Entpackungsprozess mit unpy2exe oder pyinstxtractor resultiert, die dann von uncompyle6 aufgrund einer fehlenden Python-Bytecode-Versionnummer nicht erkannt wird. Um dies zu beheben, wurde eine Voranstellungsoption hinzugefügt, die die erforderliche Python-Bytecode-Versionnummer anfügt und den Dekompilierungsprozess erleichtert.

Beispiel für das Problem:

# 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

Wenn es Ihnen nicht gelungen ist, den python "originalen" Code gemäß den vorherigen Schritten zu extrahieren, können Sie versuchen, die assembly zu extrahieren (aber es ist nicht sehr beschreibend, also versuchen Sie, den originalen Code noch einmal zu extrahieren). Hier hier habe ich einen sehr einfachen Code gefunden, um die .pyc Binärdatei zu disassemblieren (viel Glück beim Verstehen des Codeflusses). Wenn die .pyc von python2 ist, verwenden Sie 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 zu Executable

Um zu beginnen, zeigen wir Ihnen, wie Payloads in py2exe und PyInstaller kompiliert werden können.

Um einen Payload mit py2exe zu erstellen:

  1. Installieren Sie das py2exe-Paket von http://www.py2exe.org/

  2. Für den Payload (in diesem Fall nennen wir ihn hello.py) verwenden Sie ein Skript wie das in Abbildung 1. Die Option “bundle_files” mit dem Wert 1 wird alles, einschließlich des Python-Interpreters, in eine exe bündeln.

  3. Sobald das Skript bereit ist, geben wir den Befehl “python setup.py py2exe” ein. Dies wird die ausführbare Datei erstellen, genau wie in Abbildung 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

Um ein Payload mit PyInstaller zu erstellen:

  1. Installieren Sie PyInstaller mit pip (pip install pyinstaller).

  2. Danach geben wir den Befehl “pyinstaller –onefile hello.py” ein (eine Erinnerung, dass ‘hello.py’ unser Payload ist). Dies wird alles in eine ausführbare Datei bündeln.

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

Bug bounty tip: Melden Sie sich an für Intigriti, eine Premium-Bug-Bounty-Plattform, die von Hackern für Hacker erstellt wurde! Treten Sie uns bei https://go.intigriti.com/hacktricks heute bei und beginnen Sie, Prämien von bis zu 100.000 $ zu verdienen!

Support HackTricks

Last updated