FART: Solução Automatizada de Desempacotamento Baseada em Invocação Ativa em Ambiente ART

Fluxo de Inicialização do Aplicativo

A criação de um processo de aplicativo no Android inicia no processo Zygote, culminando na execução do método ActivityThread.main(). Este ponto de entrada configura o loop de mensagens principal e inicializa o ambiente da aplicação.

// Criar instância do ActivityThread
ActivityThread instance = new ActivityThread();
instance.attach(false);

// Iniciar o loop de mensagens
Looper.loop();

}


</div>O método `handleBindApplication` é invocado quando o sistema vincula os dados da aplicação. Neste ponto, ocorre a inicialização do `Application`, incluindo a chamada aos métodos `attachBaseContext` e `onCreate`. Ferramentas de proteção frequentemente substituem a classe `Application` para inserir lógica de desempacotamento nesses métodos.

Princípio de Empacotamento e Fluxo de Execução
----------------------------------------------

O empacotamento envolve criptografar os DEX e injetar código de desempacotamento na classe `Application`. Durante a execução, o shell descriptografa os DEX na memória, carrega-os via um `ClassLoader` customizado e utiliza reflexão para corrigir variáveis críticas, especialmente o `ClassLoader` da aplicação.

Para contramedidas contra despejo de memória, shells avançados implementam desempacotamento por instruções, descriptografando métodos apenas durante a execução. Esta técnica dificulta a obtenção do DEX completo.

Ferramentas de Desempacotamento em ART e Limitações
---------------------------------------------------

Técnicas existentes incluem despejo durante a compilação `dex2oat`, interceptação de estruturas `DexFile` na memória, e hooking de funções de carregamento. No entanto, muitas destas abordagens falham contra shells que empregam desempacotamento por instruções.

A proposta ativa de métodos, como implementada no FUPK3 para Dalvik, engana o shell executando métodos de forma controlada, forçando a descriptografia. Com a transição para ART, surgiu a necessidade de uma solução equivalente.

Princípio e Implementação do FART
---------------------------------

O FART opera em três etapas principais:

1. Despejo completo do DEX a partir da estrutura `DexFile` na memória.
2. Invocação ativa de métodos para despejar seus `CodeItem`s.
3. Reparo dos métodos extraídos utilizando os dados coletados.

### 1. Despejo da Estrutura DexFile

O ponto de coleta é dentro de `ActivityThread.performLaunchActivity`, após a inicialização completa do `Application`. Obtém-se o `ClassLoader` final e inicia uma nova thread para operações demoradas.

<div class="code-block">```
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // ... código existente ...
    ClassLoader cl = r.packageInfo.getClassLoader();
    final ClassLoader appClassLoader = mInitialApplication.getClassLoader();
    
    new Thread(() -> {
        dumpDexFilesViaReflection(appClassLoader);
    }).start();
    // ... continuação ...
}
    int fd = open(convertJString(env, path), O_WRONLY | O_CREAT, 0666);
    write(fd, data, size);
    close(fd);
}

}


</div>### 2. Invocação Ativa de Métodos

A invocação ativa é inspirada no mecanismo JNI. Modifica-se `ArtMethod::Invoke` para detectar chamadas artificiais (através de um marcador, como `Thread*` nulo) e despejar o `CodeItem` do método.

<div class="code-block">```
void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, 
                       JValue* result, const char* shorty) {
    if (self == nullptr) { // Marcador de invocação ativa
        dumpMethodCodeItem(this);
        return;
    }
    // ... implementação original ...
}

void ArtMethod::invokeArtificially(ArtMethod* method) {
    JValue unused_result;
    uint32_t placeholder_args = 0;
    method->Invoke(nullptr, &placeholder_args, 0, &unused_result, "V");
}

3. Reparo dos Métodos Extraídos

Um script Python recombina os CodeItems despejados com o arquivo DEX, corrigindo os métodos cujo código foi extraído pelo shell.

# Ler metadados dos CodeItems despejados
for method_code in read_code_items(output_dir):
    method_id = locate_method(dex_data, method_code)
    replace_code_item(dex_data, method_id, method_code.content)

with open(dex_path + '.repaired', 'wb') as f:
    f.write(dex_data)

</div>Uso e Configuração
------------------

O proceso envolve criar um arquivo de configuração com o nome do pacote e o caminho de dados privados, instalá-lo no dispositivo, e iniciar a aplicação. O FART automaticamente despejará os DEX e `CodeItem`s durante a inicialização da `Activity` principal. Os arquivos resultantes são então combinados offline usando o script de reparo.

Imagens de sistema pré-configuradas são fornecidas para emuladores e dispositivos físicos (como Nexus 5) para facilitar testes.

Tags: android ART Runtime DEX Desempacotamento Segurança de Aplicativos

Publicado em 6-13 16:39 por Thomas