Não há recurso semelhante para o código de bytes Java.
Quando você compila um programa C e o vincula estaticamente a uma biblioteca padrão, o código da biblioteca estará presente, mais ou menos sem modificações, dentro do binário (exceto para endereços que serão alterados), mas não haverá qualquer indício de que uma função específica tinha um nome específico antes de ser compilada (a menos que a depuração seja habilitada durante a compilação / vinculação). Mas, qualquer função tem um padrão mais ou menos fixo de bytes e, reconhecendo esses bytes, o IDA pode atribuir o nome original à função.
No bytecode Java, não há necessidade de fazer isso. Nomes de funções, nomes de variáveis e informações semelhantes estão presentes no bytecode compilado de qualquer maneira. A "biblioteca padrão", rt.jar
, também não está embutida no bytecode, então se uma classe usa um ArrayList
, a classe terá uma referência a java.util.ArrayList
mesmo após o processo de ofuscação. Portanto, nada a fazer aqui para um analisador de assinatura.
Se o aplicativo optar por ofuscar a biblioteca padrão também, ele precisará incluir essa biblioteca ofuscada em seus próprios arquivos jar. Isso provavelmente levantará alguns problemas de licenciamento, mas, além disso, como o obfuscator renomeará métodos e campos, o código de byte dessa biblioteca ofuscada será muito diferente do código de byte original para ser reconhecido por um recurso como o FLIRT do IDA. Além disso, você não pode simplesmente renomear o método no IDA, porque você também teria que modificar todas as referências.
No entanto, há pelo menos um projeto de código aberto que tem um problema semelhante ao seu, e eles parecem ter resolvido muito bem. Minecraft é um jogo popular que inclui um servidor escrito em Java (e ofuscado); o projeto Spigot descompila este servidor, muda algumas coisas, adiciona uma API e distribui o resultado. Especificamente, para evitar problemas de licenciamento, eles distribuem um sistema de compilação que baixa, descompila, corrige e recompila o servidor Minecraft na máquina do usuário.
Eles usam o descompilador fernflower, que tem a opção de renomear símbolos durante a descompilação e inclui um extenso mapa de nomes de símbolos ofuscados para legíveis. Exemplo:
AttributeInstance a () LIAttribute; getAttributeAttributeInstance a (D) V setValueAttributeInstance e () D getValueAttributeMapServer b () Ljava / util / Set; getAttributesAxisAlignedBB b (DDD) LAxisAlignedBB; grow
O código-fonte, que é gerado usando esses mapas, é obviamente muito mais legível do que o original. E, pelo menos para o projeto spigot, recompilar esta fonte (depois de adicionar alguns patches para criar uma API) produz um servidor Minecraft funcional.
Então, talvez, esta possa ser uma maneira de você continuar - use fernflower para descompilar suas classes, carregue-as em um editor para encontrar algum código útil e atribua nomes de classe legíveis, escreva um arquivo de mapeamento e repita isso algumas vezes. Então, quando você quiser fazer alguma análise dinâmica, recompile o código Java descompilado e carregue-o no IDA.
Claro, esta abordagem ainda tem alguns problemas:
- você ainda terá que identificar cada função manualmente - mas como eu disse, você provavelmente não encontrará nenhuma função de biblioteca padrão em seu código. E, não há bibliotecas de assinatura existentes para qualquer método que você use, então provavelmente não há maneira de contornar isso.
- o código descompilado / recompilado pode não funcionar, por causa de bugs / falhas no próprio descompilador Java
- o código descompilado / recompilado pode não funcionar por causa do ofuscador; por exemplo, o obfuscator pode substituir todas as constantes de string por algo como
Obfuscator :: decode ("some_crypted_stuff")
, onde a função decode
usa o nome da classe de chamada como seu chave de descriptografia, o que significa que a descriptografia falha quando a classe é renomeada - o obfuscator pode trazer seu próprio carregador de classe, que altera o nome da classe antes de carregá-la; por exemplo, ele pode saber transformar uma classe
com.obfuscate.SOME_BASE_64_STRING
em uma string base64 decodificada, então com.obfuscate.amF2YS51dGlsLkFycmF5TGlzdAo.something ()
chamaria java.util.ArrayList.something ()
. Isso quebra a conexão visível entre o chamador e o receptor (mas o mapeamento de nome pode resolver esse problema muito bem e você pode automatizar muito)
Mesmo se você não puder obter um descompilado, recompilável, versão do seu binário, você provavelmente pode escrever algum código que funcione no código-fonte descompilado para identificar funções por seu comportamento, usando alguma heurística. Em seguida, faça com que seu código escreva uma tabela de mapeamento e escreva um plugin Python para importar essa tabela de mapeamento para o seu código como comentários.
É questionável se essas abordagens superam a engenharia reversa manual dentro do IDA, mas como o IDA não tem esse recurso e como não há bibliotecas de assinatura genéricas (e elas não funcionariam de qualquer maneira, veja acima), é o melhor que tenho a oferecer.
Editar 2016-04-17
Acontece que tenho um pequeno projeto onde poderia usar algum mapeamento de desofuscação sozinho e verifiquei no processo de desofuscação da etapa de descompilação do Minecraft um pouco mais.
Acontece que eles nem usam flores de samambaia r recurso de emapping. Em vez disso, eles têm seu próprio conjunto de ferramentas. Esses são lamentavelmente subdocumentados, mas parece haver um Repositório GitHub.
O primeiro, SpecialSource.jar, compara um jar ofuscado com uma versão não ofuscada e gera uma tabela de mapeamento. Isso parece permitir construir novas tabelas rapidamente quando uma nova versão do original ofuscado for lançada. No entanto, não há documentação sobre o que exatamente está sendo comparado.
O segundo, SpecialSource-2.jar, remapeia referências e nomes de classes e métodos diretamente no arquivo jar , sem uma etapa de descompilação / compilação, para evitar todos os problemas que vêm com isso. Assim, depois de ter um arquivo de mapeamento, você pode aplicá-lo ao jar para obter um jar de saída, que você pode alimentar no IDA ou em um descompilador de sua escolha. O uso é
java - jar /path/to/SpecialSource-2.jar map -m mapping.csrg \ -i obfuscated.jar -o readable.jar
com o arquivo de mapeamentos parecido com este
# Isso renomeia uma classe, dado o nome ofuscado e onecom / example / ab / a legível MyNiceClassName # Isso renomeia um método, dado a classe, método, assinatura e nome legível.MyNiceClassName a (D) I doubleToInt