
एक क्रॉस-वर्जन पाइथन बाइटकोड डीकंपाइलर
|buildstatus| |Pypi Installs| |Latest Version| |Supported Python Versions|
|packagestatus|
.. contents::
एक मूल Python क्रॉस-वर्जन डीकंपाइलर और फ्रैगमेंट डीकंपाइलर। decompyle, uncompyle, और uncompyle2 का उत्तराधिकारी।
मैंने ब्लैकहैट एशिया 2024 <https://youtu.be/H-7ZNrpsV50?si=nOaixgYHr7RbILVS>_ में इस पर एक व्याख्यान दिया।
uncompyle6 Python बाइटकोड को वापस समकक्ष Python स्रोत कोड में अनुवादित करता है। यह Python संस्करण 1.0 से 3.8 तक के बाइटकोड को स्वीकार करता है, जो Python रिलीज़ के 24 वर्षों से अधिक की अवधि को कवर करता है। हम Dropbox के Python 2.5 बाइटकोड और कुछ PyPy बाइटकोड भी शामिल करते हैं।
ठीक है, मैं कहूँगा: यह सॉफ्टवेयर अद्भुत है। यह आपके सामान्य हैकी डीकंपाइलर से कहीं अधिक है। compiler_ तकनीक का उपयोग करके, प्रोग्राम निर्देशों से प्रोग्राम का एक पार्स ट्री बनाता है; ऊपरी स्तरों पर नोड्स जो थोड़े-बहुत Python AST से आ सकते हैं, ऐसे दिखते हैं। इसलिए हम वास्तव में Python बाइटकोड के अनुभागों में क्या चल रहा है, इसे वर्गीकृत और समझ सकते हैं।
इस पर निर्माण करते हुए, एक और चीज़ जो इसे अन्य CPython बाइटकोड डीकंपाइलरों से अलग बनाती है, वह यह है कि यह स्रोत कोड के केवल टुकड़ों को डीपार्स कर सकता है और किसी दिए गए बाइटकोड ऑफ़सेट के आसपास स्रोत-कोड जानकारी दे सकता है।
मैं ट्री फ्रैगमेंट का उपयोग अपने trepan_ डिबगर्स_ में रन टाइम पर कोड के टुकड़ों को डीपार्स करने के लिए करता हूँ। उसके लिए, बाइटकोड ऑफ़सेट रिकॉर्ड किए जाते हैं और स्रोत कोड के टुकड़ों से जुड़े होते हैं। यह उद्देश्य, मूल आशय के अनुकूल होने के बावजूद, थोड़ा अलग है। अधिक जानकारी के लिए this_ देखें।
एक निर्देश ऑफ़सेट दिए जाने पर Python फ्रैगमेंट डीपार्सिंग, स्टैक ट्रेस दिखाने में उपयोगी है और इसे किसी भी प्रोग्राम में शामिल किया जा सकता है जो रनटाइम पर सिर्फ एक लाइन नंबर से अधिक विस्तार में एक स्थान दिखाना चाहता है। यह कोड तब भी उपयोग किया जा सकता है जब स्रोत कोड जानकारी मौजूद न हो और केवल बाइटकोड हो। फिर से, मेरे डिबगर्स इसका उपयोग करते हैं।
पहले (और अब भी) कई decompyle, uncompyle, uncompyle2, uncompyle3 फोर्क थे। उनमें से कई मूलतः एक ही कोड बेस से आते हैं, और (लगभग?) सभी अब सक्रिय रूप से बनाए नहीं रखे जाते हैं। एक Python 1.5-2.3 को डीकंपाइल करने में वास्तव में अच्छा था, दूसरा Python 2.7 में वास्तव में अच्छा है, लेकिन केवल वही। दूसरा केवल Python 3.2 को संभालता है; दूसरे ने उसे पैच किया और केवल 3.3 को संभाला। आप विचार समझ गए होंगे। यह कोड इन सभी फोर्क्स को एक साथ लाता है और आगे बढ़ता है। इस कोड बेस में उन पुराने फोर्क्स की तुलना में गंभीर रीफैक्टरिंग और सफाई है। decompyle3_ में और भी अधिक प्रयोगात्मक रीफैक्टरिंग चल रही है।
यह स्पष्ट रूप से सभी Python संस्करणों में Python को डीकंपाइल करने में सर्वश्रेष्ठ प्रदर्शन करता है। और भले ही कोई अन्य प्रोजेक्ट हो जो केवल Python संस्करणों के एक उपसमुच्चय के लिए डीकंपाइलेशन प्रदान करता हो, हम आम तौर पर उनके लिए भी स्पष्ट रूप से बेहतर करते हैं।
हम कैसे बता सकते हैं? उस Python संस्करण के साथ वितरित Python बाइटकोड लेकर और उसे डीकंपाइल करके। उन लोगों में से जो सफलतापूर्वक डीकंपाइल करते हैं, हम यह सुनिश्चित कर सकते हैं कि परिणामी प्रोग्राम सिंटैक्टिक रूप से सही हैं, उस बाइटकोड संस्करण के लिए Python इंटरप्रेटर चलाकर। अंत में, ऐसे मामलों में जहाँ प्रोग्राम में स्वयं के लिए एक परीक्षण है, हम डीकंपाइल कोड पर जाँच चला सकते हैं।
हम बग खोजने के लिए स्वचालित प्रक्रियाओं का उपयोग करते हैं। अन्य डीकंपाइलरों के इश्यू ट्रैकर्स में, आपको रास्ते में हमारे द्वारा पाए गए कई बग मिलेंगे। उनमें से बहुत कम अन्य डीकंपाइलरों में ठीक किए गए हैं।
गिट रिपॉजिटरी में कोड Python 2.4 से नवीनतम Python संस्करण तक चलाया जा सकता है, Python 3.0 से 3.2 को छोड़कर। यदि ऐसा करने की इच्छा है, तो स्वयंसेवकों का स्वागत है जो इन कमियों को दूर करें।
हालाँकि, यह ऐसा करने का तरीका लगातार Python संस्करणों को गिट ब्रांचों में अलग करके है:
master Python 3.11 और उससे ऊपर (poetry install और नए Python मुहावरों का उपयोग करता है) python-3.6-to-3.10 Python 3.6 से 3.10 (नए f-strings, अधिक आधुनिक मुहावरे, और अधिक आधुनिक Type annotations का उपयोग करता है) python-3.3-to-3.5 Python 3.3 से 3.5 (सामान्य Python 3) python-3.0-to-3.2 Python 3.0 से 3.2 (प्रारंभिक Python 3; 3.0 कुछ क्षेत्रों में Python 2.6 के करीब था, Python 2.7 से अधिक) python-2.4-to-2.7 Python 2.4 से 2.7 (सामान्य Python 2)
PyPy संस्करण 2.4 से ऊपर भी काम करता है।
यह जो बाइटकोड फ़ाइलें पढ़ सकता है, उनका परीक्षण Python बाइटकोड पर संस्करण 1.4, 2.1-2.7, और 3.0-3.8 और बाद के PyPy संस्करणों से किया गया है।
हाल के Python रिलीज़ (Python 3.11+) के लिए, आप PyPI से uncompyle6 नाम का उपयोग करके स्थापित कर सकते हैं::
pip install uncompyle6
Python 3.11 से पहले के रिलीज़ के लिए, PyPI का उपयोग करके स्थापित न करें, बल्कि GitHub Releases section में एक फ़ाइल का उपयोग करके स्थापित करें। पुराने Python में easy_install <https://python101.pythonlibrary.org/chapter29_pip.html#using-easy-install>_ का उपयोग होता था। लेकिन यह अब PyPi या नए Python संस्करणों पर समर्थित नहीं है। और इसके विपरीत, poetry या pip, (नए तरीके) पुराने Python पर समर्थित नहीं हैं।
यदि आप जिस Python संस्करण पर uncompyle6 चला रहे हैं, वह Python 2.4 से 2.7 के बीच है, तो uncompyle6_24-x.y.z.tar.gz नामक टारबॉल का उपयोग करें।
यदि आप जिस Python संस्करण पर uncompyle6 चला रहे हैं, वह Python 3.0 से 3.2 के बीच है, तो uncompyle6_30-x.y.z.tar.gz नामक टारबॉल का उपयोग करें।
यदि आप जिस Python संस्करण पर uncompyle6 चला रहे हैं, वह Python 3.3 से 3.5 के बीच है, तो uncompyle6_33-x.y.z.tar.gz नामक टारबॉल का उपयोग करें।
यदि आप जिस Python संस्करण पर uncompyle6 चला रहे हैं, वह Python 3.6 से 3.11 के बीच है, तो uncompyle6_36-x.y.z.tar.gz नामक टारबॉल का उपयोग करें।
यदि आप जिस Python संस्करण पर uncompyle6 चला रहे हैं, वह 3.11 या बाद का है, तो uncompyle6-x.y.z.tar.gz नामक टारबॉल का उपयोग करें।
आप अंडे या व्हील भी आज़मा सकते हैं जिनका समान संस्करण पदनाम है, उदाहरण के लिए, Python 3.9 स्थापना के लिए uncompyle6-x.y.z-py39-none-any.whl। *हालाँकि, ध्यान दें कि पदनाम के बिना संस्करण का अर्थ है Python 3.11 या उससे अधिक।
इसी प्रकार, बिना _xx वाला टारबॉल केवल Python 3.11 या उससे अधिक पर काम करता है।
गिट ब्रांच का उपयोग करने का तर्क ++++++++++++++++++++++++++++++++
वर्तमान में एक Python स्रोत कोड होना संभव नहीं है (यदि अव्यावहारिक नहीं है) जो इतनी जटिलता और इतनी सुविधाओं के साथ Python 2.7 और Python 3.13+ दोनों पर चल सके। भाषाएँ इतनी अलग हो गई हैं, और पैकेजिंग बहुत अलग है। वास्तव में, Python 3.11+ के लिए पैकेजिंग प्रथा Python 2.7 (और उससे पहले Python 2.4 तक) के साथ असंगत है, जो "easy_install" का पक्षधर था।
स्रोत पाठ से स्थापना ++++++++++++++++++++++
स्रोत कोड से स्थापित करने के लिए, सुनिश्चित करें कि आपके पास सही गिट शाखा है। गिट शाखा नामों के लिए आवश्यकताएँ अनुभाग देखें।
सही शाखा सेट करने के बाद::
$ pip install -e . # स्रोत ट्री से चलाने के लिए सेट करें
एक GNU Makefile भी प्रदान किया गया है, इसलिए :code:make install (संभवतः रूट या sudo के रूप में) उपरोक्त चरणों को करेगा।
::
make check
एक GNU makefile को सही कमांड सेट अप करने और चलाने, और परीक्षणों को सबसे तेज़ से सबसे धीमी गति से चलाने के लिए जोड़ा गया है।
यदि आपके पास remake_ स्थापित है, तो आप :code:remake --tasks के माध्यम से परीक्षणों सहित सभी कार्यों की सूची देख सकते हैं।
चलाएँ
::
$ uncompyle6 compiled-python-file-pyc-or-pyo
उपयोग सहायता के लिए:
::
$ uncompyle6 -h
Python के पुराने संस्करणों में, बाइटकोड को डीकंपाइल करके और फिर उस बाइटकोड संस्करण के लिए Python इंटरप्रेटर का उपयोग करके संकलित करके सत्यापित करना संभव था। ऐसा करने के बाद, उत्पादित बाइटकोड की तुलना मूल बाइटकोड से की जा सकती थी। हालाँकि, जैसे-जैसे Python का कोड जनरेशन बेहतर होता गया, यह अब संभव नहीं रहा।
यदि आप डीकंपाइलेशन प्रक्रिया की शुद्धता का Python सिंटैक्स सत्यापन चाहते हैं, तो :code:--syntax-verify विकल्प जोड़ें। हालाँकि, चूंकि Python सिंटैक्स बदलता है। आपको इस विकल्प का उपयोग करना चाहिए यदि बाइटकोड उस Python इंटरप्रेटर के लिए सही बाइटकोड है जो सिंटैक्स की जाँच करेगा।
आप परिणामों की तुलना uncompyle6 के किसी अन्य संस्करण से भी कर सकते हैं, क्योंकि कभी-कभी विशिष्ट बाइटकोड को डीकंपाइल करने में नियमन होते हैं, क्योंकि समग्र गुणवत्ता में सुधार होता है।
Python 3.7 और 3.8 के लिए, decompyle3_ में कोड आम तौर पर बेहतर है।
या किसी अन्य विशिष्ट Python डीकंपाइलर जैसे uncompyle2_, unpyc37_, या pycdc_ आज़माएँ। चूंकि बाद वाले दो अलग तरीके से काम करते हैं, यहाँ के बग अक्सर उनमें नहीं होते, और इसके विपरीत।
इन प्रोग्रामों का एक दिलचस्प वर्ग है जो आसानी से उपलब्ध है ताकि मजबूत सत्यापन दिया जा सके: वे प्रोग्राम जो चलने पर स्वयं का परीक्षण करते हैं। हमारा परीक्षण सूट इन्हें शामिल करता है।
और Python इस तरह के प्रोग्रामों का एक और सेट लेकर आता है: मानक पुस्तकालय के लिए इसका परीक्षण सूट। हमारे पास इस प्रकार की जाँच की सुविधा के लिए :code:test/stdlib में कुछ कोड है।
सबसे बड़ी ज्ञात और संभवतः सुधार योग्य (लेकिन कठिन) समस्या नियंत्रण प्रवाह को संभालने से संबंधित है। (Python में शायद सबसे विविध और पेचीदा सेट है जो मैंने कभी देखा है; लूप और try ब्लॉक पर "else" क्लॉज हैं जिनके बारे में मुझे संदेह है कि कई प्रोग्रामर नहीं जानते हैं।)
सभी Python डीकंपाइलर जिन्हें मैंने देखा है, उन्हें Python के नियंत्रण प्रवाह को डीकंपाइल करने में समस्याएँ हैं। कुछ मामलों में, हम एक गलत डीकंपाइलेशन का पता लगा सकते हैं और इसकी रिपोर्ट कर सकते हैं।
Python 2 के लिए Python समर्थन काफी अच्छा है।
Python संस्करणों के निचले छोर पर, डीकंपाइलेशन काफी अच्छा लगता है, हालाँकि हमारे पास Python के वितरित परीक्षणों के लिए कोई स्वचालित परीक्षण नहीं है। साथ ही, हमारे पास संस्करण 1.6 और 2.0 के लिए Python इंटरप्रेटर नहीं है।
Python 3 श्रृंखला में, Python समर्थन 3.4 या 3.3 के आसपास सबसे मजबूत है और जैसे-जैसे आप इन संस्करणों से दूर जाते हैं, गिरता जाता है। Python 3.0 अजीब है क्योंकि यह कुछ मायनों में 2.6 जैसा दिखता है, 3.1 या 2.7 से अधिक। Python 3.6 चीजों को मौलिक रूप से बदलता है, बाइट कोड के बजाय शब्द कोड का उपयोग करके। नतीजतन, एक जंप इंस्ट्रक्शन आर्गुमेंट में जंप ऑफ़सेट फ़ील्ड कम हो गया है। इससे :code:EXTENDED_ARG निर्देश अब जंप निर्देशों में अधिक प्रचलित हो गए हैं; पहले वे दुर्लभ थे। शायद अतिरिक्त :code:EXTENDED_ARG निर्देशों की भरपाई के लिए, अतिरिक्त जंप ऑप्टिमाइज़ेशन जोड़ा गया है। तो संक्षेप में, नियंत्रण प्रवाह को तदर्थ साधनों द्वारा संभालना, जैसा कि वर्तमान में किया जाता है, बदतर है।
Python 3.5, 3.6, और 3.7 के बीच, :code:MAKE_FUNCTION और :code:CALL_FUNCTION निर्देशों में बड़े बदलाव हुए हैं।
Python 3.8 :code:SETUP_LOOP, :code:SETUP_EXCEPT, :code:BREAK_LOOP, और :code:CONTINUE_LOOP निर्देशों को हटा देता है, जो नियंत्रण-प्रवाह का पता लगाना और अधिक कठिन बना सकता है, क्योंकि अधिक परिष्कृत नियंत्रण-प्रवाह विश्लेषण का अभाव है जिसकी योजना बनाई गई है। हम देखेंगे।
वर्तमान में, सभी Python मैजिक नंबर समर्थित नहीं हैं। विशेष रूप से Python के कुछ संस्करणों में, विशेष रूप से Python 3.6, मैजिक नंबर एक संस्करण के भीतर कई बार बदल चुका है।
हम केवल जारी किए गए संस्करणों का समर्थन करते हैं, उम्मीदवार संस्करणों का नहीं। ध्यान दें, हालाँकि, जारी किए गए संस्करण का जादू आमतौर पर रिलीज़ से पहले अंतिम उम्मीदवार संस्करण के समान होता है।
अनुकूलित Python इंटरप्रेटर भी हैं, विशेष रूप से Dropbox, जो अपने स्वयं के मैजिक का उपयोग करते हैं और बाइटकोड को एन्क्रिप्ट करते हैं। Dropbox के पुराने Python 2.5 इंटरप्रेटर को छोड़कर, इस प्रकार की चीज़ को संभाला नहीं जाता है।
हम PJOrion_ या अन्यथा अस्पष्ट कोड को भी नहीं संभालते हैं। PJOrion के लिए प्रयास करें: इस टूल को आज़माने से पहले वैध बाइटकोड प्राप्त करने के लिए बाइटकोड को अनस्क्रैम्बल करने के लिए PJOrion Deobfuscator_; pydecipher_ उसमें मदद कर सकता है।
यह प्रोग्राम Py2EXE_ द्वारा बनाई गई Microsoft Windows EXE फ़ाइलों को डीकंपाइल नहीं कर सकता है, हालाँकि हम संभवतः बाइटकोड को ठीक से निकालने के बाद कोड को डीकंपाइल कर सकते हैं। Pydeinstaller <https://github.com/charles-dyfis-net/pydeinstaller>_ Pyinstaller बंडलरों को अनपैक करने में मदद कर सकता है।
पैथोलॉजिकल रूप से लंबी अभिव्यक्तियों या कथनों की सूचियों को संभालना धीमा है। हम Cython_ या MicroPython को नहीं संभालते हैं, जो बाइटकोड का उपयोग नहीं करते हैं।
डीकंपाइलेशन में कई बग हैं। और यह उन सभी अन्य CPython डीकंपाइलरों के लिए सच है जिनका मैंने सामना किया है, यहां तक कि वे भी जिन्होंने किसी विशेष संस्करण जैसे 2.4 पर "पूर्ण" होने का दावा किया है।
जैसे-जैसे Python आगे बढ़ता है, डीकंपाइलेशन भी कठिन होता जाता है क्योंकि संकलन अधिक परिष्कृत होता है और भाषा स्वयं अधिक परिष्कृत होती है। मुझे संदेह है कि unpyc37_ (जो 3.3 डीकंपाइलर पर आधारित है) जैसे कम तदर्थ प्रयास होंगे, क्योंकि ऐसा करना कठिन है। अच्छी खबर, कम से कम मेरे दृष्टिकोण से, यह है कि मुझे लगता है कि मैं समझता हूँ कि समस्याओं को अधिक मजबूती से हल करने के लिए क्या आवश्यक है। लेकिन अभी, जब तक परियोजना को बेहतर वित्त पोषित नहीं किया जाता, मैं Python संस्करण 3.8 या 3.9 का समर्थन करने के लिए कोई गंभीर प्रयास करने का इरादा नहीं रखता, जिसमें आने वाले बग भी शामिल हैं। मैं कल्पना करता हूँ कि किसी बिंदु पर मुझे इसमें रुचि हो सकती है।
आप मानक परीक्षण सूट के विरुद्ध परीक्षण चलाकर आसानी से बग पा सकते हैं जिसका उपयोग Python स्वयं की जाँच के लिए करता है। किसी भी समय, दर्जनों ज्ञात समस्याएँ होती हैं जो काफी अच्छी तरह से अलग-थलग हैं और जिन्हें हल किया जा सकता है यदि कोई ऐसा करने में समय लगाए। समस्या यह है कि बग फिक्स करने पर काम करने वाले बहुत से लोग नहीं हैं।
3.7 और 3.8 में कुछ बग केवल decompyle3 में सुधारों को बैक-पोर्ट करने का मामला है। कोई स्वयंसेवक?
आप एक ऐसे बग पर आ सकते हैं जिसे आप रिपोर्ट करना चाहते हैं। कृपया How to report a bug <https://github.com/rocky/python-uncompyle6/blob/master/HOW-TO-REPORT-A-BUG.md>_ पढ़ने के बाद ऐसा करें और issue खोलते समय निर्देशों <https://github.com/rocky/python-uncompyle6/issues/new?assignees=&labels=&template=bug-report.md>_ का पालन करें।
ध्यान रखें कि हो सकता है कि यह कुछ समय के लिए मेरा ध्यान आकर्षित न करे। यदि आप परियोजना को किसी तरह से प्रायोजित या समर्थन करते हैं, तो मैं आपके मुद्दों को उन अन्य चीजों की कतार में प्राथमिकता दूंगा जो मैं इसके बजाय कर सकता हूँ। दुर्लभ परिस्थितियों में, मैं शुल्क के लिए बाइटकोड का हाथ से डीकंपाइलेशन कर सकता हूँ। हालाँकि, यह महंगा है, आमतौर पर उससे अधिक जो अधिकांश लोग खर्च करने को तैयार हैं।
uncompyle6 decompyle3 -- BlackHat 2024 Asia (video <https://www.youtube.com/watch?v=NA77SFncppE>_). आयोजकों और समीक्षकों को बहुत-बहुत धन्यवाद कि मुझे बोलने दिया। इस तरह की चीज़ मुझे इस तरह की परियोजनाओं पर काम करने के लिए प्रोत्साहित करती है।uncompyle6 परिणाम गलत हैं, जबकि :code:uncompyle2 परिणाम सही हैं, लेकिन अक्सर uncompyle6 सही होता है जब uncompyle2 नहीं होता। क्योंकि :code:uncompyle6 सटीकता को मुहावरेदार Python पर वरीयता देता है, :code:uncompyle2 सही होने पर अधिक प्राकृतिक दिखने वाला कोड उत्पन्न कर सकता है। वर्तमान में :code: हल्के से बनाए रखा जाता है। अधिक विवरण के लिए इसका इश्यू _ देखें।.. _Cython: https://en.wikipedia.org/wiki/Cython .. _trepan: https://pypi.python.org/pypi/trepan3k .. _compiler: https://github.com/rocky/python-uncompyle6/wiki/How-does-this-code-work%3F .. _HISTORY: https://github.com/rocky/python-uncompyle6/blob/master/HISTORY.md .. _report_bug: https://github.com/rocky/python-uncompyle6/blob/master/HOW-TO-REPORT-A-BUG.md .. _debuggers: https://pypi.python.org/pypi/trepan3k .. _remake: https://bashdb.sf.net/remake .. _pycdc: https://github.com/zrax/pycdc .. _decompyle3: https://github.com/rocky/python-decompile3 .. _uncompyle2: https://github.com/wibiti/uncompyle2 .. _unpyc37: https://github.com/andrew-tavera/unpyc37 .. _this: https://github.com/rocky/python-uncompyle6/wiki/Deparsing-technology-and-its-use-in-exact-location-reporting .. |buildstatus| image:: https://circleci.com/gh/rocky/python-uncompyle6.svg?style=svg :target: https://app.circleci.com/pipelines/github/rocky/python-uncompyle6 .. |packagestatus| image:: https://repology.org/badge/vertical-allrepos/python:uncompyle6.svg :target: https://repology.org/project/python:uncompyle6/versions .. _PJOrion: http://www.koreanrandom.com/forum/topic/15280-pjorion-%D1%80%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%BE%D0%B1%D1%84 .. _pydecipher: .. _Deobfuscator: .. _Py2EXE: .. |Supported Python Versions| image:: .. |Latest Version| image:: :target: .. |Pypi Installs| image::
uncompyle2ट्रैकर <https://github.com/wibiti/uncompyle2/issues>How to report a bug <https://github.com/rocky/python-uncompyle6/blob/master/HOW-TO-REPORT-A-BUG.md>_इश्यू ट्रैकर <https://github.com/zrax/pycdc/issues>_ देखें। वर्तमान में हल्के से बनाए रखा जाता है।