Dekompileer saamgestelde python binaries (exe, elf) - Verkry vanaf .pyc

Tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks

Van saamgestelde binaire na .pyc

Uit ’n ELF saamgestelde binêre kan jy die .pyc kry met:

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 ’n saamgestelde python exe binary kan jy die .pyc kry deur die volgende uit te voer:

python pyinstxtractor.py executable.exe

Van .pyc na python code

Vir die .pyc data (“compiled” python) moet jy begin probeer onttrek die originele python code:

uncompyle6 binary.pyc  > decompiled.py

Wees seker dat die binary die uitbreiding.pyc” het (indien nie, gaan uncompyle6 nie werk nie)

Terwyl jy uncompyle6 uitvoer, mag jy die volgende foute teëkom:

Error: Unknown magic number 227

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

Om dit reg te stel moet jy die korrekte magiese nommer aan die begin van die gegenereerde lêer byvoeg.

Magiese nommers verskil volgens die python-weergawe, om die magiese nommer van python 3.8 te kry sal jy ’n python 3.8 terminal moet oopmaak en uitvoer:

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

Die magic number in hierdie geval vir python3.8 is 0x550d0d0a. Om hierdie fout reg te stel, moet jy die volgende bytes by die begin van die .pyc file voeg: 0x0d550a0d000000000000000000000000

Sodra jy daardie magic header bygevoeg het, behoort die fout opgelos te wees.

Dit is hoe ’n korrek bygevoegde .pyc python3.8 magic header sal lyk:

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

Fout: Algemene dekompileringsfoute

Andere foute soos: class 'AssertionError'>; co_code should be one of the types (<class 'str'>, <class 'bytes'>, <class 'list'>, <class 'tuple'>); is type <class 'NoneType'> kan voorkom.

Dit beteken waarskynlik dat jy nie die magic number korrek bygevoeg het nie of dat jy nie die korrekte magic number gebruik het nie, maak dus seker dat jy die korrekte een gebruik (of probeer ’n nuwe een).

Raadpleeg die vorige foutdokumentasie.

Outomatiese Tool

Die python-exe-unpacker tool dien as ’n kombinasie van verskeie gemeenskaps-beskikbare gereedskap wat ontwerp is om navorsers te help met die unpack en dekompilerings van uitvoerbare lêers geskryf in Python, spesifiek dié wat met py2exe en pyinstaller geskep is. Dit sluit YARA-reëls in om te identifiseer of ’n uitvoerbare lêer Python-gebaseer is en om die skeppingsgereedskap te bevestig.

ImportError: Lêernaam: ‘unpacked/malware_3.exe/pycache/archive.cpython-35.pyc’ bestaan nie

’n Algemene probleem wat aangetref word behels ’n onvolledige Python bytecode-lêer wat voortspruit uit die unpacking process with unpy2exe or pyinstxtractor, wat dan fails to be recognized by uncompyle6 due to a missing Python bytecode version number. Om dit aan te spreek is ’n prepend-opsie bygevoeg wat die nodige Python bytecode-weergawe-nommer byvoeg, en so die dekompileringsproses vergemaklik.

Example of the issue:

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

Ontleding van python assembly

As jy nie daarin kon slaag om die python “oorspronklike” kode uit die vorige stappe te onttrek nie, kan jy probeer om die assembly te onttrek (but it is nie baie beskrywend nie, so probeer om weer die oorspronklike kode te onttrek). In here het ek ’n baie eenvoudige kode gevind om die disassemble die .pyc binary (sterkte om die kodevloei te verstaan). As die .pyc van python2 is, gebruik python2:

Disassemble a .pyc ```python >>> 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('>> timestamp = struct.unpack('>> code = marshal.loads(code) >>> magic, timestamp, code ((62211,), (1425911959,), at 0x7fd54f90d5b0, file "hello.py", line 1>) >>> >>> # Verify if the magic number corresponds with the current python version >>> struct.unpack('>> >>> # Disassemble the code object >>> dis.disassemble(code) 1 0 LOAD_CONST 0 () 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 ```

