O ByteCode Simplifier é uma ferramenta para desviar os scripts Python protegidos por Pjorion. Esta é uma reescrita completa da minha ferramenta mais antiga Pjorion Deobfuscator
Você precisa ter os seguintes pacotes pré-instalados:
Ambos os pacotes são instaláveis pip . Além disso, verifique se o GraphViz executável está no seu caminho para pydotplus funcionar. pydotplus é necessário apenas para desenhar gráficos e, se você não quiser esse recurso, pode comentar as chamadas render_graph na função deobfuscate no arquivo deobfuscator.py
Pjorion ofusca o arquivo original e apresenta várias camadas de wrapper em cima dele. O objetivo dessas camadas é simplesmente (mais ou menos) descriptografar a próxima camada interna e executá -la através de uma instrução EXEC_STMT . Portanto, você não pode usar essa ferramenta como está em um arquivo ofuscado. Primeiro, você precisaria remover as camadas do invólucro e se apossar do objeto de código ofuscado real. Em seguida, você pode marcar o código ofuscado no disco e executar essa ferramenta, que, esperançosamente, devolve o código deobfuscado.
Consulte esta postagem do blog para obter detalhes.
O simplificador de bytecode analisa o código ofuscado usando uma abordagem de desmontagem de travessia recursiva. As instruções são desmontadas e combinadas em blocos básicos. Um bloco básico é uma sequência de instruções com uma única entrada e uma única saída.
Um bloco básico pode terminar com uma instrução de fluxo de controle, como uma instrução if . Uma declaração if tem dois ramos - verdadeiros e falsos. Correspondendo aos ramos, os blocos básicos têm arestas entre eles. Toda essa estrutura é representada por um gráfico direcionado. Usamos networkx.DiGraph para esse fim.
Os nós no gráfico representam os blocos básicos, enquanto as bordas entre os nós representam o fluxo de controle entre os blocos básicos.
Uma instrução de transferência de controle condicional, como if tiver duas ramificações - a ramificação verdadeira que é executada quando a condição é mantida. Nós marcamos esse ramo como a borda explícita, pois essa ramificação é explicitamente especificada pela instrução if . O outro ramo viz. O falso é marcado como uma borda implícita, pois é deduzida logicamente.
Uma instrução de transferência de controle incondicional como jump tem apenas uma vantagem explícita.
Depois de termos o código em um formulário de gráfico, é mais fácil raciocinar sobre o código. Portanto, a simplificação do código ofuscado é feita neste gráfico.
Duas estratégias de simplificação são usadas principalmente:
Um encaminhador é um bloco básico que consiste em uma única instrução de fluxo de controle incondicional. Um encaminhador transfere a execução para outro bloco básico sem fazer nenhum trabalho útil.
Antes da eliminação do encaminhamento

O básico bloqueado destacado em amarelo é um bloco de encaminhador. Pode ser eliminado para fornecer a seguinte estrutura abaixo.
Após a eliminação do encaminhamento

No entanto, um encaminhador nem sempre pode ser eliminado especificamente nos casos em que o encaminhador tem uma entrada implícita. Consulte o simplifier.py para obter os detalhes
Um bloco básico pode ser mesclado em seu antecessor se e somente se houver exatamente um antecessor e o antecessor tiver esse bloco básico como seu único sucessor.
Antes de se fundir

As instruções destacadas dos blocos básicas foram mesclados para formar um bloco básico maior mostrado abaixo. As instruções de transferência de controle foram removidas, pois não são mais necessárias.
Depois de se fundir

