MASTG-KNOW-0030: Detecção de Ferramentas de Reverse Engineering

A presença de ferramentas, frameworks e aplicativos comumente usados por engenheiros reversos pode indicar uma tentativa de engenharia reversa do aplicativo. Algumas dessas ferramentas só podem ser executadas em um dispositivo rootado, enquanto outras forçam o aplicativo a entrar em modo de depuração ou dependem da inicialização de um serviço em segundo plano no telefone móvel. Portanto, existem diferentes maneiras que um aplicativo pode implementar para detectar um ataque de engenharia reversa e reagir a ele, por exemplo, terminando a si mesmo.

Você pode detectar ferramentas populares de engenharia reversa que foram instaladas em sua forma não modificada procurando por pacotes de aplicativos, arquivos, processos ou outras modificações e artefatos específicos da ferramenta. Nos exemplos a seguir, discutiremos diferentes maneiras de detectar o framework de instrumentação Frida, que é amplamente utilizado neste guia. Outras ferramentas, como ElleKit e Xposed, podem ser detectadas de forma similar. Observe que ferramentas de DBI/injeção/hooking muitas vezes podem ser detectadas implicitamente, por meio de verificações de integridade em tempo de execução, que serão discutidas abaixo.

Por exemplo, em sua configuração padrão em um dispositivo rootado, o Frida é executado no dispositivo como frida-server. Quando você anexa explicitamente a um aplicativo alvo (por exemplo, via frida-trace ou o Frida REPL), o Frida injeta um frida-agent na memória do aplicativo. Portanto, você pode esperar encontrá-lo lá após anexar ao aplicativo (e não antes). Se você verificar /proc/<pid>/maps, encontrará o frida-agent como frida-agent-64.so:

bullhead:/ # cat /proc/18370/maps | grep -i frida
71b6bd6000-71b7d62000 r-xp  /data/local/tmp/re.frida.server/frida-agent-64.so
71b7d7f000-71b7e06000 r--p  /data/local/tmp/re.frida.server/frida-agent-64.so
71b7e06000-71b7e28000 rw-p  /data/local/tmp/re.frida.server/frida-agent-64.so

O outro método (que também funciona para dispositivos não rootados) consiste em incorporar um frida-gadget no APK e forçar o aplicativo a carregá-lo como uma de suas bibliotecas nativas. Se você inspecionar os mapeamentos de memória do aplicativo após iniciá-lo (não há necessidade de anexar explicitamente a ele), encontrará o frida-gadget incorporado como libfrida-gadget.so.

bullhead:/ # cat /proc/18370/maps | grep -i frida

71b865a000-71b97f1000 r-xp  /data/app/sg.vp.owasp_mobile.omtg_android-.../lib/arm64/libfrida-gadget.so
71b9802000-71b988a000 r--p  /data/app/sg.vp.owasp_mobile.omtg_android-.../lib/arm64/libfrida-gadget.so
71b988a000-71b98ac000 rw-p  /data/app/sg.vp.owasp_mobile.omtg_android-.../lib/arm64/libfrida-gadget.so

Observando esses dois rastros que o Frida deixou para trás, você já pode imaginar que detectá-los seria uma tarefa trivial. E, na verdade, contornar essa detecção também será trivial. Mas as coisas podem ficar muito mais complicadas. A tabela a seguir apresenta brevemente um conjunto de alguns métodos típicos de detecção do Frida e uma breve discussão sobre sua eficácia.

Alguns dos seguintes métodos de detecção são apresentados no artigo "The Jiu-Jitsu of Detecting Frida" de Berdhard Mueller (arquivado). Consulte-o para obter mais detalhes e exemplos de trechos de código.

