Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

04 - Engenharia Reversa e Extração de Configurações

video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione video: https://youtu.be/... no frontmatter da nota.

Engenharia Reversa e Extração de Configurações

Nota 04 do capítulo 25, dedicada à engenharia reversa com foco em CTI, onde o objetivo não é entender todo o binário, e sim extrair o que sustenta o caso.
A extração de configuração, com C2s, identificadores de campanha e chaves, é o produto de maior valor analítico da engenharia reversa aplicada.
Dialoga com as notas 02 e 03, com o agrupamento de campanhas do capítulo 05 e com as regras YARA da nota 05.

1. Contexto e Posicionamento na Biblioteca

A engenharia reversa aplicada a CTI tem um objetivo estreito e produtivo: extrair do binário o que as camadas de triagem, estática e dinâmica não conseguiram entregar. Em quase todos os casos práticos, isso significa uma coisa, a configuração do malware, o bloco de dados decifrado em runtime que carrega endpoints de C2, identificadores de build e campanha, chaves criptográficas, endereços de carteira e parâmetros operacionais. A configuração é o elo vivo entre a amostra e a infraestrutura da campanha, e é ela que permite ao analista rastrear a operação do adversário ao longo das semanas seguintes, muito depois de o hash da amostra ter perdido valor.

O posicionamento na esteira do capítulo é o de camada mais custosa e seletiva. A triagem da nota 01 classificou, a estática da nota 02 extraiu o que o arquivo entrega parado, a dinâmica da nota 03 capturou o comportamento; a engenharia reversa entra quando o esforço adicional se paga, tipicamente em amostras evasivas, em configurações cifradas com chave derivada, e em campanhas que a organização precisa acompanhar por tempo longo. A decisão de investir é de gestão de esforço, e a seção 6 formaliza critérios para essa decisão, porque horas de reversão são sempre um custo de oportunidade frente a outras filas da equipe.

2. O Que Procurar: Funções Críticas no Binário

A reversão voltada a CTI não desmonta o binário linearmente, e sim caça funções específicas cuja presença é predizível por convenção de desenvolvimento de malware. O fluxo típico de um loader organiza o código em blocos reconhecíveis, e identificar o bloco certo reduz horas de análise. Os alvos prioritários estão listados abaixo, com a pista estática que costuma apontar para cada um.

  • Rotina de decifração de configuração: identificada pela chamada a CryptDecrypt, por implementações manuais de RC4 ou AES visíveis como laços de deslocamento e XOR, ou por acesso ao bloco de dados de alta entropia visto na nota 02.
  • Resolução dinâmica de APIs: identificada por LoadLibraryA e GetProcAddress em laço, que reconstrói os nomes de função escondidos da IAT e desbloqueia a leitura do restante do código.
  • Rotina de comunicação com C2: identificada por strings de URIs, por chamadas a WinHTTP ou sockets, e pelo empacotamento dos dados enviados.
  • Rotina de desempacotamento do payload: identificada por VirtualAlloc seguida de cópia e salto de execução, que define o tamanho do shellcode entregue.
  • Derivação de chave: identificada por uso de CryptDeriveKey, MD5 ou SHA sobre valores fixos do binário, que revela de onde a chave de config nasce.

O CAPA da Mandiant automatiza parte dessa caça, mapeando o binário contra um corpus de capacidades e apontando funções candidatas a injeção, persistência e comunicação de rede. No Ghidra, o FLIRT e as assinaturas da comunidade identificam funções de biblioteca e reduzem o ruído antes do foco manual, e o script de análise automática já entrega uma árvore de funções ordenada por referências cruzadas, que é o mapa inicial da caça.

3. Fluxo de Trabalho em Ghidra e IDA

O fluxo profissional combina desmontagem estática com depuração assistida, porque a configuração frequentemente é decifrada com dados que só existem em execução. O roteiro abaixo assume Ghidra, mas transpõe diretamente para IDA Pro ou Binary Ninja, com comandos equivalentes de script.

