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

Lernen Sie AWS-Hacking von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

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

Vom kompilierten Binärformat zu .pyc

Von einem ELF-kompilierten Binärformat können Sie die .pyc mit erhalten:

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 einem Python-Exe-Binär können Sie das .pyc erhalten, indem Sie Folgendes ausführen:

python pyinstxtractor.py executable.exe

Von .pyc zu Python-Code

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

uncompyle6 binary.pyc  > decompiled.py

Stellen Sie sicher, dass die Binärdatei die Erweiterung ".pyc" hat (ansonsten funktioniert Uncompyle6 nicht)

Bei der Ausführung von uncompyle6 können Sie die folgenden Fehler finden:

Fehler: Unbekannte Magische Nummer 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 Magische Zahl hinzufügen am Anfang der generierten Datei.

Magische Zahlen variieren je nach Python-Version, um die Magische Zahl 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'

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

Nachdem Sie diesen magischen Header hinzugefügt haben, sollte der Fehler behoben sein.

So sieht ein korrekt hinzugefügter .pyc Python3.8 Magischer 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: Dekompilierungsfehler

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

Dies bedeutet wahrscheinlich, dass Sie die Magische Nummer nicht korrekt hinzugefügt haben oder dass Sie die falsche Magische Nummer verwendet haben, also stellen Sie sicher, dass Sie die richtige verwenden (oder versuchen Sie eine neue).

Überprüfen Sie die vorherige Fehlerdokumentation.

Automatisches Tool

Das python-exe-unpacker Tool dient als Kombination mehrerer in der Community verfügbarer Tools, die Forschern beim Entpacken und Dekompilieren von in Python geschriebenen ausführbaren Dateien helfen, insbesondere solchen, die mit py2exe und pyinstaller erstellt wurden. Es enthält YARA-Regeln, um festzustellen, ob eine ausführbare Datei auf Python basiert, und bestätigt das Erstellungstool.

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 aufgrund des Entpackungsprozesses mit unpy2exe oder pyinstxtractor entsteht, die dann von uncompyle6 aufgrund einer fehlenden Python-Bytecode-Version nicht erkannt wird. Um dies zu beheben, wurde eine Vorsatzoption hinzugefügt, die die erforderliche Python-Bytecode-Version anhängt 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 ursprünglichen Python-Code gemäß den vorherigen Schritten zu extrahieren, können Sie versuchen, die Assembly zu extrahieren (sie ist jedoch nicht sehr beschreibend, also versuchen Sie erneut, den ursprünglichen Code zu extrahieren). Hier habe ich einen sehr einfachen Code gefunden, um die .pyc Binärdatei zu disassemblieren (viel Glück beim Verständnis des Codeflusses). Wenn die .pyc von Python2 stammt, 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 ausführbarer Datei

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. Verwenden Sie für den Payload (in diesem Fall nennen wir es hello.py) 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. Dadurch wird die ausführbare Datei erstellt, 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" aus (zur Erinnerung, 'hello.py' ist unser Payload). Dadurch wird alles in eine ausführbare Datei gebündelt.

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.

Referenzen

Bug-Bounty-Tipp: Registriere dich bei Intigriti, einer Premium-Bug-Bounty-Plattform, die von Hackern für Hacker erstellt wurde! Trete uns noch heute bei unter https://go.intigriti.com/hacktricks und beginne, Prämien von bis zu 100.000 $ zu verdienen!

Lerne AWS-Hacking von Null auf Held mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Last updated