Resolvendo OWASP Uncrackable Level 1 de Android

Olá! Esse é o meu writeup para o uncrackeble level 1 da owasp disponível em https://github.com/OWASP/owasp-mstg/tree/master/Crackmes, vamos a descrição da questão. Para resolver esse desafio vamos precisar de um dispositivo com o frida server habilitado (emulado ou real).

Disclaimer

Se você ainda não conseguiu completar o desafio, eu recomendo fortemente que tente mais um pouco antes de ler. A intenção aqui foi mostrar uma das várias formas de chegar no mesmo lugar, então se você não quer tomar nenhum spoiler, salva o link e volta aqui depois do desafio :)

O Problema ROOT

Para os testes eu uso um dispositivo com acesso root, então assim que abri o aplicativo já visualizamos uma mensagem dizendo que o aplicativo será fechado por conta dele ser rooteado. Se você usa magisk, pode facilmente habilitar o MagiskHide e não terá esse problema, mas resolvi tentar bypassar esse check para sentir como seria.

Para isso utilizei o frida e pesquisando um pouco na internet você pode achar diversos guias, tanto de como instalar, quanto de uma série de bypasses, mas cada caso acaba sendo um pouco diferente, então isso exige um pouco mais de análise.

Olhando o código fonte, nós podemos observar que na MainActivity temos a função onCreate, que checa se o dispositivo possui root ou não, com testes em funções sendo implementadas no arquivo c.

Para bypassar o check de root temos que basicamente fazer com que todas as chamadas das funções de c retornem ‘false’ e assim a aplicação siga normalmente.

Utilizando a ferramenta frida podemos facilmente bypassar esse check, com o código abaixo:

Nesse código, reescrevemos as funções que fazem os checks de root, fazendo com que elas sempre retornem false. Para testar o código basta salvarmos esse código em um arquivo.js e executarmos o comando:

frida -l arquivo.js -U -f owasp.mstg.uncrackable1 - no-pause

Nesse comando podemos ver as opções:

  • -l: O script que queremos que o frida execute
  • -U: Para um dispositivo conectado via USB
  • -f: O “arquivo” alvo, nesse caso um pacote (aplicação) android
  • -no-pause: para que após executar o script ele comece na thread principal

Após isso o app deverá iniciar sem problemas!

Achando o segredo

Analisando mais o código fonte nós podemos ver que a função verify na MainActivity chama por uma função em outro arquivo, enviando o valor que digitamos e caso o resultado dê verdadeiro uma caixa de sucesso é exibida. Vamos dar uma olhada nessa função:

Vendo essa parte do código podemos reparar que o retorno dela é basicamente uma comparação entre o valor que digitamos e um valor gerado a partir de uma outra função convertido em string, vamos um pouco mais fundo para observar essa função chamada.

Aqui temos uma função que vai gerar o segredo para ser comparado com o que digitamos. Agora que sabemos isso, nós podemos incrementar nosso script, para fazer com que o frida nos retorne qual valor está sendo gerado por essa função. Para isso podemos utilizar o script:

Agora, além de bypassar a detecção de root, nosso script também irá nos retornar o segredo.

Repare que diferente do primeiro exemplo, nós não simplesmente reescrevemos a função e ignoramos o que ela normalmente faz. Dessa vez apenas armazenamos o array em uma variável, printamos o valor na tela e deixamos a função executar como de costume.

Executando esse script com o mesmo código que utilizamos da primeira vez e tentando qualquer valor, o segredo será printado no nosso terminal.

Aqui pegamos o segredo!

Obrigado por ler até aqui! Pretendo escrever mais writeups voltados a aplicações android, então até logo!