# 1. Importar a amostra desempacotada herdada das notas anteriores
#    (binario extraido do recurso RCDATA na nota 02, ou dump da nota 03)
ghidra-headless analyzeHeadless ./projeto GhidraProj -import LDR_payload.bin

# 2. Aplicar assinaturas FLIRT e rodar o CAPA sobre o binario
capa LDR_payload.bin -f json > capa_report.json

# 3. Localizar a funcao que aponta para o bloco de config (xrefs do endereco
#    do bloco de alta entropia mapeado na nota 02) e renomear:
#    FUN_00402a10 -> ConfigDecrypt

# 4. Definir o tipo de retorno e exportar o pseudocodigo da funcao
#    (janela de decompilacao, exportar para evidencia do caso)

# 5. Executar a amostra no depurador com breakpoint na ConfigDecrypt
#    x64dbg: bp no endereco da funcao, dumpar o buffer apos o retorno

A combinação decisiva é o pseudocódigo do descompilador para entender a lógica e o depurador para obter os dados reais. A depuração deve ocorrer na mesma VM da nota 03, com snapshot e isolamento, pois o payload decifrado é executável vivo. O dump do buffer retornado pela ConfigDecrypt, salto em memória ou registro em disco, é o artefato que a seção seguinte transforma na configuração legível, e esse dump deve ser registrado na ficha do caso com hash próprio, mantendo a cadeia de evidências.

4. Configuração de Malware: Anatomia e Valor Analítico

A configuração é o parâmetro de fábrica da campanha: o operador do malware preenche campos num painel ou builder, o builder cifra o bloco e o embute no build, e cada vítima recebe o mesmo bloco. Essa estrutura tem consequência analítica direta, pois a configuração sobrevive a recompilações e a mudanças de empacotador, e portanto sustenta agrupamento de campanhas e rastreamento de infraestrutura com muito mais estabilidade que strings ou hashes. Os campos típicos e seu uso analítico estão na tabela abaixo.

Campo típico Conteúdo Uso em CTI
C2 e painel de exfiltração URLs, IPs, portas Infraestrutura para bloqueio, hunting de rede e monitoramento de registro de domínio
Campaign ID e build ID Identificadores alfanuméricos Agrupamento de amostras e correlação de vítimas no painel do adversário
Chave criptográfica Chave RC4, AES ou XOR Decifração de tráfego capturado e validação de config de outras amostras
Mutex e nome de serviço Strings de identidade Detecção de endpoint estável e identificação de família
Endereços de carteira Carteiras de substituição Vigilância financeira e correlação com campanhas de clippers
Intervalos e flags operacionais Sleep, retry, módulos habilitados Caracterização de versão e evolução do builder

O valor de longo prazo vem da série temporal: o mesmo build ID com C2 diferente indica rotação de infraestrutura; o C2 idêntico em builds diferentes indica reaproveitamento de painel; a chave criptográfica constante entre campanhas indica que o operador não rotaciona material, o que permite decifrar tráfego capturado historicamente. Essas leituras são exatamente o material que o agrupamento de campanhas do capítulo 05 consome, e nenhuma outra fonte da biblioteca produz essa visão com a mesma precisão.

5. Extractors Públicos e Scripts de Automação

A extração de configuração é problema resolvido o suficiente para ter ecossistema próprio, e o analista deve consultá-lo antes de investir em reversão manual. O MWCP, da Mandiant, padroniza parsers de configuração em Python, com um contrato de campos e testes; o MACE aborda o problema por similaridade, decifrando configs de novas amostras com base em parsers existentes; e o CAPE, da nota 03, executa extractors embutidos durante a sandbox e entrega a configuração no relatório quando a família é suportada. Repositórios comunitários de decodificadores, herdeiros do legado RATDecoders, cobrem as famílias de RAT e stealer mais difundidas.