PyInstaller raw marshal & Pyarmor v9 static unpack workflow

  • Onttrek ingebedde marshal blobs: pyi-archive_viewer sample.exe en exporteer rou objects (bv. ’n lêer genaamd vvs). PyInstaller stoor blote marshal streams wat begin met 0xe3 (TYPE_CODE met FLAG_REF) in plaas van volledige .pyc-lêers. Voeg die korrekte 16-bytte .pyc header vooraan (magic vir die ingebedde interpreter-weergawe + nulgestelde timestamp/grootte) sodat dekompileerders dit aanvaar. Vir Python 3.11.5 kan jy die magic kry via imp.get_magic().hex() en dit met dd/printf patseer voor die marshal payload.
  • Dekompileer met weergawe-bewuste gereedskap: pycdc -c -v 3.11.5 vvs.pyc > vvs.py of PyLingual. As slegs gedeeltelike kode nodig is, kan jy die AST deurloop (bv. ast.NodeVisitor) om spesifieke argumente/konstantes te onttrek.
  • Parse die Pyarmor v9 header om crypto-parameters te herwin: signature PY<license> by 0x00, Python major/minor by 0x09/0x0a, protection type 0x09 wanneer BCC geaktiveer is (0x08 anders), ELF start/end offsets by 0x1c/0x38, en die 12-bytte AES-CTR nonce wat oor 0x24..0x27 en 0x2c..0x33 gesplit is. Dieselfde patroon herhaal na die ingebedde ELF.
  • Neem rekening met Pyarmor-gemodifiseerde code objects: co_flags het bit 0x20000000 gestel en ’n ekstra length-prefixed veld. Deaktiveer CPython deopt_code() tydens parsing om dekripsiefoute te vermy.
  • Identifiseer geënkripteerde kodegebiede: bytecode is omring deur LOAD_CONST __pyarmor_enter_*__LOAD_CONST __pyarmor_exit_*__. Dekripteer die ingeslotene blob met AES-128-CTR gebruikende die runtime key (bv. 273b1b1373cf25e054a61e2cb8a947b8). Lei die per-streek nonce af deur die payload-spesifieke 12-bytte XOR key (van die Pyarmor runtime) te XOR met die 12 bytes in die __pyarmor_exit_*__ merk. Na dekripsie kan jy ook __pyarmor_assert_*__ (geënkripteerde strings) en __pyarmor_bcc_*__ (gecompileerde dispatch targets) sien.
  • Dekripteer Pyarmor “mixed” strings: konstantes voorafgegaan deur 0x81 is AES-128-CTR geënkripteer (plaintext gebruik 0x01). Gebruik dieselfde sleutel en die runtime-afgeleide string-nonce (bv. 692e767673e95c45a1e6876d) om lang string-konstantes te herstel.
  • Hanteer BCC mode: Pyarmor --enable-bcc kompileer baie funksies na ’n begeleidende ELF en laat Python-stubs wat __pyarmor_bcc_*__ roep. Map daardie konstantes na ELF-symbols met gereedskap soos bcc_info.py, en dekompileer/analyseer dan die ELF by die gerapporteerde offsets (bv. __pyarmor_bcc_58580__bcc_180 by offset 0x4e70).

Python to Executable

Om te begin, gaan ons wys hoe payloads in py2exe en PyInstaller saamgestel kan word.

Om ’n payload met py2exe te skep:

  1. Installeer die py2exe-pakket vanaf http://www.py2exe.org/
  2. Vir die payload (in hierdie geval noem ons dit hello.py), gebruik ’n script soos die een in Figuur 1. Die opsie “bundle_files” met die waarde 1 sal alles saambind, insluitend die Python interpreter, in een exe.
  3. Sodra die script gereed is, voer ons die kommando python setup.py py2exe. Dit sal die uitvoerbare lêer skep, net soos in Figuur 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

Om ’n payload met PyInstaller te skep:

  1. Installeer PyInstaller met pip (pip install pyinstaller).
  2. Daarna voer ons die opdrag “pyinstaller –onefile hello.py” uit (ter herinnering: ‘hello.py’ is ons payload). Dit sal alles in een uitvoerbare lêer saamvoeg.
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.

Verwysings

Tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks