Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
simplify — Máquina virtual Android e desofuscador | Kitploit
Ferramentas/GitHubGitHub/calebfenton/simplify
Segurança AndroidAnálise Dinâmica (Sandboxing)Engenharia ReversaAnálise de MalwareAnálise de Binários
GitHubcalebfenton/simplify

simplify

Máquina virtual Android e desofuscador

Ver Repositório
4.7k4557há 5 anosRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

Simplify

Build Status Coverage Status Coverity Scan Build Status

Desofuscador Android Genérico

O Simplify executa virtualmente um aplicativo para entender seu comportamento e então tenta otimizar o código para que se comporte de forma idêntica, mas seja mais fácil para um humano entender. Cada tipo de otimização é simples e genérico, portanto não importa qual tipo específico de ofuscação é usado.

Antes e Depois

O código à esquerda é uma descompilação de um aplicativo ofuscado, e o código à direita foi desofuscado.

Muitas chamadas de método, nenhum significado claro Uau, tão literal, muito significado

Visão Geral

Há três partes no projeto: smalivm, simplify e o aplicativo de demonstração.

  1. smalivm: Fornece uma sandbox de máquina virtual para executar métodos Dalvik. Após executar um método, retorna um grafo contendo todos os valores possíveis de registradores e classes para cada caminho de execução. Funciona mesmo se alguns valores forem desconhecidos, como E/S de arquivo e rede. Por exemplo, qualquer condicional if ou switch com um valor desconhecido resulta em ambos os ramos sendo seguidos.
  2. simplify: Analisa os grafos de execução do smalivm e aplica otimizações como propagação de constantes, remoção de código morto, desreflexão e algumas otimizações de pequeno escopo. Elas são bastante simples, mas quando aplicadas juntas repetidamente, descriptografam strings, removem reflexão e simplificam bastante o código. Ele não renomeia métodos e classes.
  3. demoapp: Contém exemplos simples e fortemente comentados para usar o smalivm no seu próprio projeto. Se você está construindo algo que precisa executar código Dalvik, dê uma olhada.

Uso

root@kitploit:~
usage: java -jar simplify.jar <input> [options]
deobfuscates a dalvik executable
 -et,--exclude-types <pattern>   Exclude classes and methods which include REGEX, eg: "com/android", applied after include-types
 -h,--help                       Display this message
 -ie,--ignore-errors             Ignore errors while executing and optimizing methods. This may lead to unexpected behavior.
    --include-support            Attempt to execute and optimize classes in Android support library packages, default: false
 -it,--include-types <pattern>   Limit execution to classes and methods which include REGEX, eg: ";->targetMethod\("
    --max-address-visits <N>     Give up executing a method after visiting the same address N times, limits loops, default: 10000
    --max-call-depth <N>         Do not call methods after reaching a call depth of N, limits recursion and long method chains, default: 50
    --max-execution-time <N>     Give up executing a method after N seconds, default: 300
    --max-method-visits <N>      Give up executing a method after executing N instructions in that method, default: 1000000
    --max-passes <N>             Do not run optimizers on a method more than N times, default: 100
 -o,--output <file>              Output simplified input to FILE
    --output-api-level <LEVEL>   Set output DEX API compatibility to LEVEL, default: 15
 -q,--quiet                      Be quiet
    --remove-weak                Remove code even if there are weak side effects, default: true
 -v,--verbose <LEVEL>            Set verbosity to LEVEL, default: 0

Compilação

A compilação requer a instalação do Java Development Kit 8 (JDK).

Como este projeto contém submodulos para frameworks Android, clone com --recursive:

root@kitploit:~
git clone --recursive https://github.com/CalebFenton/simplify.git

Ou atualize os submodulos a qualquer momento com:

root@kitploit:~
git submodule update --init --recursive

Então, para construir um único jar que contém todas as dependências:

root@kitploit:~
./gradlew fatjar

O jar do Simplify estará em simplify/build/libs/. Você pode testar se está funcionando simplificando o aplicativo de exemplo ofuscado fornecido. Aqui está como executá-lo (você pode precisar alterar simplify.jar):

root@kitploit:~
java -jar simplify/build/libs/simplify.jar -it "org/cf/obfuscated" -et "MainActivity" simplify/obfuscated-app.apk

Para entender o que está sendo desofuscado, veja o README do Aplicativo Ofuscado.

Solução de Problemas

Se o Simplify falhar, tente estas recomendações, em ordem:

  1. Apenas direcione alguns métodos ou classes usando a opção -it.
  2. Se a falha for por exceder o máximo de visitas, tente usar valores maiores para --max-address-visits, --max-call-depth e --max-method-visits.
  3. Tente com -v ou -v 2 e relate o problema com os logs e um hash do DEX ou APK.
  4. Tente novamente, mas não quebre o contato visual. O Simplify sente medo.

Se estiver compilando no Windows e a compilação falhar com um erro semelhante a:

Could not find tools.jar. Please check that C:\Program Files\Java\jre1.8.0_151 contains a valid JDK installation.

Isso significa que o Gradle não consegue encontrar um caminho adequado do JDK. Certifique-se de que o JDK está instalado, defina a variável de ambiente JAVA_HOME para o caminho do JDK e certifique-se de fechar e reabrir o prompt de comando usado para compilar.

Contribuindo

Não seja tímido. Eu acho que execução virtual e desofuscação são problemas fascinantes. Qualquer um interessado é automaticamente legal e contribuições são bem-vindas, mesmo que seja apenas para corrigir um erro de digitação. Sinta-se à vontade para fazer perguntas nas issues e enviar pull requests.

Relatando Problemas

Por favor, inclua um link para o APK ou DEX e o comando completo que você está usando. Isso torna muito mais fácil reproduzir (e assim corrigir) o seu problema.

Se você não puder compartilhar a amostra, por favor inclua o hash do arquivo (SHA1, SHA256, etc).

Estratégias de Otimização

Propagação de Constantes

Se uma operação coloca um valor de um tipo que pode ser transformado em uma constante, como uma string, número ou booleano, esta otimização substituirá essa operação pela constante. Por exemplo:

root@kitploit:~
const-string v0, "VGVsbCBtZSBvZiB5b3VyIGhvbWV3b3JsZCwgVXN1bC4="
invoke-static {v0}, Lmy/string/Decryptor;->decrypt(Ljava/lang/String;)Ljava/lang/String;
# Decrypts to: "Tell me of your homeworld, Usul."
move-result v0

Neste exemplo, uma string criptografada é descriptografada e colocada em v0. Como strings são "constantizáveis", o move-result v0 pode ser substituído por um const-string:

root@kitploit:~
const-string v0, "VGVsbCBtZSBvZiB5b3VyIGhvbWV3b3JsZCwgVXN1bC4="
invoke-static {v0}, Lmy/string/Decryptor;->decrypt(Ljava/lang/String;)Ljava/lang/String;
const-string v0, "Tell me of your homeworld, Usul."

Remoção de Código Morto

O código está morto se removê-lo não puder alterar o comportamento do aplicativo. O caso mais óbvio é se o código é inalcançável, ex.: if (false) { // morto }). Se o código é alcançável, pode ser considerado morto se não afetar nenhum estado fora do método, ou seja, não tem efeito colateral. Por exemplo, o código pode não afetar o valor de retorno do método, alterar variáveis de classe ou realizar E/S. Isso é difícil de determinar em análise estática. Felizmente, o smalivm não precisa ser inteligente. Ele apenas executa tudo que pode de forma estúpida e assume que há efeitos colaterais se não tiver certeza. Considere o exemplo da Propagação de Constantes:

root@kitploit:~
const-string v0, "VGVsbCBtZSBvZiB5b3VyIGhvbWV3b3JsZCwgVXN1bC4="
invoke-static {v0}, Lmy/string/Decryptor;->decrypt(Ljava/lang/String;)Ljava/lang/String;
const-string v0, "Tell me of your homeworld, Usul."

Neste código, o invoke-static não afeta mais o valor de retorno do método e vamos supor que ele não faz nada estranho, como escrever bytes no sistema de arquivos ou em um socket de rede, então não tem efeitos colaterais. Ele pode ser simplesmente removido.

root@kitploit:~
const-string v0, "VGVsbCBtZSBvZiB5b3VyIGhvbWV3b3JsZCwgVXN1bC4="
const-string v0, "Tell me of your homeworld, Usul."

Finalmente, o primeiro const-string atribui um valor a um registrador, mas esse valor nunca é usado, ou seja, a atribuição está morta. Também pode ser removida.

root@kitploit:~
const-string v0, "Tell me of your homeworld, Usul."

Eba!

Desreflexão

Um grande desafio na análise estática de Java é a reflexão. Simplesmente não é possível saber quais são os argumentos para métodos de reflexão sem fazer uma análise cuidadosa do fluxo de dados. Existem maneiras inteligentes e engenhosas de fazer isso, mas o smalivm faz apenas executando o código. Quando encontra uma invocação de método refletido como:

root@kitploit:~
invoke-virtual {v0, v1, v2}, Ljava/lang/reflect/Method;->invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;

Ele pode saber os valores de v0, v1 e v2. Se tiver certeza sobre os valores, pode substituir a chamada a Method.invoke() por uma invocação de método real não refletida. O mesmo se aplica a buscas refletidas de campos e classes.

Peephole

Para tudo que não se encaixa perfeitamente em uma categoria específica, existem otimizações de pequeno escopo. Isso inclui remover operações check-cast inúteis, substituir chamadas Ljava/lang/String;-><init> por const-string, e assim por diante.

Exemplo de Desofuscação

Antes da Otimização

root@kitploit:~
.method public static test1()I
    .locals 2

    new-instance v0, Ljava/lang/Integer;
    const/4 v1, 0x1
    invoke-direct {v0, v1}, Ljava/lang/Integer;-><init>(I)V

    invoke-virtual {v0}, Ljava/lang/Integer;->intValue()I
    move-result v0

    return v0
.end method

Tudo isso faz é v0 = 1.

Após a Propagação de Constantes

root@kitploit:~
.method public static test1()I
    .locals 2

    new-instance v0, Ljava/lang/Integer;
    const/4 v1, 0x1
    invoke-direct {v0, v1}, Ljava/lang/Integer;-><init>(I)V

    invoke-virtual {v0}, Ljava/lang/Integer;->intValue()I
    const/4 v0, 0x1

    return v0
.end method

O move-result v0 é substituído por const/4 v0, 0x1. Isso ocorre porque há apenas um valor de retorno possível para intValue()I e o tipo de retorno pode ser transformado em uma constante. Os argumentos v0 e v1 são inequívocos e não mudam. Isto é, há um consenso de valores para cada caminho de execução possível em intValue()I. Outros tipos de valores que podem ser transformados em constantes:

  • números - const/4, const/16, etc.
  • strings - const-string
  • classes - const-class

Após a Remoção de Código Morto

root@kitploit:~
.method public static test1()I
    .locals 2

    const/4 v0, 0x1

    return v0
.end method

Porque o código acima de const/4 v0, 0x1 não afeta o estado fora do método (sem efeitos colaterais), ele pode ser removido sem alterar o comportamento. Se houvesse uma chamada de método que escrevesse algo no sistema de arquivos ou na rede, ela não poderia ser removida porque afeta o estado fora do método. Ou se test()I recebesse um argumento mutável, como um LinkedList, quaisquer instruções que o acessassem não poderiam ser consideradas mortas.

Outros exemplos de código morto:

  • atribuições não referenciadas - atribuir registradores e não usá-los
  • instruções não alcançadas / inalcançáveis - if (false) { dead_code(); }

Licença

Esta ferramenta está disponível sob uma licença dupla: uma comercial adequada para projetos de código fechado e uma licença GPL que pode ser usada em software de código aberto.

Dependendo de suas necessidades, você deve escolher uma delas e seguir suas políticas. Um detalhe das políticas e acordos para cada tipo de licença está disponível nos arquivos LICENSE.COMMERCIAL e LICENSE.GPL.

Leitura Adicional

  • Execução Virtual Dalvik com SmaliVM
  • Guillot, Yoann, and Alexandre Gazet. "Automatic Binary Deobfuscation." Journal in Computer Virology 6.3 (2010): 261-76
  • Unicorn - The ultimate CPU emulator
  • Babak Yadegari, Saumya Debray. "Symbolic Execution of Obfuscated Code"
  • Histórias de sucesso:
    • Carregamento Dinâmico de Classes Android com criptografia "AES/CFB/NoPadding". Dê uma espiada antes e depois. Ferramenta usada: #simplify. #Android #ofuscação #criptografiaDeClasses #dex
    • Descriptografando Criptografia de Strings de Malware
Baixar ferramenta