# Esqueleto de parser MWCP para o stealer ficticio do caso, rodando sobre o
# dump do bloco de config obtido na secao 3. RC4 e o algoritmo identificado
# no pseudocodigo da ConfigDecrypt, com chave fixa de 16 bytes no binario.

from mwcp.parser import Parser
from mwcp import FileObject, reporting
from cryptography.hazmat.primitives.ciphers import Arc4

class SombraStealer(Parser):
    DESCRIPTION = "SombraStealer config extractor"
    AUTHOR = "Equipe de CTI"

    @classmethod
    def identify(cls, file_object: FileObject) -> bool:
        # Ancora de 8 bytes no inicio do bloco de config, vista na nota 02
        return file_object.data.startswith(bytes.fromhex("c65a1b90"))

    def run(self):
        data = self.file_object.data
        key = data[8:24]
        blob = data[24:]
        cipher = Arc4(key)
        plaintext = cipher.decrypt(blob)
        self.reporter.add_report_item("config", {
            "c2_panel": plaintext[0:64].split(b"\x00")[0].decode("utf-8", "ignore"),
            "campaign_id": plaintext[64:72].decode("utf-8", "ignore"),
            "rc4_key": key.hex(),
        })

O script ilustra o contrato básico de qualquer extractor: uma âncora de identificação estável, a decifração com a chave extraída ou embutida, e o mapeamento dos campos para uma estrutura padronizada. Quando a família não é suportada por nenhum extractor público, esse mesmo esqueleto é o destino da reversão manual, e o parser produzido entra no repositório interno ao lado das regras YARA da nota 05, formando o par de caracterização da família, regra para detectar e extractor para enriquecer.

6. Exemplo Documentado: Extração de Config do SombraStealer

O caso fictício que serve de fio condutor do capítulo fecha aqui. O payload extraído na nota 02 e detonado na nota 03 revelou, em memória, um bloco decifrado que o Procmon não explicava; a hipótese era configuração cifrada com RC4, sustentada pelo pseudocódigo da função renomeada ConfigDecrypt. O roteiro executado segue abaixo, com os achados documentados passo a passo.

# 1. Localizar o xref do bloco de alta entropia em .data (0x0043A120)
#    Ghidra: References to 0x0043A120 aponta para FUN_00402a10 (ConfigDecrypt)

# 2. Pseudocodigo da ConfigDecrypt mostra: chave = bytes 8 a 24 do bloco,
#    corpo decifrado com RC4, e retorno de struct com 6 campos

# 3. Dump do bloco bruto em x64dbg com breakpoint no retorno da funcao
#    Bloco de 0x1F8 bytes salvo como config_dump.bin

# 4. Decifragem local do dump com a chave extraída (script da secao 5)
python3 sombra_config_parser.py config_dump.bin

# 5. Validar C2 decifrado contra o trafego capturado na nota 03
#    POST /gate.php confirma o mesmo host e user-agent da config

A configuração decifrada produziu a ficha abaixo, registrada na evidência do caso com TLP:AMBER+STRICT herdado da triagem.

Campo Valor decifrado
Painel C2 hxxp://203.0.113.42:8085/gate
Backup C2 hxxp://198.51.100.77:8085/gate
Campaign ID SOM-BRT-2026-01
Build ID SG-2.4.1
Chave RC4 c65a1b90e3f2a7d4b6c8e0f1a2b3c4d5
Mutex Global\Sombra-Mtx-0142
Carteira de substituição bc1qexample9x8v7t6r5e4w3q2p1o0n9m8l7k6j5h4
Sleep 120 segundos

A leitura analítica da ficha demonstra o porquê do esforço. O Campaign ID SOM-BRT-2026-01 vincula a amostra à série de anexos de boleto do setor financeiro, confirmando a hipótese registrada na triagem da nota 01; o Build ID 2.4.1 permite buscar outras amostras da mesma versão em retrohunt da nota 05; e a chave RC4 decifra o tráfego capturado na nota 03, expondo o corpo das requisições de exfiltração de teste e confirmando o formato esperado pelo painel. O esforço total foi de meio dia de analista, e o retorno é a infraestrutura ativa da campanha, insumo que nenhuma camada anterior produziria.

