Isi
Dekompiler lintas versi dan dekompiler fragmen Python asli. Penerus decompyle, uncompyle, dan uncompyle2.
uncompyle6 menerjemahkan bytecode Python kembali ke kode sumber Python yang setara. Ia menerima bytecode dari Python versi 1.0 hingga versi 3.8, yang mencakup lebih dari 24 tahun rilis Python. Kami menyertakan bytecode Python 2.5 Dropbox dan beberapa bytecode PyPy.
Oke, saya akan mengatakannya: perangkat lunak ini luar biasa. Ini lebih dari dekompiler hacky normal Anda. Menggunakan teknologi kompiler, program membuat pohon parse program dari instruksi; node di tingkat atas yang terlihat seperti apa yang mungkin berasal dari Python AST. Jadi kita benar-benar dapat mengklasifikasikan dan memahami apa yang terjadi di bagian bytecode Python.
Berdasarkan hal ini, hal lain yang membuatnya berbeda dari dekompiler bytecode CPython lainnya adalah kemampuannya untuk menguraikan hanya fragmen kode sumber dan memberikan informasi kode sumber di sekitar offset bytecode tertentu.
Saya menggunakan fragmen pohon untuk menguraikan fragmen kode pada saat run time di dalam debugger trepan saya. Untuk itu, offset bytecode dicatat dan dikaitkan dengan fragmen kode sumber. Tujuan ini, meskipun sesuai dengan maksud awal, namun sedikit berbeda. Lihat ini untuk informasi lebih lanjut.
Deparsing fragmen Python dengan instruksi offset berguna dalam menampilkan jejak tumpukan dan dapat dimasukkan ke dalam program apa pun yang ingin menampilkan lokasi secara lebih detail daripada sekadar nomor baris saat runtime. Kode ini juga dapat digunakan ketika informasi kode sumber tidak ada dan yang ada hanya bytecode. Sekali lagi, debugger saya memanfaatkan ini.
Ada (dan masih) sejumlah garpu decompyle, uncompyle, uncompyle2, uncompyle3. Banyak di antaranya yang pada dasarnya berasal dari basis kode yang sama, dan (hampir?) semuanya tidak lagi dipelihara secara aktif. Yang satu sangat bagus dalam mendekompilasi Python 1.5-2.3, yang lain sangat bagus dalam Python 2.7, tapi itu saja. Yang lain hanya menangani Python 3.2; yang lain menambalnya dan hanya menangani 3.3. Anda mengerti idenya. Kode ini menyatukan semua percabangan ini dan bergerak maju . Ada beberapa pemfaktoran ulang dan pembersihan serius dalam basis kode ini pada fork lama tersebut. Pemfaktoran ulang yang lebih eksperimental sedang dilakukan di decompyle3.
Ini terbukti melakukan yang terbaik dalam mendekompilasi Python di semua versi Python. Dan bahkan ketika ada proyek lain yang hanya menyediakan dekompilasi untuk sebagian versi Python, secara umum kami juga melakukan hal yang lebih baik untuk proyek tersebut.
Bagaimana kita bisa mengetahuinya? Dengan mengambil bytecode Python yang didistribusikan dengan versi Python tersebut dan mendekompilasinya. Di antara program yang berhasil didekompilasi, kami kemudian dapat memastikan program yang dihasilkan benar secara sintaksis dengan menjalankan juru bahasa Python untuk versi bytecode tersebut. Terakhir, jika program mempunyai pengujian sendiri, kita dapat menjalankan pemeriksaan pada kode yang telah didekompilasi.
Kami menggunakan proses otomatis untuk menemukan bug. Dalam pelacak masalah untuk dekompiler lainnya, Anda akan menemukan sejumlah bug yang kami temukan selama ini. Sangat sedikit atau tidak ada satupun yang diperbaiki di dekompiler lainnya.
Kode dalam repositori git dapat dijalankan dari Python 2.4 hingga versi Python terbaru, dengan pengecualian Python 3.0 hingga 3.2. Relawan dipersilakan untuk mengatasi kekurangan ini jika ada keinginan untuk melakukannya.
Cara melakukannya adalah dengan memisahkan versi Python berturut-turut ke dalam cabang git:
PyPy 3-2.4 dan yang lebih baru juga berfungsi.
File bytecode yang dapat dibacanya telah diuji pada bytecode Python dari versi 1.4, 2.1-2.7, dan 3.0-3.8 dan versi PyPy yang lebih baru.
Anda dapat menginstal dari PyPI menggunakan nama uncompyle6
:
pip instal uncompyle6
Untuk menginstal dari kode sumber, proyek ini menggunakan setup.py, sehingga mengikuti rutinitas standar Python:
$ pip instal -e. # diatur untuk dijalankan dari pohon sumber
atau:
$ python setup.py install # mungkin memerlukan sudo
GNU Makefile juga disediakan jadi make install
(mungkin sebagai root atau sudo) akan melakukan langkah-langkah di atas.
melakukan pengecekan
Makefile GNU telah ditambahkan untuk memperlancar pengaturan menjalankan perintah yang benar, dan menjalankan pengujian dari yang tercepat hingga yang paling lambat.
Jika Anda telah menginstal remake, Anda dapat melihat daftar semua tugas termasuk tes melalui remake --tasks
Berlari
$ uncompyle6 *kompilasi-file-python-pyc-or-pyo*
Untuk bantuan penggunaan:
$ batalkan kompilasi6 -h
Dalam versi Python yang lebih lama, dimungkinkan untuk memverifikasi bytecode dengan mendekompilasi bytecode, dan kemudian mengkompilasi menggunakan juru bahasa Python untuk versi bytecode tersebut. Setelah melakukan ini, bytecode yang dihasilkan dapat dibandingkan dengan bytecode aslinya. Namun karena pembuatan kode Python menjadi lebih baik, hal ini tidak lagi dapat dilakukan.
Jika Anda ingin verifikasi sintaksis Python atas kebenaran proses dekompilasi, tambahkan opsi --syntax-verify
. Namun karena sintaksis Python berubah, Anda harus menggunakan opsi ini jika bytecode tersebut adalah bytecode yang tepat untuk juru bahasa Python yang akan memeriksa sintaksisnya.
Anda juga dapat membandingkan silang hasilnya dengan versi uncompyle6 yang lain karena terkadang ada regresi dalam mendekompilasi bytecode tertentu seiring dengan peningkatan kualitas secara keseluruhan.
Untuk Python 3.7 dan 3.8, kode di decompyle3 umumnya lebih baik.
Atau coba dekompiler python lain yang spesifik seperti uncompyle2, unpyc37, atau pycdc. Karena dua yang terakhir bekerja secara berbeda, bug di sini sering kali tidak ada di dalamnya, dan sebaliknya.
Ada kelas menarik dari program-program ini yang tersedia dan memberikan verifikasi yang lebih kuat: program-program yang ketika dijalankan akan menguji dirinya sendiri. Rangkaian pengujian kami mencakup ini.
Dan Python hadir dengan serangkaian program lain seperti ini: rangkaian pengujiannya untuk perpustakaan standar. Kami memiliki beberapa kode di test/stdlib
untuk memfasilitasi pemeriksaan semacam ini juga.
Masalah terbesar yang diketahui dan mungkin dapat diperbaiki (tetapi sulit) berkaitan dengan penanganan aliran kontrol. (Python mungkin memiliki rangkaian pernyataan majemuk yang paling beragam dan kacau yang pernah saya lihat; ada klausa "lain" pada loop dan blok try yang saya curigai tidak diketahui oleh banyak programmer.)
Semua dekompiler Python yang saya lihat memiliki masalah saat mendekompilasi aliran kontrol Python. Dalam beberapa kasus, kami dapat mendeteksi kesalahan dekompilasi dan melaporkannya.
Dukungan Python cukup bagus untuk Python 2
Pada versi Python kelas bawah, dekompilasi tampaknya cukup bagus meskipun kami tidak memiliki pengujian otomatis apa pun untuk pengujian terdistribusi Python. Selain itu, kami tidak memiliki juru bahasa Python untuk versi 1.6 dan 2.0.
Dalam seri Python 3, dukungan Python paling kuat di sekitar 3.4 atau 3.3 dan menurun saat Anda semakin menjauh dari versi tersebut. Python 3.0 aneh karena dalam beberapa hal lebih menyerupai 2.6 daripada 3.1 atau 2.7. Python 3.6 mengubah banyak hal secara drastis dengan menggunakan kode kata daripada kode byte. Akibatnya, bidang offset lompat dalam argumen instruksi lompat telah dikurangi. Hal ini membuat instruksi EXTENDED_ARG
sekarang lebih lazim dalam instruksi lompat; sebelumnya mereka jarang terjadi. Mungkin untuk mengimbangi petunjuk EXTENDED_ARG
tambahan, pengoptimalan lompatan tambahan telah ditambahkan. Jadi secara keseluruhan penanganan aliran kontrol dengan cara ad hoc seperti yang dilakukan saat ini lebih buruk.
Antara Python 3.5, 3.6, 3.7 ada perubahan besar pada instruksi MAKE_FUNCTION
dan CALL_FUNCTION
.
Python 3.8 menghapus SETUP_LOOP
, SETUP_EXCEPT
, BREAK_LOOP
, dan CONTINUE_LOOP
, instruksi yang mungkin membuat deteksi aliran kontrol lebih sulit, sehingga tidak memiliki analisis aliran kontrol yang lebih canggih seperti yang direncanakan. Kita lihat saja nanti.
Saat ini tidak semua nomor ajaib Python didukung. Khususnya di beberapa versi Python, terutama Python 3.6, angka ajaibnya telah berubah beberapa kali dalam suatu versi.
Kami hanya mendukung versi yang dirilis, bukan versi kandidat. Namun perlu diperhatikan bahwa keajaiban versi yang dirilis biasanya sama dengan versi kandidat terakhir sebelum rilis.
Ada juga penerjemah Python yang disesuaikan, terutama Dropbox, yang menggunakan sihirnya sendiri dan mengenkripsi bytecode. Dengan pengecualian juru bahasa Python 2.5 lama Dropbox, hal semacam ini tidak ditangani.
Kami juga tidak menangani PJOrion atau kode yang dikaburkan. Untuk PJOrion coba: PJOrion Deobfuscator menguraikan bytecode untuk mendapatkan bytecode yang valid sebelum mencoba alat ini; pydecipher mungkin bisa membantu dalam hal itu.
Program ini tidak dapat mendekompilasi file Microsoft Windows EXE yang dibuat oleh Py2EXE, meskipun kami mungkin dapat mendekompilasi kode setelah Anda mengekstrak bytecode dengan benar. Pydeinstaller dapat membantu membongkar bundler Pyinstaller.
Menangani daftar ekspresi atau pernyataan yang panjang secara patologis membutuhkan waktu yang lambat. Kami tidak menangani Cython atau MicroPython yang tidak menggunakan bytecode.
Ada banyak bug dalam dekompilasi. Dan itu berlaku untuk setiap dekompiler CPython lain yang saya temui, bahkan yang diklaim "sempurna" pada versi tertentu seperti 2.4.
Seiring kemajuan Python, dekompilasi juga menjadi lebih sulit karena kompilasinya lebih canggih dan bahasanya sendiri lebih canggih. Saya menduga akan ada lebih sedikit upaya ad-hoc seperti unpyc37 (yang didasarkan pada dekompiler 3.3) hanya karena lebih sulit untuk melakukannya. Kabar baiknya, setidaknya dari sudut pandang saya, saya rasa saya memahami apa yang diperlukan untuk mengatasi masalah ini dengan cara yang lebih kuat. Namun saat ini hingga proyek mendapat pendanaan yang lebih baik, saya tidak bermaksud melakukan upaya serius apa pun untuk mendukung Python versi 3.8 atau 3.9, termasuk bug yang mungkin muncul. Saya membayangkan suatu saat saya mungkin tertarik padanya.
Anda dapat dengan mudah menemukan bug dengan menjalankan pengujian terhadap rangkaian pengujian standar yang digunakan Python untuk memeriksa dirinya sendiri. Pada waktu tertentu, terdapat lusinan permasalahan yang diketahui dan terisolasi dengan baik dan dapat diselesaikan jika seseorang meluangkan waktu untuk menyelesaikannya. Masalahnya adalah tidak banyak orang yang melakukan perbaikan bug.
Beberapa bug di 3.7 dan 3.8 hanyalah masalah melakukan back-porting perbaikan di decompyle3 . Ada sukarelawan?
Anda mungkin menemukan bug yang ingin Anda laporkan. Silakan lakukan ini setelah membaca Cara melaporkan bug dan ikuti instruksi saat membuka terbitan.
Sadarilah bahwa ini mungkin tidak menarik perhatian saya untuk sementara waktu. Jika Anda mensponsori atau mendukung proyek dengan cara tertentu, saya akan memprioritaskan masalah Anda di atas antrean hal lain yang mungkin saya lakukan. Dalam situasi yang jarang terjadi, saya dapat melakukan dekompilasi bytecode secara manual dengan biaya tertentu. Namun jumlah ini sangat besar, biasanya melebihi jumlah yang ingin dibelanjakan kebanyakan orang.
uncompyle6
decompyle3
-- BlackHat 2024 Asia (video). Terima kasih yang sebesar-besarnya kepada Penyelenggara dan Peninjau yang mengizinkan saya berbicara. Hal semacam ini mendorong saya untuk mengerjakan proyek seperti ini.uncompyle6
salah sedangkan hasil uncompyle2
tidak, namun lebih sering uncompyle6 benar ketika uncompyle2 tidak. Karena uncompyle6
lebih mengutamakan akurasi daripada Python idiomatik, uncompyle2
dapat menghasilkan kode yang tampak lebih alami jika kode tersebut benar. Saat ini uncompyle2
dikelola dengan ringan. Lihat pelacak masalahnya untuk lebih jelasnya.