MASTG-TOOL-0028: radare2 para Android
radare2 (r2) é um popular framework de engenharia reversa de código aberto para desmontagem, depuração, aplicação de patches e análise de binários que é scriptável e suporta muitas arquiteturas e formatos de arquivo, incluindo aplicativos Android e iOS. Para Android, são suportados Dalvik DEX (odex, multidex), ELF (executáveis, .so, ART) e Java (JNI e classes Java). Ele também contém vários scripts úteis que podem ajudar você durante a análise de aplicativos móveis, pois oferece desmontagem de baixo nível e análise estática segura que são úteis quando as ferramentas tradicionais falham.
O radare2 implementa uma rica interface de linha de comando (CLI) onde você pode realizar as tarefas mencionadas. No entanto, se você não se sente muito confortável usando a CLI para engenharia reversa, pode considerar usar a Web UI (através da flag -H) ou a versão GUI ainda mais conveniente em Qt e C++ chamada iaito. Tenha em mente que a CLI, e mais concretamente seu Modo Visual e suas capacidades de script (r2pipe), são o cerne do poder do radare2 e definitivamente vale a pena aprender a usá-los.
Instalando o radare2¶
Consulte as instruções oficiais de instalação do radare2. Recomendamos fortemente sempre instalar o radare2 a partir da versão do GitHub em vez de usar gerenciadores de pacotes comuns como APT. O radare2 está em desenvolvimento muito ativo, o que significa que repositórios de terceiros geralmente estão desatualizados.
Usando o radare2¶
O framework radare2 compreende um conjunto de pequenos utilitários que podem ser usados a partir do shell r2 ou independentemente como ferramentas CLI. Esses utilitários incluem rabin2, rasm2, rahash2, radiff2, rafind2, ragg2, rarun2, rax2 e, claro, r2, que é o principal.
Por exemplo, você pode usar rafind2 para ler strings diretamente de um Android Manifest codificado (AndroidManifest.xml):
# Permissões
$ rafind2 -ZS permission AndroidManifest.xml
# Atividades
$ rafind2 -ZS activity AndroidManifest.xml
# Provedores de conteúdo
$ rafind2 -ZS provider AndroidManifest.xml
# Serviços
$ rafind2 -ZS service AndroidManifest.xml
# Receptores
$ rafind2 -ZS receiver AndroidManifest.xml
Ou use rabin2 para obter informações sobre um arquivo binário.
Use o utilitário principal r2 para acessar o shell r2. Você pode carregar binários DEX como qualquer outro binário:
r2 classes.dex
Digite r2 -h para ver todas as opções disponíveis. Uma flag muito usada é -A, que dispara uma análise após carregar o binário alvo. No entanto, isso deve ser usado com moderação e com binários pequenos, pois é muito consumidor de tempo e recursos. Você pode aprender mais sobre isso em Desmontagem de Native Code.
Uma vez no shell r2, você também pode acessar funções oferecidas pelos outros utilitários do radare2. Por exemplo, executar i imprimirá as informações do binário, exatamente como rabin2 -I faz.
Para imprimir todas as strings, use rabin2 -Z ou o comando iz (ou o menos verboso izq) do shell r2.
[0x000009c8]> izq
0xc50 39 39 /dev/com.koushikdutta.superuser.daemon/
0xc79 25 25 /system/app/Superuser.apk
...
0xd23 44 44 5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc=
0xd51 32 32 8d127684cbc37c17616d806cf50473cc
0xd76 6 6 <init>
0xd83 10 10 AES error:
0xd8f 20 20 AES/ECB/PKCS7Padding
0xda5 18 18 App is debuggable!
0xdc0 9 9 CodeCheck
0x11ac 7 7 Nope...
0x11bf 14 14 Root detected!
Na maioria das vezes, você pode anexar opções especiais aos seus comandos, como q para tornar o comando menos verboso (quiet) ou j para dar a saída em formato JSON (use ~{} para embelezar a string JSON).
[0x000009c8]> izj~{}
[
{
"vaddr": 3152,
"paddr": 3152,
"ordinal": 1,
"size": 39,
"length": 39,
"section": "file",
"type": "ascii",
"string": "L2Rldi9jb20ua291c2hpa2R1dHRhLnN1cGVydXNlci5kYWVtb24v"
},
{
"vaddr": 3193,
"paddr": 3193,
"ordinal": 2,
"size": 25,
"length": 25,
"section": "file",
"type": "ascii",
"string": "L3N5c3RlbS9hcHAvU3VwZXJ1c2VyLmFwaw=="
},
Você pode imprimir os nomes das classes e seus métodos com o comando r2 ic (information classes).
[0x000009c8]> ic
...
0x0000073c [0x00000958 - 0x00000abc] 356 class 5 Lsg/vantagepoint/uncrackable1/MainActivity
:: Landroid/app/Activity;
0x00000958 method 0 pC Lsg/vantagepoint/uncrackable1/MainActivity.method.<init>()V
0x00000970 method 1 P Lsg/vantagepoint/uncrackable1/MainActivity.method.a(Ljava/lang/String;)V
0x000009c8 method 2 r Lsg/vantagepoint/uncrackable1/MainActivity.method.onCreate (Landroid/os/Bundle;)V
0x00000a38 method 3 p Lsg/vantagepoint/uncrackable1/MainActivity.method.verify (Landroid/view/View;)V
0x0000075c [0x00000acc - 0x00000bb2] 230 class 6 Lsg/vantagepoint/uncrackable1/a :: Ljava/lang/Object;
0x00000acc method 0 sp Lsg/vantagepoint/uncrackable1/a.method.a(Ljava/lang/String;)Z
0x00000b5c method 1 sp Lsg/vantagepoint/uncrackable1/a.method.b(Ljava/lang/String;)[B
Você pode imprimir os métodos importados com o comando r2 ii (information imports).
[0x000009c8]> ii
[Imports]
Num Vaddr Bind Type Name
...
29 0x000005cc NONE FUNC Ljava/lang/StringBuilder.method.append(Ljava/lang/String;) Ljava/lang/StringBuilder;
30 0x000005d4 NONE FUNC Ljava/lang/StringBuilder.method.toString()Ljava/lang/String;
31 0x000005dc NONE FUNC Ljava/lang/System.method.exit(I)V
32 0x000005e4 NONE FUNC Ljava/lang/System.method.getenv(Ljava/lang/String;)Ljava/lang/String;
33 0x000005ec NONE FUNC Ljavax/crypto/Cipher.method.doFinal([B)[B
34 0x000005f4 NONE FUNC Ljavax/crypto/Cipher.method.getInstance(Ljava/lang/String;) Ljavax/crypto/Cipher;
35 0x000005fc NONE FUNC Ljavax/crypto/Cipher.method.init(ILjava/security/Key;)V
36 0x00000604 NONE FUNC Ljavax/crypto/spec/SecretKeySpec.method.<init>([BLjava/lang/String;)V
Uma abordagem comum ao inspecionar um binário é procurar por algo, navegar até ele e visualizá-lo para interpretar o código. Uma das maneiras de encontrar algo usando radare2 é filtrando a saída de comandos específicos, ou seja, usando grep neles com ~ mais uma palavra-chave (~+ para não diferenciar maiúsculas de minúsculas). Por exemplo, podemos saber que o aplicativo está verificando algo, podemos inspecionar todas as flags do radare2 e ver onde encontramos algo relacionado a "verify".
Ao carregar um arquivo, o radare2 marca tudo o que consegue encontrar. Esses nomes ou referências marcados são chamados de flags. Você pode acessá-los via o comando
f.
Neste caso, vamos usar grep nas flags usando a palavra-chave "verify":
[0x000009c8]> f~+verify
0x00000a38 132 sym.Lsg_vantagepoint_uncrackable1_MainActivity.method. \
verify_Landroid_view_View__V
0x00000a38 132 method.public.Lsg_vantagepoint_uncrackable1_MainActivity. \
Lsg_vantagepoint_uncrackable1
_MainActivity.method.verify_Landroid_view_View__V
0x00001400 6 str.verify
Parece que encontramos um método em 0x00000a38 (que foi marcado duas vezes) e uma string em 0x00001400. Vamos navegar (seek) para esse método usando sua flag:
[0x000009c8]> s sym.Lsg_vantagepoint_uncrackable1_MainActivity.method. \
verify_Landroid_view_View__V
E, claro, você também pode usar as capacidades de desmontagem do r2 e imprimir a desmontagem com o comando pd (ou pdf se você souber que já está localizado em uma função).
[0x00000a38]> pd
Os comandos do r2 normalmente aceitam opções (veja pd?), por exemplo, você pode limitar os opcodes exibidos anexando um número ("N") ao comando pd N.

Em vez de apenas imprimir a desmontagem no console, você pode entrar no chamado Modo Visual digitando V.

Por padrão, você verá a visualização hexadecimal. Digitando p você pode alternar para diferentes visualizações, como a visualização de desmontagem:

O Radare2 oferece um Modo Gráfico que é muito útil para seguir o fluxo do código. Você pode acessá-lo a partir do Modo Visual digitando V:

Esta é apenas uma seleção de alguns comandos do radare2 para começar a obter algumas informações básicas de binários Android. O Radare2 é muito poderoso e tem dezenas de comandos que você pode encontrar na documentação de comandos do radare2. O Radare2 será usado ao longo do guia para diferentes finalidades, como reverter código, depurar ou realizar análise binária. Também o usaremos em combinação com outros frameworks, especialmente Frida (consulte a seção r2frida para mais informações).
Consulte Desmontagem de Native Code para um uso mais detalhado do radare2 no Android, especialmente ao analisar bibliotecas nativas. Você também pode querer ler o livro oficial do radare2.