7. Quando Vale o Esforço: Critérios de Decisão

A reversão custa dias e as filas da equipe não perdoam, então o critério de investimento precisa ser explícito e escrito. O esforço se paga quando pelo menos uma das condições abaixo é verdadeira, e a decisão deve ser registrada na ficha do caso, com o mesmo rigor da rota definida na triagem.

  • A amostra é de campanha direcionada contra a organização, com expectativa de recorrência e necessidade de rastrear infraestrutura por semanas.
  • A família é relevante para o setor, mas sem extractor público disponível, e o volume de amostras justifica construir o parser interno.
  • A sandbox da nota 03 foi evadida de forma sustentada, e a condição de evasão só se esclarece lendo o código.
  • A configuração decifrada desbloqueia outra investigação, como decifrar tráfego capturado ou vincular campanhas no agrupamento do capítulo 05.

O esforço não se paga quando a necessidade é responder a um incidente fechado com hash e bloqueios, quando um extractor público cobre a família, ou quando a curiosidade técnica é o único motor. Nessas situações, a estática e a dinâmica já entregam o IOC suficiente, e a reversão entra como dívida técnica registrada para um momento de menor pressão, e não como desvio da fila.

8. Erros Comuns e Pontos de Atenção

O erro mais custoso é entrar em reversão sem hipótese, desmontando o binário linearmente na esperança de entender tudo. A reversão voltada a CTI é caça dirigida por pistas estáticas e dinâmicas, e o analista que não anota os endereços dos blocos de alta entropia e os xrefs antes de abrir o descompilador gasta o primeiro turno apenas reencontrando o que as notas anteriores já sabiam. O erro simétrico é confiar no dump de memória sem validação: buffers decifrados em runtime podem conter lixo de execução, e a validação contra tráfego capturado ou contra segunda amostra é obrigatória antes de disseminar campos como IOC.

Completam a lista os itens abaixo.

  • Reverter a amostra empacotada em vez do payload desempacotado herdado da nota 02, gastando horas contra o packer em vez de contra a lógica.
  • Esquecer que o depurador executa código vivo, rodando a depuração fora da VM isolada da nota 03.
  • Publicar chave de configuração e Campaign ID sem passar pelo filtro do TLP do caso, entregando ao adversário o formato que o denuncia.
  • Tratar extractor público como veredito automático, sem conferir se a versão do parser cobre a versão do build analisado.
  • Não versionar o parser interno produzido, perdendo o investimento quando a próxima amostra da família chegar.
  • Assumir que campos vazios na config significam análise errada, quando a flag desabilitada no builder é explicação frequente.

9. Integração com o Restante da Biblioteca

A configuração extraída é o insumo de maior densidade analítica que a esteira do capítulo produz, e seu destino atravessa a biblioteca. No capítulo 05, os Campaign IDs e a rotação de C2 alimentam o agrupamento de campanhas e a análise de infraestrutura adversária; no capítulo 03, os endpoints decifrados entram no ciclo de vida de IOCs com contexto e confiança altos, pois vieram do próprio binário em vez de feeds de terceiros; e no capítulo 08, os campos de infraestrutura viram hipóteses de caça em DNS, HTTP e TLS.

Na camada de detecção e resposta, o par regra YARA da nota 05 e parser da família forma o pacote de caracterização que o PRT.5 implanta e que o capítulo 18 versiona como código. O SIM.4 recebe os campos de config como material de teste de detecção de IOCs, e a resposta a incidente do capítulo 13 consulta a ficha de configuração para saber o que buscar nos hosts afetados, do mutex à carteira de substituição. O ciclo se fecha quando a próxima variante da família chega à triagem da nota 01 e a ficha do caso anterior acelera a rota, transformando o investimento em reversão em vantagem cumulativa da equipe.