
Decompilatore Python per 3.7-3.8 Derivato da uncompyle6 per poter rifattorizzare e iniziare a risolvere alcuni problemi di lunga data
|buildstatus| |Pypi Installs| |Latest Version| |Supported Python Versions|
|packagestatus|
.. contents::
Un decompilatore Python nativo cross-version e decompilatore di frammenti. Una rielaborazione di uncompyle6_.
Ho tenuto una presentazione su questo a BlackHat Asia 2024 <https://youtu.be/H-7ZNrpsV50?si=nOaixgYHr7RbILVS>_.
decompyle3 traduce il bytecode Python in codice sorgente Python equivalente. Accetta bytecode dalla versione 3.7 in poi.
Per la decompilazione di bytecode Python più vecchi, vedere uncompyle6_.
Uncompyle6 è fantastico, ma ha un problema fondamentale nel modo in cui gestisce il flusso di controllo. Nei primi giorni di Python, quando c'era poca ottimizzazione e il codice veniva generato in modo molto basato su template, individuare le strutture di controllo poteva essere fatto semplicemente osservando i pattern del codice.
Nel corso degli anni, maggiore ottimizzazione del codice, in particolare intorno alla gestione dei salti, ha reso più difficile supportare il rilevamento del flusso di controllo strettamente dai pattern del codice. Questo è stato notato già da Python 2.4 (2004), ma poiché è un problema difficile, finora non è stato affrontato in modo soddisfacente.
Il tentativo iniziale di risolvere questo problema è stato aggiungere marcatori nel flusso di istruzioni, inizialmente un'istruzione COME_FROM, e poi usarla nel rilevamento dei pattern.
Nel corso degli anni, l'ho esteso per essere più specifico, quindi sono stati aggiunti COME_FROM_LOOP e COME_FROM_WITH. E ho aggiunto controlli al momento della riduzione della grammatica per cercare di assicurarmi che i salti corrispondano ai presunti target COME_FROM.
Tuttavia, tutto questo è complicato, non robusto, ha notevolmente rallentato il deparsing e non è realmente sostenibile.
In questo progetto, abbiamo iniziato a riscrivere e rifattorizzare la grammatica.
Tuttavia, anche questo non basta. Il flusso di controllo deve essere affrontato usando dominatori e dominatori inversi, che il progetto python-control-flow_ può fornire.
Questo lo sto finalmente facendo lentamente in un altro progetto non pubblico. È molto lavoro. I finanziamenti sotto forma di sponsorizzazione, sebbene molto apprezzati, non sono commisurati allo sforzo, e attualmente ho un lavoro a tempo pieno. Quindi potrebbe volerci del tempo prima che sia disponibile pubblicamente, se mai lo sarà.
Il codice qui può essere eseguito su Python versioni 3.7 o 3.8. I file bytecode che può leggere sono stati testati su bytecode Python delle versioni 3.7 e 3.8.
Puoi installare da PyPI usando il nome decompyle3::
pip install decompyle3
Per installare dal codice sorgente, questo progetto usa setup.py, quindi segue la routine standard di Python::
$ pip install -e . # set up to run from source tree
oppure::
$ python setup.py install # may need sudo
Viene fornito anche un GNU Makefile, quindi :code:make install (possibilmente come root o sudo) farà i passaggi sopra.
::
make check
È stato aggiunto un GNU makefile per facilitare l'impostazione e l'esecuzione del comando giusto, e l'esecuzione dei test dal più veloce al più lento.
Se hai remake_ installato, puoi vedere l'elenco di tutte le attività inclusi i test tramite :code:remake --tasks
Esegui
::
$ decompyle3 compiled-python-file-pyc-or-pyo
Per aiuto sull'uso:
::
$ decompyle3 -h
Se vuoi la verifica della sintassi Python della correttezza del processo di decompilazione, aggiungi l'opzione :code:--syntax-verify. Tuttavia, poiché la sintassi Python cambia. Dovresti usare questa opzione se il bytecode è il bytecode giusto per l'interprete Python che controllerà la sintassi.
Puoi anche confrontare i risultati con un altro decompilatore Python come unpyc37_. Poiché funzionano diversamente, i bug qui spesso non sono presenti in quello, e viceversa.
C'è una classe interessante di questi programmi che è prontamente disponibile per dare una verifica più forte: quei programmi che, quando eseguiti, testano se stessi. La nostra suite di test li include.
E Python viene fornito con un altro insieme di programmi come questo: la sua suite di test per la libreria standard. Abbiamo del codice in :code:test/stdlib per facilitare anche questo tipo di controllo.
Supportiamo solo versioni rilasciate, non versioni candidate. Nota comunque che il magic number di una versione rilasciata è solitamente lo stesso dell'ultima versione candidata prima del rilascio.
Inoltre non gestiamo PJOrion_ o codice altrimenti offuscato. Per PJOrion prova: PJOrion Deobfuscator_ per decifrare il bytecode e ottenere bytecode valido prima di provare questo strumento; pydecipher_ potrebbe aiutare.
Questo programma non può decompilare file EXE di Microsoft Windows creati da Py2EXE_, anche se possiamo probabilmente decompilare il codice dopo aver estratto correttamente il bytecode. Pydeinstaller <https://github.com/charles-dyfis-net/pydeinstaller>_ può aiutare a decomprimere i bundler Pyinstaller.
La gestione di liste patologicamente lunghe di espressioni o istruzioni è lenta. Non gestiamo Cython_ o MicroPython, che non usano bytecode.
Ci sono numerosi bug nella decompilazione. E questo è vero per ogni altro decompilatore CPython che ho incontrato, anche quelli che affermavano di essere 'perfetti' su qualche versione particolare come la 2.4.
Con il progredire di Python, la decompilazione diventa più difficile perché la compilazione è più sofisticata e il linguaggio stesso è più sofisticato. Sospetto che ci saranno meno tentativi ad hoc come unpyc37_ (che si basa su un decompilatore 3.3) semplicemente perché è più difficile farlo. La buona notizia, almeno dal mio punto di vista, è che penso di capire cosa serve per affrontare i problemi in modo più robusto. Ma al momento, fino a quando il progetto non sarà meglio finanziato, non intendo fare alcuno sforzo serio per supportare Python versioni 3.8 o 3.9, inclusi i bug che potrebbero presentarsi. Immagino che a un certo punto potrei essere interessato.
Puoi facilmente trovare bug eseguendo i test contro la suite di test standard che Python usa per controllarsi. In qualsiasi momento, ci sono dozzine di problemi noti che sono abbastanza ben isolati e che potrebbero essere risolti se si dedicasse tempo. Il problema è che non ci sono molte persone che hanno lavorato alla correzione dei bug.
Potresti imbatterti in un bug che desideri segnalare. Per favore fallo. Ma sii consapevole che potrebbe non attirare la mia attenzione per un po'. Se sponsorizzi o supporti il progetto in qualche modo, darò priorità ai tuoi problemi rispetto alla coda di altre cose che potrei fare. In rare situazioni, posso fare una decompilazione manuale del bytecode a pagamento. Tuttavia, questo è costoso, di solito oltre ciò che la maggior parte delle persone è disposta a spendere.
uncompyle e decompyle.