Conteúdo
Um descompilador de versão cruzada e descompilador de fragmentos nativo do Python. O sucessor de descompilar, descompilar e descompilar2.
uncompyle6 traduz o bytecode Python de volta em código-fonte Python equivalente. Ele aceita bytecodes do Python versão 1.0 até a versão 3.8, abrangendo mais de 24 anos de lançamentos do Python. Incluímos o bytecode Python 2.5 do Dropbox e alguns bytecodes PyPy.
Ok, vou dizer: este software é incrível. É mais do que um descompilador hacky normal. Usando tecnologia de compilador, o programa cria uma árvore de análise do programa a partir das instruções; nós nos níveis superiores que se parecem um pouco com o que pode vir de um AST Python. Assim, podemos realmente classificar e entender o que está acontecendo nas seções do bytecode Python.
Com base nisso, outra coisa que o torna diferente de outros descompiladores de bytecode CPython é a capacidade de analisar apenas fragmentos de código-fonte e fornecer informações do código-fonte em torno de um determinado deslocamento de bytecode.
Eu uso os fragmentos de árvore para analisar fragmentos de código em tempo de execução dentro de meus depuradores trepan. Para isso, os deslocamentos de bytecode são registrados e associados a fragmentos do código-fonte. Este propósito, embora compatível com a intenção original, é ainda um pouco diferente. Veja isto para obter mais informações.
A análise de fragmentos Python dado um deslocamento de instrução é útil para mostrar rastreamentos de pilha e pode ser incorporada a qualquer programa que queira mostrar um local com mais detalhes do que apenas um número de linha em tempo de execução. Este código também pode ser usado quando não existe informação de código-fonte e há apenas bytecode. Novamente, meus depuradores fazem uso disso.
Havia (e ainda há) vários garfos decompyle, uncompyle, uncompyle2, uncompyle3 por aí. Muitos deles vêm basicamente da mesma base de código e (quase?) todos eles não são mais mantidos ativamente. Um era muito bom em descompilar Python 1.5-2.3, outro era muito bom em Python 2.7, mas só isso. Outro lida apenas com Python 3.2; outro corrigiu isso e tratou apenas do 3.3. Você entendeu. Este código reúne todas essas bifurcações e avança . Há algumas refatorações e limpezas sérias nesta base de código em relação às bifurcações antigas. Ainda mais refatorações experimentais estão acontecendo no decompyle3.
Isso comprovadamente é o melhor na descompilação do Python em todas as versões do Python. E mesmo quando há outro projeto que fornece apenas descompilação para um subconjunto de versões do Python, geralmente nos saímos comprovadamente melhor para eles também.
Como podemos saber? Pegando o bytecode Python que vem distribuído com essa versão do Python e descompilando-os. Entre aqueles que são descompilados com sucesso, podemos garantir que os programas resultantes estejam sintaticamente corretos executando o interpretador Python para essa versão de bytecode. Por fim, nos casos em que o programa possui um teste próprio, podemos executar a verificação no código descompilado.
Usamos processos automatizados para encontrar bugs. Nos rastreadores de problemas de outros descompiladores, você encontrará vários bugs que encontramos ao longo do caminho. Muito poucos ou nenhum deles são corrigidos nos outros descompiladores.
O código no repositório git pode ser executado do Python 2.4 até a versão mais recente do Python, com exceção do Python 3.0 a 3.2. Voluntários são bem-vindos para resolver essas deficiências se desejarem fazê-lo.
A maneira como isso é feito é segregando versões consecutivas do Python em ramificações git:
PyPy 3-2.4 e posterior também funcionam.
Os arquivos de bytecode que ele pode ler foram testados em bytecodes Python das versões 1.4, 2.1-2.7 e 3.0-3.8 e versões posteriores do PyPy.
Você pode instalar a partir do PyPI usando o nome uncompyle6
:
pip instalar descompile6
Para instalar a partir do código-fonte, este projeto usa setup.py, portanto segue a rotina padrão do Python:
$ pip instalar -e. # configurado para rodar a partir da árvore de origem
ou:
$ python setup.py install # pode precisar do sudo
Um Makefile GNU também é fornecido, então make install
(possivelmente como root ou sudo) executará os passos acima.
fazer verificação
Um makefile GNU foi adicionado para facilitar a configuração da execução do comando correto e da execução de testes do mais rápido ao mais lento.
Se você tiver o remake instalado, poderá ver a lista de todas as tarefas, incluindo testes, via remake --tasks
Correr
$ uncompyle6 *arquivo-python-compilado-pyc-ou-pyo*
Para ajuda de uso:
$ descompilar6 -h
Em versões mais antigas do Python era possível verificar o bytecode descompilando o bytecode e depois compilando usando o interpretador Python para essa versão do bytecode. Feito isso, o bytecode produzido poderia ser comparado com o bytecode original. No entanto, à medida que a geração de código do Python melhorou, isso não era mais viável.
Se você deseja a verificação da sintaxe Python da exatidão do processo de descompilação, adicione a opção --syntax-verify
. No entanto, como a sintaxe do Python muda, você deve usar esta opção se o bytecode for o bytecode correto para o interpretador Python que verificará a sintaxe.
Você também pode comparar os resultados com outra versão do uncompyle6 , pois às vezes há regressões na descompilação de bytecode específico à medida que a qualidade geral melhora.
Para Python 3.7 e 3.8, o código em decompyle3 geralmente é melhor.
Ou tente outro descompilador python específico, como uncompyle2, unpyc37 ou pycdc. Como os dois últimos funcionam de maneira diferente, os bugs aqui geralmente não estão presentes e vice-versa.
Há uma classe interessante desses programas que está prontamente disponível e oferece uma verificação mais forte: aqueles programas que, quando executados, testam a si mesmos. Nosso conjunto de testes inclui isso.
E o Python vem com outro conjunto de programas como este: seu conjunto de testes para a biblioteca padrão. Temos algum código em test/stdlib
para facilitar esse tipo de verificação também.
O maior problema conhecido e possivelmente corrigível (mas difícil) tem a ver com o manuseio do fluxo de controle. (Python tem provavelmente o conjunto mais diversificado e complicado de instruções compostas que já vi; existem cláusulas "else" em loops e blocos try que suspeito que muitos programadores não conhecem.)
Todos os descompiladores Python que examinei têm problemas ao descompilar o fluxo de controle do Python. Em alguns casos podemos detectar uma descompilação errada e reportá-la.
O suporte Python é muito bom para Python 2
Na extremidade inferior das versões do Python, a descompilação parece muito boa, embora não tenhamos nenhum teste automatizado para os testes distribuídos do Python. Além disso, não temos um interpretador Python para as versões 1.6 e 2.0.
Na série Python 3, o suporte ao Python é mais forte em torno de 3.4 ou 3.3 e diminui à medida que você se afasta dessas versões. O Python 3.0 é estranho porque, em alguns aspectos, se assemelha mais ao 2.6 do que ao 3.1 ou 2.7. O Python 3.6 muda drasticamente as coisas usando códigos de palavras em vez de códigos de bytes. Como resultado, o campo de deslocamento de salto em um argumento de instrução de salto foi reduzido. Isso faz com que as instruções EXTENDED_ARG
sejam agora mais predominantes nas instruções de salto; anteriormente eles eram raros. Talvez para compensar as instruções EXTENDED_ARG
adicionais, uma otimização de salto adicional tenha sido adicionada. Portanto, em suma, lidar com o fluxo de controle por meios ad hoc, como é feito atualmente, é pior.
Entre Python 3.5, 3.6, 3.7, houve grandes mudanças nas instruções MAKE_FUNCTION
e CALL_FUNCTION
.
Python 3.8 remove SETUP_LOOP
, SETUP_EXCEPT
, BREAK_LOOP
e CONTINUE_LOOP
, instruções que podem dificultar a detecção do fluxo de controle, sem a análise de fluxo de controle mais sofisticada planejada. Veremos.
Atualmente nem todos os números mágicos do Python são suportados. Especificamente em algumas versões do Python, principalmente no Python 3.6, o número mágico muda várias vezes dentro de uma versão.
Oferecemos suporte apenas a versões lançadas, não a versões candidatas. Observe, entretanto, que a magia de uma versão lançada geralmente é a mesma da última versão candidata antes do lançamento.
Existem também intérpretes Python personalizados, principalmente o Dropbox, que usam sua própria magia e criptografam bytecode. Com exceção do antigo interpretador Python 2.5 do Dropbox, esse tipo de coisa não é tratado.
Também não lidamos com PJOrion ou código ofuscado de outra forma. Para PJOrion tente: PJOrion Deobfuscator para desembaralhar o bytecode para obter bytecode válido antes de tentar esta ferramenta; pydecipher pode ajudar com isso.
Este programa não pode descompilar arquivos EXE do Microsoft Windows criados por Py2EXE, embora provavelmente possamos descompilar o código depois de extrair o bytecode corretamente. O Pydeinstaller pode ajudar a descompactar os pacotes do Pyinstaller.
O tratamento de listas patologicamente longas de expressões ou declarações é lento. Não lidamos com Cython ou MicroPython que não usam bytecode.
Existem vários bugs na descompilação. E isso é verdade para todos os outros descompiladores CPython que encontrei, mesmo aqueles que afirmam ser "perfeitos" em alguma versão específica como a 2.4.
À medida que o Python avança, a descompilação também fica mais difícil porque a compilação é mais sofisticada e a linguagem em si é mais sofisticada. Suspeito que haverá menos tentativas ad-hoc como unpyc37 (que é baseado em um descompilador 3.3) simplesmente porque é mais difícil fazê-lo. A boa notícia, pelo menos do meu ponto de vista, é que penso compreender o que é necessário para resolver os problemas de uma forma mais robusta. Mas agora, até que o projeto seja melhor financiado, não pretendo fazer nenhum esforço sério para suportar as versões 3.8 ou 3.9 do Python, incluindo bugs que possam surgir.
Você pode encontrar bugs facilmente executando os testes no conjunto de testes padrão que o Python usa para verificar a si mesmo. A qualquer momento, existem dezenas de problemas conhecidos que estão bastante isolados e que poderiam ser resolvidos se alguém dedicasse tempo para fazê-lo. O problema é que não há muitas pessoas trabalhando na correção de bugs.
Alguns dos bugs em 3.7 e 3.8 são simplesmente uma questão de retroportar as correções em decompyle3 . Algum voluntário?
Você pode se deparar com um bug que deseja relatar. Faça isso depois de ler Como relatar um bug e siga as instruções ao abrir um problema.
Esteja ciente de que isso pode não chamar minha atenção por um tempo. Se você patrocinar ou apoiar o projeto de alguma forma, priorizarei seus problemas acima da fila de outras coisas que poderia estar fazendo. Em situações raras, posso fazer uma descompilação manual do bytecode mediante o pagamento de uma taxa. No entanto, isso é caro, geralmente além do que a maioria das pessoas está disposta a gastar.
uncompyle6
decompyle3
- BlackHat 2024 Asia (vídeo). Um grande obrigado aos organizadores e revisores por me deixarem falar. Esse tipo de coisa me incentiva a trabalhar em projetos como esse.uncompyle6
estão incorretos, enquanto os resultados uncompyle2
não estão, mas mais frequentemente o uncompyle6 está correto quando o uncompyle2 não está. Como uncompyle6
adere à precisão do Python idiomático, uncompyle2
pode produzir um código de aparência mais natural quando está correto. Atualmente uncompyle2
é levemente mantido. Consulte seu rastreador de problemas para obter mais detalhes.