Skip to content

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.