Depois que o gráfico for simplificado, precisamos montar os blocos básicos de volta ao código plano. Isso é implementado no conjunto de arquivos.py.
O processo de montagem em si consiste em subfatrios:
JUMP_FORWARD para JUMP_ABSOLUTE : Se o bloco básico A tiver uma instrução de fluxo de controle relativo para o Bloco B, o bloco B deverá estar localizado após o bloco A no layout gerado. Isso ocorre porque as instruções de fluxo de controle relativo geralmente são usadas para se referir a endereços localizados após ele. Se a instrução relativa do CF for JUMP_FORWARD podemos mudar para JUMP_ABSOLUTE .SETUP_LOOP, SETUP_EXCEPT etc., precisamos criar um novo bloco de encaminhador que consiste em uma instrução absoluta de salto para bloquear B e fazer com que a instrução de fluxo de controle relativo no bloco A aponte para o bloco do encaminhador. Isso funciona, pois o bloco do encaminhador será naturalmente após o bloco A no layout gerado e as instruções relativas sempre podem ser usadas para apontar para os blocos localizados após ele, ou seja, um endereço mais alto.JUMP_FORWARD & SETUP_LOOP usa o operando para consultar outras instruções. Esta referência é um número inteiro que denota o endereço de deslocamento/absoluto do alvo. $ python main.py --ifile=obfuscated.pyc --ofile=deobfuscated.pyc
INFO:__main__:Opening file obfuscated.pyc
INFO:__main__:Input pyc file header matched
DEBUG:__main__:Unmarshalling file
INFO:__main__:Processing code object x0bx08x0cx19x0bx0ex03
DEBUG:deobfuscator:Code entrypoint matched PjOrion signature v1
INFO:deobfuscator:Original code entrypoint at 124
INFO:deobfuscator:Starting control flow analysis...
DEBUG:disassembler:Finding leaders...
DEBUG:disassembler:Start leader at 124
DEBUG:disassembler:End leader at 127
.
<snip>
.
DEBUG:disassembler:Found 904 leaders
DEBUG:disassembler:Constructing basic blocks...
DEBUG:disassembler:Creating basic block 0x27dc5a8 spanning from 13 to 13, both inclusive
DEBUG:disassembler:Creating basic block 0x2837800 spanning from 5369 to 5370, end exclusive
.
<snip>
.
DEBUG:disassembler:461 basic blocks created
DEBUG:disassembler:Constructing edges between basic blocks...
DEBUG:disassembler:Adding explicit edge from block 0x2a98080 to 0x2aa88a0
DEBUG:disassembler:Adding explicit edge from block 0x2aa80f8 to 0x2a9ab70
DEBUG:disassembler:Basic block 0x2aa8dc8 has xreference
.
<snip>
.
INFO:deobfuscator:Control flow analysis completed.
INFO:deobfuscator:Starting simplication of basic blocks...
DEBUG:simplifier:Eliminating forwarders...
INFO:simplifier:Adding implicit edge from block 0x2aa8058 to 0x2a9ab70
INFO:simplifier:Adding explicit edge from block 0x2b07ee0 to 0x2a9ab70
DEBUG:simplifier:Forwarder basic block 0x2aa80f8 eliminated
.
<snip>
.
INFO:
INFO:simplifier:307 basic blocks merged.
INFO:deobfuscator:Simplication of basic blocks completed.
INFO:deobfuscator:Beginning verification of simplified basic block graph...
INFO:deobfuscator:Verification succeeded.
INFO:deobfuscator:Assembling basic blocks...
DEBUG:assembler:Performing a DFS on the graph to generate the layout of the blocks.
DEBUG:assembler:Morphing some JUMP_ABSOLUTE instructions to make file decompilable.
DEBUG:assembler:Verifying generated layout...
INFO:assembler:Basic block 0x2b0e940 uses a relative control transfer instruction to access block 0x2abb3a0 located before it.
INFO:assembler:Basic block 0x2ab5300 uses a relative control transfer instruction to access block 0x2ada918 located before it.
DEBUG:assembler:Successfully verified layout.
DEBUG:assembler:Calculating addresses of basic blocks.
DEBUG:assembler:Calculating instruction operands.
DEBUG:assembler:Generating code...
INFO:deobfuscator:Successfully assembled.
INFO:__main__:Successfully deobfuscated code object main
INFO:__main__:Collecting constants for code object main
INFO:__main__:Generating new code object for main
INFO:__main__:Generating new code object for x0bx08x0cx19x0bx0ex03
INFO:__main__:Writing deobfuscated code object to disk
INFO:__main__:Success