Содержание
Собственный декомпилятор кросс-версий Python и декомпилятор фрагментов. Преемник декомпиляции, декомпиляции и декомпиляции2.
uncompyle6 преобразует байт-код Python обратно в эквивалентный исходный код Python. Он принимает байт-коды Python от версии 1.0 до версии 3.8, охватывающие более 24 лет выпуска Python. Мы включаем байт-код Dropbox Python 2.5 и некоторые байт-коды PyPy.
Хорошо, я скажу это: это программное обеспечение потрясающее. Это больше, чем обычный хакерский декомпилятор. Используя технологию компилятора, программа создает дерево разбора программы из инструкций; узлы на верхних уровнях, которые немного похожи на то, что могло бы быть из Python AST. Таким образом, мы действительно можем классифицировать и понять, что происходит в разделах байт-кода Python.
Опираясь на это, еще одна вещь, которая отличает его от других декомпиляторов байт-кода CPython, — это способность разбирать только фрагменты исходного кода и предоставлять информацию об исходном коде вокруг заданного смещения байт-кода.
Я использую фрагменты дерева для разбора фрагментов кода во время выполнения внутри моих трепан-отладчиков. Для этого смещения байт-кода записываются и связываются с фрагментами исходного кода. Эта цель, хотя и совместима с первоначальным замыслом, все же немного отличается. См. это для получения дополнительной информации.
Деанализ фрагмента 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 для этой версии байт-кода. Наконец, в тех случаях, когда программа имеет тест для себя, мы можем запустить проверку декомпилированного кода.
Мы используем автоматизированные процессы для поиска ошибок. В трекерах проблем для других декомпиляторов вы найдете ряд ошибок, которые мы обнаружили в ходе работы. Очень немногие из них не исправлены в других декомпиляторах.
Код в репозитории git можно запускать от Python 2.4 до последней версии Python, за исключением Python 3.0–3.2. Добровольцы могут устранить эти недостатки, если есть желание.
Однако это делается путем разделения последовательных версий Python на ветки git:
PyPy 3-2.4 и более поздние версии также работают.
Файлы байт-кода, которые он может читать, были протестированы на байт-кодах Python версий 1.4, 2.1–2.7 и 3.0–3.8 и более поздних версий PyPy.
Вы можете установить из PyPI, используя имя uncompyle6
:
pip install uncompyle6
Для установки из исходного кода этот проект использует setup.py, поэтому он следует стандартной процедуре Python:
$ pip install -e . # настроен для запуска из дерева исходного кода
или:
$ python setup.py install # может потребоваться sudo
Также предоставляется GNU Makefile, поэтому make install
(возможно, от имени пользователя root или sudo) выполнит описанные выше шаги.
сделать чек
Был добавлен make-файл GNU, позволяющий плавно настраивать запуск правильной команды и запускать тесты от самого быстрого к самому медленному.
Если у вас установлен ремейк, вы можете увидеть список всех задач, включая тесты, через remake --tasks
Бегать
$ uncompyle6 *скомпилированный-python-файл-pyc-or-pyo*
Для помощи в использовании:
$ uncompyle6 -h
В более старых версиях Python можно было проверить байт-код путем декомпиляции байт-кода и последующей компиляции с использованием интерпретатора Python для этой версии байт-кода. Сделав это, полученный байт-код можно будет сравнить с исходным байт-кодом. Однако по мере того, как генерация кода Python становилась лучше, это уже было невозможно.
Если вы хотите проверить синтаксис Python на корректность процесса декомпиляции, добавьте опцию --syntax-verify
. Однако, поскольку синтаксис Python меняется, вам следует использовать эту опцию, если байт-код является правильным байт-кодом для интерпретатора Python, который будет проверять синтаксис.
Вы также можете перекрестно сравнить результаты с другой версией uncompyle6 , поскольку иногда при декомпиляции определенного байт-кода возникают регрессии по мере улучшения общего качества.
Для Python 3.7 и 3.8 код в decompyle3 обычно лучше.
Или попробуйте другой декомпилятор Python, например uncompyle2, unpyc37 или pycdc. Поскольку последние два работают по-разному, ошибок здесь зачастую не в этом, и наоборот.
Существует интересный класс этих программ, которые легко доступны и обеспечивают более строгую проверку: программы, которые при запуске тестируют себя. В наш набор тестов они входят.
В состав Python входит еще один набор подобных программ: набор тестов для стандартной библиотеки. У нас есть некоторый код в test/stdlib
для облегчения такой проверки.
Самая большая известная и, возможно, решаемая (но сложная) проблема связана с обработкой потока управления. (Python, вероятно, имеет самый разнообразный и странный набор составных операторов, который я когда-либо видел; в циклах и блоках try есть предложения «else», о которых, как я подозреваю, многие программисты не знают.)
Все декомпиляторы Python, которые я рассмотрел, имеют проблемы с декомпиляцией потока управления Python. В некоторых случаях мы можем обнаружить ошибочную декомпиляцию и сообщить об этом.
Поддержка Python довольно хороша для Python 2.
В младших версиях Python декомпиляция кажется довольно хорошей, хотя у нас нет автоматического тестирования для распределенных тестов Python. Кроме того, у нас нет интерпретатора Python для версий 1.6 и 2.0.
В серии Python 3 поддержка Python наиболее сильна в районе 3.4 или 3.3 и снижается по мере удаления от этих версий. Python 3.0 странен тем, что в некотором смысле он больше похож на 2.6, чем на 3.1 или 2.7. Python 3.6 кардинально меняет ситуацию, используя словесные коды, а не байтовые коды. В результате поле смещения перехода в аргументе инструкции перехода было уменьшено. Благодаря этому инструкции EXTENDED_ARG
теперь более распространены в инструкциях перехода; раньше они были редкостью. Возможно, чтобы компенсировать дополнительные инструкции EXTENDED_ARG
, была добавлена дополнительная оптимизация перехода. Таким образом, обработка суммы потоком управления специальными средствами, как это делается в настоящее время, хуже.
В версиях Python 3.5, 3.6, 3.7 произошли серьезные изменения в инструкциях MAKE_FUNCTION
и CALL_FUNCTION
.
В Python 3.8 удалены инструкции SETUP_LOOP
, SETUP_EXCEPT
, BREAK_LOOP
и CONTINUE_LOOP
, которые могут затруднить обнаружение потока управления из-за отсутствия запланированного более сложного анализа потока управления. Посмотрим.
В настоящее время поддерживаются не все магические числа Python. В частности, в некоторых версиях Python, особенно в Python 3.6, магическое число менялось несколько раз в пределах версии.
Мы поддерживаем только выпущенные версии, а не версии-кандидаты. Однако обратите внимание, что магия выпущенной версии обычно такая же, как и у последней версии-кандидата перед выпуском.
Существуют также специальные интерпретаторы Python, в частности Dropbox, которые используют свою собственную магию и шифруют байт-код. За исключением старого интерпретатора Python 2.5 Dropbox, подобные вещи не обрабатываются.
Мы также не обрабатываем PJOrion или другой запутанный код. Для PJOrion попробуйте: PJOrion Deobfuscator, чтобы расшифровать байт-код и получить действительный байт-код, прежде чем использовать этот инструмент; pydecipher может помочь в этом.
Эта программа не может декомпилировать EXE-файлы Microsoft Windows, созданные Py2EXE, хотя мы, вероятно, сможем декомпилировать код после того, как вы правильно извлечете байт-код. Pydeinstaller может помочь с распаковкой сборщиков Pyinstaller.
Обработка патологически длинных списков выражений или утверждений происходит медленно. Мы не работаем с Cython или MicroPython, которые не используют байт-код.
При декомпиляции имеется множество ошибок. И это верно для любого другого декомпилятора CPython, с которым я сталкивался, даже для тех, которые утверждали, что они «идеальны» в какой-то конкретной версии, например 2.4.
По мере развития Python декомпиляция также становится сложнее, поскольку компиляция становится более сложной, а сам язык — более сложным. Я подозреваю, что будет меньше специальных попыток, таких как unpyc37 (который основан на декомпиляторе 3.3), просто потому, что это сложнее сделать. Хорошая новость, по крайней мере, с моей точки зрения, заключается в том, что я думаю, что понимаю, что необходимо для более эффективного решения проблем. Но прямо сейчас, пока проект не будет лучше финансироваться, я не собираюсь прилагать какие-либо серьезные усилия для поддержки версий Python 3.8 или 3.9, включая ошибки, которые могут возникнуть. Я думаю, в какой-то момент меня это может заинтересовать.
Вы можете легко найти ошибки, запустив тесты со стандартным набором тестов, который Python использует для самопроверки. В любой момент времени существуют десятки известных проблем, которые довольно хорошо изолированы и могут быть решены, если потратить на это время. Проблема в том, что над исправлением ошибок работает не так много людей.
Некоторые ошибки в версиях 3.7 и 3.8 — это просто вопрос обратного переноса исправлений в decompyle3 . Есть добровольцы?
Вы можете столкнуться с ошибкой, о которой хотите сообщить. Пожалуйста, сделайте это после прочтения статьи «Как сообщить об ошибке» и следуйте инструкциям при открытии проблемы.
Имейте в виду, что какое-то время это может не привлечь моего внимания. Если вы каким-либо образом спонсируете или поддерживаете проект, я буду ставить ваши проблемы выше других дел, которые я мог бы делать вместо этого. В редких ситуациях я могу за определенную плату сделать ручную декомпиляцию байткода. Однако это дорого, обычно превышает то, что большинство людей готовы потратить.
uncompyle6
decompyle3
— BlackHat 2024 Asia (видео). Большое спасибо организаторам и рецензентам за предоставленную мне возможность выступить. Подобные вещи мотивируют меня работать над подобными проектами.uncompyle6
неверны, а результаты uncompyle2
— нет, но чаще всего uncompyle6 является правильным, а uncompyle2 — нет. Поскольку uncompyle6
придерживается большей точности по сравнению с идиоматическим Python, uncompyle2
может создавать более естественный код, если он правильный. В настоящее время uncompyle2
поддерживается незначительно. Более подробную информацию можно найти в системе отслеживания проблем.