
Python 디컴파일러 (3.7-3.8 지원) — uncompyle6에서 축소하여 리팩토링 및 오래된 문제 해결을 시작할 수 있도록 함
|buildstatus| |Pypi Installs| |Latest Version| |Supported Python Versions|
|packagestatus|
.. contents::
네이티브 Python 크로스-버전 디컴파일러 및 조각 디컴파일러입니다. uncompyle6_ 을 재구성한 것입니다.
이에 대해 블랙햇 아시아 2024 <https://youtu.be/H-7ZNrpsV50?si=nOaixgYHr7RbILVS>_ 에서 발표했습니다.
decompyle3 는 Python 바이트코드를 다시 동등한 Python 소스 코드로 변환합니다. Python 3.7 이상의 바이트코드를 지원합니다.
이전 Python 바이트코드의 디컴파일은 uncompyle6_ 을 참조하세요.
Uncompyle6은 훌륭하지만, 제어 흐름 처리 방식에 근본적인 문제가 있습니다. Python 초기에는 최적화가 거의 없고 코드가 매우 템플릿 방식으로 생성되었기 때문에, 제어 흐름 구조를 파악하는 것이 단순히 코드 패턴을 살펴보는 것만으로 가능했습니다.
시간이 지나면서, 특히 점프 처리를 중심으로 한 코드 최적화가 증가하면서 코드 패턴만으로 제어 흐름을 감지하는 것을 지원하기가 더 어려워졌습니다. 이 문제는 이미 Python 2.4 (2004) 시절부터 인지되었지만, 이는 어려운 문제이기 때문에 지금까지 만족스러운 방식으로 해결되지 못했습니다.
이 문제를 해결하기 위한 초기 시도는 명령어 스트림에 마커를 추가하는 것이었습니다. 처음에는 COME_FROM 명령어를 추가하고 패턴 감지에 사용했습니다.
시간이 지나면서 이를 더 구체화하여 COME_FROM_LOOP 와 COME_FROM_WITH 를 추가했습니다. 그리고 문법 축소 시간에 점프가 예상되는 COME_FROM 대상과 일치하는지 확인하는 검사를 추가했습니다.
그러나 이 모든 것은 복잡하고 견고하지 않으며, 디파싱 속도를 크게 저하시켰고 실제로 지속 가능하지 않습니다.
이 프로젝트에서는 문법을 재작성하고 리팩토링하기 시작했습니다.
하지만 이것만으로는 충분하지 않습니다. 제어 흐름은 지배자(dominator)와 역지배자(reverse-dominator)를 사용하여 처리해야 하며, 이는 python-control-flow_ 프로젝트에서 제공할 수 있습니다.
이 작업을 저는 드디어 또 다른 비공개 프로젝트에서 천천히 진행하고 있습니다. 많은 작업이 필요합니다. 후원 형태의 자금 지원은 많은 도움이 되지만 노력의 양에 비례하지 않으며, 현재 저는 풀타임 직장이 있습니다. 따라서 공개적으로 사용 가능해지기까지 시간이 걸릴 수 있으며, 아예 공개되지 않을 수도 있습니다.
여기의 코드는 Python 3.7 또는 3.8에서 실행할 수 있습니다. 읽을 수 있는 바이트코드 파일은 Python 3.7 및 3.8 버전의 바이트코드에서 테스트되었습니다.
PyPI에서 decompyle3 이름으로 설치할 수 있습니다::
pip install decompyle3
소스 코드에서 설치하려면 이 프로젝트는 setup.py를 사용하므로 표준 Python 절차를 따릅니다::
$ pip install -e . # 소스 트리에서 실행할 수 있도록 설정
또는::
$ python setup.py install # sudo가 필요할 수 있음
GNU Makefile도 제공되므로 :code:make install (필요시 root 또는 sudo로) 위 단계를 수행합니다.
::
make check
올바른 명령을 설정하고 실행하며, 가장 빠른 테스트부터 느린 테스트 순으로 실행할 수 있도록 GNU makefile이 추가되었습니다.
remake_ 가 설치되어 있다면 :code:remake --tasks 를 통해 테스트를 포함한 모든 작업 목록을 볼 수 있습니다.
실행
::
$ decompyle3 compiled-python-file-pyc-or-pyo
사용법 도움말:
::
$ decompyle3 -h
디컴파일 과정의 정확성에 대한 Python 구문 검증을 원한다면 :code:--syntax-verify 옵션을 추가하세요. 다만 Python 구문은 변경됩니다. 바이트코드가 구문을 검사할 Python 인터프리터에 맞는 올바른 바이트코드인 경우에만 이 옵션을 사용해야 합니다.
또한 unpyc37_ 과 같은 다른 Python 디컴파일러와 결과를 교차 비교할 수 있습니다. 두 도구는 작동 방식이 다르므로, 여기서 발견된 버그는 저쪽에 없는 경우가 많고 그 반대도 마찬가지입니다.
더 강력한 검증을 제공할 수 있는 흥미로운 프로그램 부류가 있습니다: 실행될 때 스스로를 테스트하는 프로그램들입니다. 우리의 테스트 스위트에는 이러한 프로그램들이 포함되어 있습니다.
그리고 Python에는 이와 같은 또 다른 프로그램 세트, 즉 표준 라이브러리용 테스트 스위트가 있습니다. 이러한 검사를 용이하게 하기 위해 :code:test/stdlib 에 일부 코드를 마련했습니다.
우리는 릴리스 버전만 지원하며, 후보 버전은 지원하지 않습니다. 하지만 릴리스 버전의 매직 넘버는 일반적으로 릴리스 직전의 마지막 후보 버전과 동일합니다.
또한 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이 자체 검사에 사용하는 표준 테스트 스위트에 대해 테스트를 실행하면 버그를 쉽게 찾을 수 있습니다. 특정 시점에는 매우 잘 격리되어 있고 시간을 투자하면 해결할 수 있는 수십 개의 알려진 문제가 있습니다. 문제는 버그 수정에 참여하는 사람이 그리 많지 않다는 것입니다.
버그를 발견하여 보고하고 싶을 수 있습니다. 그렇게 해주세요. 하지만 제가 주목하기까지 시간이 걸릴 수 있음을 인지하십시오. 프로젝트를 어떤 방식으로든 후원하거나 지원한다면, 제가 대신 하고 있을 다른 일들보다 귀하의 이슈를 우선 처리하겠습니다. 드문 경우지만 수동 바이트코드 디컴파일을 유료로 수행할 수 있습니다. 그러나 이는 비용이 많이 들며, 대부분의 사람들이 지불할 의사가 있는 수준을 넘는 경우가 많습니다.
uncompyle 및 decompyle 프로그램과 동일한 문제를 겪습니다... |buildstatus| image:: https://dl.circleci.com/status-badge/img/gh/rocky/python-decompile3/tree/master.svg?style=svg :target: https://dl.circleci.com/status-badge/redirect/gh/rocky/python-decompile3/tree/master .. |packagestatus| image:: https://repology.org/badge/vertical-allrepos/python:uncompyle6.svg :target: https://repology.org/project/python:decompyle3/versions .. _Cython: https://en.wikipedia.org/wiki/Cython .. _MicroPython: https://micropython.org .. _uncompyle6: https://pypi.python.org/pypi/uncompyle6 .. _python-control-flow: https://github.com/rocky/python-control-flow .. _trepan: https://pypi.python.org/pypi/trepan3k .. _compiler: https://pypi.python.org/pypi/spark_parser .. _HISTORY: https://github.com/rocky/python-decompile3/blob/master/HISTORY.md .. _debuggers: https://pypi.python.org/pypi/trepan3k .. _remake: https://bashdb.sf.net/remake .. _unpyc37: https://github.com/andrew-tavera/unpyc37/ .. _this: https://github.com/rocky/python-decompile3/wiki/Deparsing-technology-and-its-use-in-exact-location-reporting .. |TravisCI| image:: https://travis-ci.org/rocky/python-decompile3.svg :target: https://travis-ci.org/rocky/python-decompile3 .. |CircleCI| image:: https://circleci.com/gh/rocky/python-decompile3.svg?style=svg :target:
.. _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 .. _Deobfuscator: https://github.com/extremecoders-re/PjOrion-Deobfuscator .. _Py2EXE: https://en.wikipedia.org/wiki/Py2exe .. |Supported Python Versions| image:: https://img.shields.io/pypi/pyversions/decompyle3.svg .. |Latest Version| image:: https://badge.fury.io/py/decompyle3.svg :target: https://badge.fury.io/py/decompyle3 .. |PyPI Installs| image:: https://pepy.tech/badge/decompyle3/month .. _pydecipher: https://github.com/mitre/pydecipher