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

Ondersteun HackTricks

Bug bounty wenk: meld aan vir Intigriti, 'n premium bug bounty platform geskep deur hackers, vir hackers! Sluit by ons aan by https://go.intigriti.com/hacktricks vandag, en begin verdien bounties tot $100,000!

Van Gecompileerde Binêre na .pyc

Van 'n ELF gecompileerde 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 python exe binêre gecompileer kan jy die .pyc kry deur te loop:

python pyinstxtractor.py executable.exe

Van .pyc na python kode

Vir die .pyc data ("gecompileerde" python) moet jy begin probeer om die oorspronklike python kode te onttrek:

uncompyle6 binary.pyc  > decompiled.py

Maak seker dat die binêre die uitbreiding ".pyc" het (as nie, gaan uncompyle6 nie werk nie)

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

Fout: Onbekende magiese nommer 227

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

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

Magiese nommers verskil met 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, dan, om hierdie fout reg te stel, sal jy moet byvoeg aan die begin van die .pyc file die volgende bytes: 0x0d550a0d000000000000000000000000

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

So sal 'n korrek bygevoegde .pyc python3.8 magic header 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: Decompileer generiese foute

Ander foute soos: class 'AssertionError'>; co_code moet een van die tipes wees (<class 'str'>, <class 'bytes'>, <class 'list'>, <class 'tuple'>); is tipe <class 'NoneType'> mag verskyn.

Dit beteken waarskynlik dat jy nie korrek die magiese nommer bygevoeg het nie of dat jy nie die korrekte magiese nommer gebruik het nie, so maak verseker jy gebruik die korrekte een (of probeer 'n nuwe een).

Kyk na die vorige fout dokumentasie.

Outomatiese Gereedskap

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

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

'n Algemene probleem wat ondervind word, behels 'n onvolledige Python bytecode-lêer wat ontstaan uit die uitpakproses met unpy2exe of pyinstxtractor, wat dan nie deur uncompyle6 erken word nie weens 'n ontbrekende Python bytecode weergawe nommer. Om dit aan te spreek, is 'n prepend opsie bygevoeg, wat die nodige Python bytecode weergawe nommer byvoeg, wat die decompileerproses vergemaklik.

Voorbeeld van die probleem:

# 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

As jy nie in staat was om die python "oorspronklike" kode te onttrek nie, kan jy probeer om die assembly te onttrek (maar dit is nie baie beskrywend nie, so probeer om die oorspronklike kode weer te onttrek). In hier het ek 'n baie eenvoudige kode gevind om die .pyc binêre te ontbind (sterkte met die verstaan van die kodevloei). As die .pyc van python2 is, gebruik 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 na Uitvoerbare

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

Om 'n payload te skep met py2exe:

  1. Installeer die py2exe-pakket van http://www.py2exe.org/

  2. Vir die payload (in hierdie geval, sal ons dit hello.py noem), gebruik 'n skrif soos die een in Figuur 1. Die opsie “bundle_files” met die waarde van 1 sal alles insluit, insluitend die Python-interpretator, in een exe.

  3. Sodra die skrif gereed is, sal ons die opdrag “python setup.py py2exe” gee. Dit sal die uitvoerbare 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 te skep met PyInstaller:

  1. Installeer PyInstaller met pip (pip install pyinstaller).

  2. Daarna sal ons die opdrag “pyinstaller –onefile hello.py” gee (’n herinnering dat ‘hello.py’ ons payload is). 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

Bug bounty wenk: meld aan vir Intigriti, 'n premium bug bounty platform geskep deur hackers, vir hackers! Sluit vandag by ons aan by https://go.intigriti.com/hacktricks en begin om belonings tot $100,000 te verdien!

Ondersteun HackTricks

Last updated