내용물
네이티브 Python 버전 간 디컴파일러 및 조각 디컴파일러입니다. 디컴파일, 언컴파일, 언컴파일2의 후속 버전입니다.
uncompyle6은 Python 바이트코드를 동등한 Python 소스 코드로 다시 변환합니다. 24년 이상의 Python 릴리스에 걸쳐 Python 버전 1.0부터 버전 3.8까지의 바이트코드를 허용합니다. Dropbox의 Python 2.5 바이트코드와 일부 PyPy 바이트코드가 포함되어 있습니다.
좋습니다. 이 소프트웨어는 정말 놀랍습니다. 그것은 일반적인 해키 디컴파일러 그 이상입니다. 프로그램은 컴파일러 기술을 사용하여 명령어로부터 프로그램의 구문 분석 트리를 생성합니다. Python AST에서 나온 것과 약간 유사한 상위 수준의 노드입니다. 따라서 우리는 Python 바이트코드 섹션에서 무슨 일이 일어나고 있는지 실제로 분류하고 이해할 수 있습니다.
이를 토대로 다른 CPython 바이트코드 디컴파일러와 다른 점은 소스 코드 조각 만 분석하고 주어진 바이트코드 오프셋에 대한 소스 코드 정보를 제공하는 기능입니다.
나는 Trepan 디버거 내에서 런타임에 코드 조각을 분석하기 위해 트리 조각을 사용합니다. 이를 위해 바이트코드 오프셋이 기록되고 소스 코드 조각과 연결됩니다. 이 목적은 원래 의도와 일치하지만 아직 약간 다릅니다. 자세한 내용은 여기를 참조하세요.
명령 오프셋이 제공된 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 3.0~3.2를 제외하고 Python 2.4에서 최신 Python 버전까지 실행할 수 있습니다. 자원봉사자는 원할 경우 이러한 결함을 해결하는 것을 환영합니다.
하지만 이를 수행하는 방법은 연속적인 Python 버전을 git 브랜치로 분리하는 것입니다.
PyPy 3-2.4 이상도 작동합니다.
읽을 수 있는 바이트코드 파일은 버전 1.4, 2.1-2.7, 3.0-3.8 및 이후 PyPy 버전의 Python 바이트코드에서 테스트되었습니다.
uncompyle6
이름을 사용하여 PyPI에서 설치할 수 있습니다.
pip 설치 uncompyle6
소스 코드에서 설치하기 위해 이 프로젝트는 setup.py를 사용하므로 표준 Python 루틴을 따릅니다.
$ pip 설치 -e . # 소스 트리에서 실행되도록 설정
또는:
$ python setup.py install # sudo가 필요할 수 있음
GNU Makefile도 제공되므로 make install
(root 또는 sudo로)이 위 단계를 수행합니다.
확인하다
올바른 명령 실행 설정과 가장 빠른 테스트부터 가장 느린 테스트 실행까지 원활하게 수행할 수 있도록 GNU makefile이 추가되었습니다.
리메이크를 설치한 경우 remake --tasks
통해 테스트를 포함한 모든 작업 목록을 볼 수 있습니다.
달리다
$ uncompyle6 *컴파일된-파이썬-파일-pyc-or-pyo*
사용법 도움말:
$ uncompyle6 -h
이전 버전의 Python에서는 바이트코드를 디컴파일한 다음 해당 바이트코드 버전에 대한 Python 인터프리터를 사용하여 컴파일하여 바이트코드를 확인할 수 있었습니다. 이렇게 하면 생성된 바이트코드를 원본 바이트코드와 비교할 수 있습니다. 그러나 Python의 코드 생성이 향상됨에 따라 이는 더 이상 가능하지 않게 되었습니다.
디컴파일 프로세스의 정확성에 대한 Python 구문 확인을 원하는 경우 --syntax-verify
옵션을 추가하세요. 그러나 Python 구문이 변경되므로 바이트코드가 구문을 검사할 Python 인터프리터에 대한 올바른 바이트코드인 경우 이 옵션을 사용해야 합니다.
전체 품질이 향상됨에 따라 특정 바이트 코드를 디컴파일하는 데 때때로 회귀가 발생하므로 결과를 다른 버전의 uncompyle6 과 교차 비교할 수도 있습니다.
Python 3.7 및 3.8의 경우 일반적으로 decompile3의 코드가 더 좋습니다.
또는 uncompyle2, unpyc37 또는 pycdc와 같은 특정 다른 Python 디컴파일러를 사용해 보세요. 나중에 두 가지가 다르게 작동하기 때문에 여기에는 버그가 없는 경우가 많으며 그 반대의 경우도 마찬가지입니다.
쉽게 사용할 수 있는 이러한 프로그램 중 더 강력한 검증을 제공하는 흥미로운 클래스가 있습니다. 즉, 실행 시 스스로 테스트하는 프로그램입니다. 우리의 테스트 스위트에는 다음이 포함됩니다.
그리고 Python에는 다음과 같은 또 다른 프로그램 세트가 함께 제공됩니다. 표준 라이브러리에 대한 테스트 모음입니다. 이런 종류의 검사를 용이하게 하기 위해 test/stdlib
에 일부 코드가 있습니다.
가장 잘 알려져 있고 해결이 가능한(그러나 어려운) 가장 큰 문제는 제어 흐름을 처리하는 것과 관련이 있습니다. (Python에는 아마도 내가 본 것 중 가장 다양하고 까다로운 복합문 세트가 있을 것입니다. 루프와 try 블록에는 많은 프로그래머가 모르는 "else" 절이 있습니다.)
내가 살펴본 모든 Python 디컴파일러에는 Python의 제어 흐름을 디컴파일하는 데 문제가 있습니다. 어떤 경우에는 잘못된 디컴파일을 감지하여 보고할 수 있습니다.
Python 지원은 Python 2에 매우 좋습니다.
Python 버전의 하위 엔드에서는 Python의 분산 테스트를 위한 자동화된 테스트가 없지만 디컴파일이 꽤 좋아 보입니다. 또한 버전 1.6 및 2.0용 Python 인터프리터도 없습니다.
Python 3 시리즈에서 Python 지원은 3.4 또는 3.3 부근에서 가장 강력하며 해당 버전에서 멀어질수록 감소합니다. Python 3.0은 어떤 면에서 3.1이나 2.7보다 2.6과 더 유사하다는 점에서 이상합니다. 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도 있습니다. Dropbox의 이전 Python 2.5 인터프리터를 제외하고 이러한 종류의 작업은 처리되지 않습니다.
또한 PJOrion 또는 기타 난독화된 코드도 처리하지 않습니다. PJOrion의 경우 이 도구를 사용하기 전에 PJOrion Deobfuscator를 사용하여 바이트코드를 해독하여 유효한 바이트코드를 얻으세요. pydecipher가 도움이 될 수 있습니다.
이 프로그램은 Py2EXE로 생성된 Microsoft Windows EXE 파일을 디컴파일할 수 없습니다. 하지만 바이트코드를 올바르게 추출한 후에는 코드를 디컴파일할 수 있습니다. 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
결과는 올바르지 않은 상황이 있지만, uncompyle2가 올바르지 않을 때 uncompyle6이 올바른 경우가 더 많습니다. uncompyle6
관용적인 Python보다 정확성을 고수하기 때문에 uncompyle2
정확할 때 더 자연스럽게 보이는 코드를 생성할 수 있습니다. 현재 uncompyle2
가볍게 유지관리됩니다. 자세한 내용은 문제 추적기를 참조하세요.