Método Descrição Discussão
Verificação da Assinatura do Aplicativo Para incorporar o frida-gadget dentro do APK, seria necessário reempacotá-lo e reassiná-lo. Você pode verificar a assinatura do APK quando o aplicativo é iniciado (por exemplo, GET_SIGNING_CERTIFICATES a partir do nível de API 28) e compará-la com a que você fixou em seu APK. Infelizmente, isso é trivial demais para contornar, por exemplo, por meio de patch do APK ou hooking de chamadas de sistema.
Verificar o Ambiente em Busca de Artefatos Relacionados Artefatos podem ser arquivos de pacote, binários, bibliotecas, processos e arquivos temporários. Para o Frida, isso pode ser o frida-server em execução no sistema alvo (rootado) (o daemon responsável por expor o Frida via TCP). Inspecione os serviços em execução (getRunningServices) e processos (ps) procurando por um cujo nome seja "frida-server". Você também pode percorrer a lista de bibliotecas carregadas e verificar se há alguma suspeita (por exemplo, aquelas que incluem "frida" em seus nomes). A partir do Android 7.0 (nível de API 24), a inspeção de serviços/processos em execução não mostrará daemons como o frida-server, pois ele não é iniciado pelo próprio aplicativo. Mesmo que fosse possível, contornar isso seria tão fácil quanto renomear o artefato correspondente do Frida (frida-server/frida-gadget/frida-agent).
Verificação de Portas TCP Abertas O processo frida-server vincula-se à porta TCP 27042 por padrão. Verificar se essa porta está aberta é outro método de detectar o daemon. Este método detecta o frida-server em seu modo padrão, mas a porta de escuta pode ser alterada por meio de um argumento de linha de comando, então contornar isso é um pouco trivial demais.
Verificação de Portas que Respondem à Autenticação D-Bus O frida-server usa o protocolo D-Bus para comunicação, então você pode esperar que ele responda ao D-Bus AUTH. Envie uma mensagem D-Bus AUTH para cada porta aberta e verifique se há uma resposta, na esperança de que o frida-server se revele. Este é um método bastante robusto de detectar o frida-server, mas o Frida oferece modos alternativos de operação que não requerem o frida-server.
Varredura da Memória do Processo em Busca de Artefatos Conhecidos Varra a memória em busca de artefatos encontrados nas bibliotecas do Frida, por exemplo, a string "LIBFRIDA" presente em todas as versões do frida-gadget e frida-agent. Por exemplo, use Runtime.getRuntime().exec e itere através dos mapeamentos de memória listados em /proc/self/maps ou /proc/<pid>/maps (dependendo da versão do Android) procurando pela string. Este método é um pouco mais eficaz e é difícil de contornar apenas com o Frida, especialmente se alguma ofuscação tiver sido adicionada e se múltiplos artefatos estiverem sendo varridos. No entanto, os artefatos escolhidos podem ser modificados por patch nos binários do Frida. Encontre o código-fonte no GitHub de Berdhard Mueller.

Lembre-se de que esta tabela está longe de ser exaustiva. Poderíamos começar a falar sobre a detecção de named pipes (usados pelo frida-server para comunicação externa) e trampolines (vetores de salto indireto inseridos no prólogo de funções), o que ajudaria a detectar o ElleKit ou o Interceptor do Frida. Muitas outras técnicas existem, e cada uma delas dependerá de se você está usando um dispositivo rootado, a versão específica do método de root e/ou a versão da própria ferramenta. Além disso, o aplicativo pode tentar dificultar a detecção dos mecanismos de proteção implementados usando várias técnicas de ofuscação. No final, isso faz parte do jogo de gato e rato de proteger dados sendo processados em um ambiente não confiável (um aplicativo em execução no dispositivo do usuário).

É importante notar que esses controles apenas aumentam a complexidade do processo de engenharia reversa. Se usados, a melhor abordagem é combiná-los de forma inteligente, em vez de usá-los individualmente. No entanto, nenhum deles pode garantir 100% de eficácia, pois o engenheiro reverso sempre terá acesso total ao dispositivo e, portanto, sempre vencerá! Você também deve considerar que a integração de alguns desses controles em seu aplicativo pode aumentar a complexidade do mesmo e até mesmo ter um impacto em seu desempenho.