Baixe o app para aproveitar ainda mais
Prévia do material em texto
Disciplina Análise de Malware Apresentação Olá alunos, sejam muito bem-vindos na disciplina de análise de malware. Será um prazer percorrer essa jornada com vocês e tenho certeza que será um tempo de muito aprendizado. Saiba que este material foi preparado com muito cuidado para que essa jornada possa ser a mais tranquila possível. Este curso não visa torná-lo um analista, pois sabemos que, para isso, seriam necessários anos de aperfeiçoamento e dedicação. Nossa pretensão é dar uma visão geral e desmistificar nesta grande área da Segurança Cibernética. Essa disciplina, permeia outras grandes ciências e possui diversos requisitos necessários. Não será uma jornada simples, mas estaremos ao seu lado para poder conduzir da melhor forma. Ao final, você será capaz de saber analisar e identificar os tipos de ameaças dos códigos e dos programas maliciosos que impactam na segurança dos sistemas computacionais. Objetivos • Identificar os tipos de ameaças dos códigos e dos programas maliciosos que impactam na segurança dos sistemas computacionais; • Analisar o comportamento dos malwares e conhecer as implicações nos sistemas onde eles residam; • Conhecer as principais técnicas utilizadas para a análise de malwares. Aula 1: Conceitos de Malware Apresentação Nesta primeira aula desmistificaremos o conceito de malwares, assunto que normalmente é tratado com certo medo. Toda linha de código criada com um intuito malicioso pode ser considerado como um malware, portanto saber identificar suas intenções e seu alcance é vital para o analista. Definiremos, também, os principais tipos categorizados e, por fim, faremos uma visão geral da análise estática e dinâmica. Objetivo • Descrever conceitos básicos sobre análise de malware; • Identificar diferenças entre os tipos de malwares existentes; • Distinguir a diferença entre análise dinâmica e estática. Introdução Este conteúdo não visa torná-lo um analista, pois sabemos que, para isso, seriam necessários anos de aperfeiçoamento e dedicação. Nossa pretensão é dar uma visão geral e desmistificar esta área da Segurança Cibernética, que permeia outras grandes áreas e possui diversos requisitos necessários. Ao final, você será capaz de analisar e identificar os tipos de ameaças dos códigos e dos programas maliciosos que impactam na segurança dos sistemas computacionais. Fonte: Adaptado de Freepik Malware: Ameaças Cibernéticas A Internet mudou completamente a indústria de computadores e dos aspectos relacionados à segurança da computação. Softwares maliciosos se espalham rapidamente em um mundo onde bilhões de usuários estão conectados à Internet e usam e-mail, trocam mensagens instantâneas e compartilham dados diariamente. Basta imaginar que, há alguns anos, um malware necessitava de um disquete para ser carregado em outro computador para se propagar, com isso podemos entender o porquê de uma infecção demorar semanas ou meses para atingir milhares de máquinas. O processo de infecção era bastante lento e a defesa muito mais simples, pois os canais de infecção eram poucos e exigiam intervenção humana para que o programa se propagasse. No entanto, hoje isso mudou muito, a Internet criou uma conexão virtual entre quase todos os computadores do planeta. Atualmente, os malwares modernos podem se espalhar automaticamente para milhões de computadores sem qualquer intervenção humana. Fonte: Adaptado de Unsplash E é neste contexto que o analista atua, mas antes de entrarmos nos detalhes de como analisar malwares e resolver todos estes problemas, faz-se necessário definir algumas terminologias, categorizar os tipos mais comuns existentes e, por fim, apresentar as metodologias e formas de abordagem fundamental para sua análise. Um aspecto fundamental de uma boa análise é definir qual o objetivo a ser alcançado. Vamos desenhar um caso genérico: Exemplo João Wannacry é analista de malware da empresa Vulnerável S.A. Houve um grande vazamento de dados e diversas informações que deveriam ser acessadas apenas por algumas pessoas, tornou-se público. O chefe convoca uma reunião cobrando por respostas. João utiliza a solução de antivírus da empresa que localiza algumas máquinas contaminadas. Com isso, ele deleta os arquivos infectados, cria uma assinatura do malware no sistema de detecção de invasões, para realizar bloqueios automáticos em caso de reuso do mesmo e, por fim, faz algumas atualizações de segurança em possíveis sistemas vulneráveis. Será que esses procedimentos serão suficientes para prevenir um futuro vazamento? Dado o cenário proposto, vamos fazer algumas ponderações. De modo geral, a equipe de segurança deve fornecer os indícios para que a empresa possa entender e identificar o porquê, quando e onde de uma possível ocorrência de uma invasão. 1 Por que Qual a motivação do atacante para acessar os computadores da empresa? 2 Quando A quanto tempo os atacantes estão dentro da empresa? Qual foi a primeira invasão? 3 Onde Quais máquinas e que usuários foram comprometidos? A que tipo de informação os atacantes podem ter tido acesso? A partir das respostas será possível um melhor entendimento quanto à identificação da porta de entrada e à mitigação do ataque a fim de que ele não ocorra novamente. Para que esse objetivo seja alcançado, é necessário determinar exatamente o que aconteceu e garantir que foram localizadas todas as máquinas e arquivos afetados. Prosseguindo com o exemplo: Exemplo A equipe de segurança da rede fez uma análise sumária e encontrou alguns arquivos suspeitos. Vamos chamá-los de artefatos, pois ainda não sabemos se tais arquivos são maliciosos ou não. Ao analisar os artefatos suspeitos, seu objetivo será determinar: O que ele pode fazer Seja criar conexões, seja armazenar todas as teclas digitadas, seja criptografar os dados, dentre outros;. Como detectá-lo em na rede Gerar assinatura para futuras detecções e rápida mitigação. Como medir e conter seus danos Entender todas as ações desencadeadas pelo artefato, gerando um mapeamento de todos os danos gerados. Conceitos Agora que você já se familiarizou com o nível e o tipo de cobrança de um analista, é importante diferenciar alguns conceitos que normalmente causam confusão em seu uso. Vamos diferenciar malware, vulnerabilidade e exploit. Malware Tivemos o cuidado de utilizar a palavra “malware” em vez do que popularmente chamamos vírus, pois, como veremos mais a frente, o vírus é apenas um dos tipos de malware. Fonte: Adaptado do Autor. A palavra “malware” vem da junção de duas palavras em inglês – malicious (malicioso) + software (aplicação), ou seja, considera-se um malware qualquer pedaço de algo que faça ações maliciosas que venham prejudicar o usuário, o computador ou a rede. Embora o malware apareça de muitas formas diferentes, técnicas comuns são usadas para sua análise. A escolha da técnica a ser empregada dependerá de seus objetivos. Existem diversos tipos de malware, conforme abordaremos mais à frente. Cada malware possui aspectos únicos, assim como um programa legítimo. Por exemplo, existem diversos tipos de editores de texto, mas cada um possui opções e recursos diferentes que os tornam únicos. Essa analogia também se aplica aos artefatos maliciosos. No caso hipotético apresentado anteriormente, João Wannacry criou uma assinatura dentro do sistema de detecção de invasão (IDS), o que isso significa? Existem dois tipos de assinaturas ou indicadores: Assinaturas baseadas em ativos ou host São usados para detectar código malicioso em computadores de vítimas. Esses indicadores costumam identificar arquivos criados ou modificados pelo malware e/ou alterações específicas que ele realiza no registro. Basicamente, os indicadores de malware focam no que o malware faz a um sistema e não nas características do malware em si. Dessa forma, torna-se mais eficaz a detecçãode malware que tente mudar de forma mesmo após ter sido excluído do disco rígido. Assinaturas de rede São usadas para detectar códigos maliciosos por meio do monitoramento do tráfego da rede. As assinaturas de rede podem ser criadas sem análise de malware, mas assinaturas criadas com a ajuda de análise de malware são geralmente muito mais eficazes, pois oferecem uma taxa de detecção mais alta e menos falsos positivos. Trata-se da verificação de domínios requisitados pelo malware, tentativas de conexões ou downloads por ele realizadas e o futuro bloqueio de qualquer tráfego de/para esses destinos. Depois de obter as assinaturas, o objetivo final é descobrir exatamente como o malware funciona. Frequentemente, essa é a pergunta mais feita pelos chefes que desejam uma explicação completa e rica em detalhes de uma invasão. Fonte: madartzgraphics / Pixabay. https://stecine.azureedge.net/webaula/estacio/go0682/aula1.html#collapse01-01 https://stecine.azureedge.net/webaula/estacio/go0682/aula1.html#collapse01-02 Vulnerabilidade Vulnerabilidade é uma falha no sistema que permite a um atacante usá-lo de uma forma não prevista pelo projetista (ANLEY, 2007). Portanto, é por meio da vulnerabilidade que se obtém a possibilidade de uso indevido de um sistema. De modo geral, existem três causas que podem ser consideradas como causas básicas, a saber: • Falhas de design do projeto Quando da concepção de funcionamento de determinado sistema ou aplicação ; (Rev. MC) acertar alinhamento dos itens 1, 2 e 3. • Erros de implementação Uso de funções ou códigos vulneráveis e que possam causar um fluxo diferentemente do planejado • Erros de configuração ou de infraestrutura do sistema Sistemas que possuam baixo nível de controle ou falta de uso de controles de segurança. Exploit O conjunto de códigos e/ou passos necessários para explorar uma vulnerabilidade é conhecido como exploit, (ANLEY, 2007). O expoit é possível apenas quando existe uma vulnerabilidade, porém ressalta- se que podem existir vulnerabilidades para as quais não exista um exploit. Fonte: Adaptado de Freepik. Tipos de malwares Durante uma análise de malware, é possível acelerar alguns processos se for com que tipo de malware estamos lidando. Com isso, são feitas suposições fundamentadas sobre as atividades dele, o que facilita a análise. Esse tipo de experiência é adquirido ao longo do tempo; você será capaz de fazer suposições cada vez melhores a partir da identificação do tipo de malware, facilitando associações e validações. Saiba mais Veja a lista com tipos de categorias em que a maioria dos malwares se enquadra, conforme Sikorski (2012). Os malwares geralmente abrangem várias categorias. Por exemplo, um programa pode ter um keylogger que coleta as senhas e possuir um componente worm que envia spam. Não se preocupe em classificar malware de acordo com sua funcionalidade, como já mencionado, essa classificação existe como auxílio no processo de análise do mesmo. Outra classificação possível pode ser feita com base no objetivo do invasor: Malware em massa Malwares como o Scareware possuem o objetivo do tipo “em massa” e são projetados para afetar o maior número de máquinas possível. Dos dois objetivos, o malware em massa é o mais comum e, geralmente, o menos sofisticado e mais fácil de ser detectado e combatido porque o software de segurança o tem como alvo. Malware com alvo específico O malware direcionado é criado sob demanda para uma organização específica. Trata-se de uma ameaça maior às redes do que o malware em massa, porque não é generalizado e os produtos de javascript:void(0); javascript:void(0); https://stecine.azureedge.net/webaula/estacio/go0682/aula1.html#collapse01-03 https://stecine.azureedge.net/webaula/estacio/go0682/aula1.html#collapse01-04 segurança provavelmente não possuem sua assinatura e não serão capazes de criar uma proteção contra eles. Sem uma análise detalhada do malware direcionado, é quase impossível proteger a rede contra esse tipo de ameaça e remover infecções realizadas. Trata-se de algo geralmente muito sofisticado e sua análise frequentemente exigirá habilidades de análise avançadas. Análise de malwares – Ransomware Os ransomwares são malwares que, ao infectar um computador, podem bloquear o acesso do usuário ou criptografar dados importantes. Uma vez bem-sucedidos, cobram uma quantia para liberar o acesso ao usuário. Esse tipo de ameaça tem se tornado cada vez mais comum. Saiba mais Casos de infecção de ransomware foram vistos pela primeira vez na Rússia entre 2005-2006. Foi publicado um relatório pela Trend Micro sobre um caso em 2006 que envolvia uma variante de ransomware que compactava certos tipos de arquivos antes de sobrescrever os originais, deixando apenas os arquivos .zip protegidos por senha no sistema do usuário. Por fim, gerava-se um arquivo de texto que funcionava como a nota de resgate informando aos usuários que os arquivos poderiam ser recuperados em troca de $300. Em seus primeiros anos O ransomware normalmente criptografava determinados tipos de arquivo, como .doc, .xls, .jpg .zip, .pdf e outras extensões de arquivo comumente usadas. compare_ arrows Pouco tempo depois Surgiram outros tipos que infectavam o Master Boot Record (MBR) de um sistema vulnerável, evitando que o sistema operacional fosse sequer carregado. Ao ser reiniciado, o sistema infectado exibia a notificação ao usuário e exigia o resgate para devolver o acesso ao usuário da máquina. Comentário Esse tipo de ameaça tem se tornado cada vez mais presente em nosso dia a dia, sem definição de alvos: podendo ser usuários comuns, pequenas e médias empresas, ou grandes redes de hospitais. Possui uma enorme capacidade evolutiva, no que concerne às técnicas de bloqueio de estratégias de defesa; aumentando assim, sua resistência e capacidade de obter sucesso na extorsão. ondemand_videoVídeo Estratégias de ataque Ao realizar uma análise, sua equipe terá, na maioria dos casos, apenas o arquivo executável do malware. Cabe ressaltar que um arquivo binário, caso nunca tenha visto um, não é legível. Assim, para entender seu fluxo e suas intenções, é preciso usar uma variedade de ferramentas e técnicas para montar um quebra-cabeça com cada uma das informações adquiridas. Quanto mais ferramentas e técnicas forem utilizadas mais nítida a imagem ficará. Duas abordagens são consideradas fundamentais dentro da análise de artefatos: estática e dinâmica: 1 Análise estática Envolve examinar o malware sem executá-lo. 2 Análise dinâmica Envolve a execução do malware. Ambas as técnicas ainda podem ser categorizadas como básicas ou avançadas. A seguir vamos conceituar cada uma destas . ondemand_videoVídeo ondemand_videoVídeo Análise Estática Básica A análise estática básica consiste em examinar o arquivo executável sem visualizar as instruções propriamente ditas. A análise estática básica pode (depende muito das situações) confirmar se um arquivo é malicioso, fornecer informações sobre sua funcionalidade e, às vezes, fornecer informações que permitirão que você produza assinaturas de rede simples. Uma característica vital deste tipo de análise é sua velocidade de pronta resposta, porém pode ser (e geralmente é) ineficaz contra artefatos sofisticados. Análise Dinâmica Básica A análise dinâmica básica consiste em executar o artefato e observar seu comportamento no sistema. Simples, certo? Com isso é possível produzir assinaturas eficazes e entender a dinâmica produzida pelo mesmo. No entanto, surge a seguinte questão: “devo executar um vírus em meu computador?” A resposta é sim, mas antes é preciso criar um ambiente seguro. Para isso, você deve configurar um ambiente que permita estudar o artefato em execução sem que haja risco de danos ao sistema ou rede. https://stecine.azureedge.net/webaula/estacio/go0682/aula1.html#collapse01-06 https://stecine.azureedge.net/webaula/estacio/go0682/aula1.html#collapse01-07Análise Estática Avançada É um tipo de análise que requer um nível mais elevado de conhecimento. A análise estática avançada consiste na engenharia reversa dos componentes internos do artefato. Vale ressaltar que artefatos complexos possuem centenas de milhares de instruções as quais devem ser analisadas. Para isso, utilizam-se ferramentas de depuração para analisar o código da aplicação e, com isso, entender o fluxo do binário ao qual se está analisando. No entanto, ressalta-se que estamos falando de uma outra área da Segurança da Informação que já mencionamos anteriormente: Engenharia reversa. Ela por si só seria um curso completo a parte. Com isso, podemos concluir que a análise estática avançada possui uma curva de aprendizado mais íngreme do que a análise estática básica e requer um conhecimento especializado de programação, arquitetura de computadores e conceitos de sistemas operacionais, os quais não abordaremos em profundidade. Análise Dinâmica Avançada Com auxílio de ferramentas de depuração (em inglês: Debugges examina-e o estado interno de um executável malicioso em execução, acompanhando o passo a passo de sua execução e entendendo sua dinâmica, literalmente. Artefatos sofisticados, em sua esmagadora maioria, estão ofuscados, ou seja, em seu estado original não se pode identificar suas reais intenções. Em algum momento o artefato revelará suas reais instruções, então o analista verificará e identificará o seu conteúdo. As técnicas avançadas de análise dinâmica fornecem outra maneira de extrair informações detalhadas de um executável. Faremos algumas demonstrações de como usar a análise dinâmica avançada junto a análise estática avançada para analisar um artefato. Aula 2: Análise Estática e Dinâmica Básica Apresentação Após consolidados os conceitos mínimos necessários, abordaremos as técnicas básicas utilizadas para fazer uma análise estática e dinâmica eficaz. https://stecine.azureedge.net/webaula/estacio/go0682/aula1.html#collapse01-08 https://stecine.azureedge.net/webaula/estacio/go0682/aula1.html#collapse01-09 Veremos, também, formas seguras para execução de artefatos maliciosos. Objetivo • Identificar as técnicas de análise de estáticas básicas; • Explicar os conceitos de uma máquina virtual; • Identificar as técnicas de análise de dinâmicas básicas. Análise básica Começamos nossa jornada da análise de malware com análise estática, que normalmente é a primeira etapa no estudo de malware. Essa análise descreve o processo de análise do código e da estrutura de um programa para determinar seu fluxo e suas intenções. O programa em si não é executado neste momento, isso ocorrerá durante a análise dinâmica. Técnicas de análise estática básica Apresentaremos algumas formas de extrair informações úteis de executáveis, discutindo as seguintes técnicas: Uso de antivírus para verificação do binário. Uso de algoritmos de hashes para identificá-lo. Coleta de informações usando ferramentas e leitura do cabeçalho. Como já vimos em outra ocasião, cada técnica pode fornecer informações diferentes como pequenas peças de um quebra-cabeça. Cabe ao analista juntá-las e montar o cenário propício para as respostas desejadas. Antivírus O primeiro passo ao analisar um artefato suspeito é executar uma checagem por meio de antivírus; alguém já pode ter feito o trabalho manual e catalogado o referido malware. Atenção Porém, cabe a ressalva de que não se trata de uma solução perfeita; não se pode afirmar que um binário é legítimo unicamente porque não foi reconhecido por um software de antivírus comercial. O antivírus se baseia na assinatura de arquivos e em análises comportamentais.| Fonte: TheDigitalArtist / Pixabay. De maneira geral, o antivírus se baseia em dois aspectos: Assinatura de arquivos Tais programas dependem, de maneira geral, de um banco de dados de funções e ações maliciosas de códigos suspeitos já conhecidos, que chamaremos de assinaturas de arquivos. Análises comportamentais Outro ponto é que os antivírus baseiam-se em análises comportamentais e de correspondência de padrões, as chamadas heurísticas, para identificar arquivos suspeitos. Vejamos alguns aspectos que são pontos de atenção em relação ao antivírus: • Tempo limitado O antivírus tem um tempo limitado para realizar um teste em um novo arquivo, bem como um tempo e recurso limitado para dar uma resposta satisfatória ao usuário. • Desatualização Um grande calcanhar de Aquiles dessa solução é a facilidade dos atacantes em modificar seu código, alterando assim a assinatura de seu programa e https://stecine.azureedge.net/webaula/estacio/go0682/aula2.html#collapse01-01 https://stecine.azureedge.net/webaula/estacio/go0682/aula2.html#collapse01-02 criando um artefato completamente novo, que muitas vezes não é detectado pelo software de antivírus, pois simplesmente não está no banco de dados. • Heurística contornável Por fim, a heurística, embora muitas vezes bem- sucedida na identificação de código malicioso desconhecido, pode ser contornada por meio de sistemas de proteção a análises. • Eficácia relativa Cada sistema de antivírus funciona de uma forma diferente, analisando o binário com uma heurística distinta e com diversas assinaturas. Portanto, é útil analisar o artefato em vários programas antivírus diferentes. Dica Para não obrigar a sua empresa a comprar diversas soluções diferentes, existem sites como o VirusTotal (http://www.virustotal.com/), que permitem que você carregue um arquivo para varredura por vários mecanismos antivírus. Atenção Muito cuidado, não existe almoço grátis. Se o produto oferecido é grátis, a empresa tem outra fonte de renda. Portanto, em hipótese alguma submeta arquivos sensíveis a esses sites, pois você estará expondo sua empresa. Se não for o caso de informação sensível, esse tipo de solução é bastante útil. O VirusTotal, por exemplo, gera um relatório que fornece o número total de mecanismos que marcaram o arquivo como malicioso, o nome do malware e, se disponível, informações adicionais. Fonte: VirusTotal (2020). Figura 1 - Site do VirusTotal javascript:void(0); Hashing O hash é um método comum usado para identificar qualquer tipo de arquivo de forma exclusiva. Um algoritmo hash é uma função que converte uma sequência de dados em uma saída numérica hexadecimal de comprimento fixo. O artefato é submetido a essa função, que produz uma sequência exclusiva identificando o mesmo, uma espécie de impressão digital. Comentário Existem casos em que pode haver colisões da saída do hash, porém são raros. Existem diversos tipos de funções hash; para nosso estudo de caso, utilizaremos a função Message-DigestAlgorithm 5 (MD5). Por meio do programa certutil, disponível gratuitamente e que acompanha o Windows 10, calculamos o hash do programa calc.exe, também disponível no Windows: sintaxe: certutil -hashfile<arquivo a ser processado><tipo de algoritmo> comando: certutil -hashfile C:\Windows\System32\calc.exe md5 Fonte: o Autor. Figura 2 - Hash Calc.exe O hash MD5 de calc.exe é: 5da8c98136d98dfec4716edd79c7145f. De posse desse valor único é boa prática que o artefato seja identificado por ele, e que seu valor seja compartilhado com outros analistas para futuras referências, bem como seja feita uma busca online pelo hash para verificar se tal artefato já foi identificado. Strings Uma string é uma sequência de caracteres. Um programa contém strings se: 1 Contiver uma mensagem a ser impressa. 2 Conectar a uma URL ou, ainda. 3 Copiar um arquivo para um local específico. Tais sequências deverão estar guardadas dentro do artefato. Pesquisar por essas informações pode ser uma maneira simples de obter dicas sobre a funcionalidade de um programa. Saiba mais Você pode usar o programa Strings para pesquisar em um executável por qualquer sequência de caracteres, normalmente armazenadas emformato ASCII ou Unicode. O uso da ferramenta é bem simples: Ao abrir um terminal, basta digitar o seguinte comando: sintaxe: strings.exe <opções><binário a ser analisado> O Strings procura em um executável por strings ignorando o contexto e a formatação, a fim de detectar strings em um arquivo inteiro. Por padrão, Strings procura uma sequência de três letras ou mais de caracteres, seguidos por um caractere de terminação de string (byte nulo). Fonte: o Autor. Figura 3 - Strings Calc.exe javascript:void(0); comando: strings.exe -n 10 c:\Windows\System32\calc.exe Realizando o comando com a opção -n 10, ou seja, tamanho mínimo da cadeia de 10 caracteres, podemos ver diversas informações: Nomes de funções, nomes de bibliotecas importadas e nomes de seções. Essas informações auxiliarão o analista durante sua investigação. Comentário A notação ASCII utiliza apenas 1 byte por caractere; já a notação Unicode utiliza 2 bytes. Em algumas situações, isso pode ser um fator decisivo para o sucesso de uma análise. O programa strings já realiza buscas tanto em ASCII quanto em Unicode. Artefatos maliciosos geralmente usam compactação ou ofuscação para tornar seus arquivos mais difíceis de serem analisados. Programas ofuscados são aqueles em que se tenta ocultar sua execução e programas compactados (ou empacotados); são um subconjunto de programas ofuscados nos quais o artefato é compactado e sua análise fica prejudicada. Ambas as técnicas limitarão a análise estática do artefato. Fonte: o Autor. Figura 4 - Programa original e Programa empacotado Ao executar um programa compactado, uma pequena rotina desempacotadora é executada para tornar o binário legível na memória. Portanto, podemos concluir que, ao analisar esse tipo de programa estaticamente, apenas esse pequeno trecho será legível. Essa é uma das técnicas de anti-análise que abordaremos mais adiante. Saiba mais A ferramenta PeiD auxilia na detecção de arquivos empacotados0 Podemos usar o PeiD para detectar o tipo de empacotador ou compilador empregado para construir um aplicativo, facilitando a análise do arquivo. Fonte: Peid (2020). Figura 5 - Uso do PeiD para detecção de empacotamento javascript:void(0); Indicadores de compromentimento (IoC) Indicadores de comprometimento (IoC), segundo a Microsoft, são eventos mal-intencionados conhecidos que indicam que uma rede ou um dispositivo já foi violado. Ao contrário de definições de alerta, esses indicadores são considerados como evidência de uma violação. Muitas vezes, eles são vistos depois que um ataque já foi executado e o objetivo foi atingido, como roubar os dados. Monitorar os IOCs também é importante durante as investigações forenses. Embora ele não possa fornecer a capacidade de intervir em uma cadeia de ataque, coletar esses indicadores pode ser útil na criação de defesas melhores para possíveis ataques futuros. Durante as análises é vital a descoberta e o registro de todos os IoC; assim será possível criar um conjunto de informações que culminarão em assinaturas a serem incorporadas nos sistemas de controle da rede. Tais assinaturas servirão de subsídios para geração de alertas para futuras invasões. Outras ferramentas de análise PEview Outra ferramenta fundamental para o analista é o PEview. Por meio dela é possível verificar a estrutura e o conteúdo não só de arquivos executáveis mas de DLL (Dynamic Link Library) e outros arquivos do tipo. javascript:void(0); Uma DLL é uma biblioteca com funções que podem ser acessadas por outros programas do computador, pois ela exporta a função implementada. ondemand_videoVídeo Dependency Walker A ferramenta Dependency Walker é utilizada para mostrar todas as dependências importadas e utilizadas pelo artefato. Ela não apenas informa as bibliotecas como também disponibiliza as funções importadas pelo binário, auxiliando no entendimento do comportamento do artefato através das chamadas do sistema. Análise de malware em máquinas virtuais Antes de executar qualquer artefato para realizar análises dinâmicas, devemos configurar um ambiente seguro. Por quê? Os malwares recentes podem ser cheios de surpresas; executá-lo em uma máquina de produção pode tornar-se o vetor de infecção de outras máquinas na rede. Um ambiente seguro permitirá que você investigue o malware sem expor sua máquina,ou outras máquinas na rede, a riscos inesperados e desnecessários. Para configurar um ambiente seguro, podemos usar máquinas físicas ou virtuais dedicadas para estudar artefatos com segurança. O malware pode ser analisado usando máquinas físicas individuais em redes isoladas com máquinas desconectadas da Internet ou de qualquer outra rede para evitar que o mesmo se espalhe. javascript:void(0); Máquina virtual As máquinas virtuais são como um computador dentro de um computador. Fonte: SIKORSKI (2012). Figura 6 - Componentes de uma máquina virtual Entre as vantagens desse modelo estão: Sistema operacional livre de risco Um sistema operacional convidado em uma máquina virtual é instalado e funciona de forma isolada dentro do sistema operacional da máquina física. Portanto, em tese, o artefato malicioso executado em uma máquina virtual não pode prejudicar o sistema operacional principal. Snapshots Outra grande vantagem da máquina virtual são os “snapshots”, em que se tira uma fotografia do estado atual da máquina e pode-se retornar a ela quando for da vontade do usuário. Logo, se um malware danificar a máquina virtual, você pode simplesmente reinstalar o sistema operacional na máquina virtual ou recuperar seu estado. https://stecine.azureedge.net/webaula/estacio/go0682/aula2.html#collapse01-03 https://stecine.azureedge.net/webaula/estacio/go0682/aula2.html#collapse01-04 Por outro lado, a máquina virtual conta possui as seguintes desvantagens: Ausência de conexão com a internet Muitos arquivos maliciosos dependem de uma conexão ativa para atualizações, comando, controle e outros recursos e, por isso, não se manifestam em ambientes virtualizados. Contudo, podemos utilizar alguns artifícios para minimizar essa desvantagem ocasionada por alguns artefatos protegidos em relação à análise. compare_ arrows Exigência de um computador de alto nível Outra desvantagem é a exigência de um bom equipamento para suportar mais de uma máquina ao mesmo tempo. Configuração da máquina virtual • Software e instalação Não fará parte dessa aula a escolha do virtualizador ou a instalação passo a passo de uma máquina virtual. Existem diversas opções para tal, sendo as soluções mais comuns Virtual Box e VMWare, ficando a critério do analista a escolha do software que mais se ajuste à necessidade. Outro ponto importante é a instalação das máquinas virtuais. O sistema operacional Windows é protegido por licença, o que impossibilita seu download indiscriminado na internet. Dica A própria Microsoft disponibiliza uma versão para desenvolvedor em seu site com uma licença de 90 dias para testes. Seu conteúdo pode ser acessado em: https://developer.microsoft.com/en-us/microsoft- edge/tools/vms/ As configurações da máquina devem ser ajustadas para que o usuário tenha uma boa experiência. Além disso, a máquina virtual, como já vimos, exige bom equipamento, capaz de suportar mais de uma máquina ao mesmo tempo. • Adaptadores de rede Existe, porém, um ponto muito importante a ser discutido: Adaptadores de rede. Ao criar uma máquina virtual, três opções básicas surgem ao usuário: Modo Bridge, modo NAT e modo Host- Only. 1 Bridge (túnel) A máquina virtual se torna parte da mesma rede que a máquina física, recebendo um IP na mesma faixa. De semelhante forma, é enxergada pelo roteador de sua casa como mais um dispositivo físico. 2 NAT A máquina física mascara todas as atividades da máquina virtual e funciona como um roteador, retransmitindo todas as requisições. Se a máquina físicapossuir internet, a máquina virtual também terá. 3 Host-Only Permite conexão apenas entre a máquina virtual e a máquina física. É possível configurar outras máquinas virtuais do mesmo modo e permitir comunicações entre elas e a máquina física, sem qualquer acesso à internet. javascript:void(0); javascript:void(0); Atenção A máquina de análise de artefatos sempre deve ser configurada em modo Host-Only. Análise dinâmica básica Como já sabemos, a análise dinâmica é a investigação realizada após a execução do artefato a fim de verificar seu comportamento. É considerada a segunda etapa do processo de análise, pois é realizada após a completude das técnicas de análise estáticas disponíveis. Podemos monitorar o comportamento do malware enquanto ele é executado ou pode ser feito um exame do sistema após a sua execução, verificando as mudanças executadas e como o sistema foi afetado. Nessa fase, as hipóteses levantadas durante a análise estática são confirmadas ou refutadas, pois a simples existência de uma função em um binário não significa que ela será executada. A análise dinâmica é a maneira mais eficiente de identificar a funcionalidade e os propósitos do artefato. Exemplo Por exemplo, se o malware for um keylogger, a análise dinâmica pode permitir que você localize o arquivo usado para guardar as informações digitadas em algum local no sistema. É possível verificar os tipos de registros que ele mantém e, ainda, descobrir para onde suas informações são enviadas. Esse tipo de percepção seria mais difícil de obter usando apenas técnicas estáticas básicas. SandBox Definições Vejamos as definições de uma sandbox: • É um mecanismo de segurança para executar programas não confiáveis em um ambiente seguro, sem necessidade de grandes precauções para não prejudicar sistemas “reais”. • É um ambiente virtualizado que muitas vezes simula serviços de rede de alguma forma para garantir que o artefato testado funcione normalmente e realize todas as suas operações, gerando um relatório com todas as atividades realizadas. Saiba mais Existem diversas opções disponíveis no mercado, inclusive de forma gratuita. Uma sandbox disponível e bastante utilizada pela comunidade é a HybridAnalysis. Existe um plano pago com mais opções e um maior acesso, mas por ora o plano grátis nos atenderá. Ao acessar o site, podemos enviar nossa amostra e escolher o sistema operacional a ser testado: Windows, Linux e Android. Depois, preenchemos os dados para recebimento do relatório e seu arquivo vai para uma fila para ser analisado. Caso ele já tenha sido enviado, você já terá acesso ao relatório com os indicadores analisados. Nunca submeta a ferramentas gratuitas arquivos com informações sensíveis. Desvantagens Os sandboxes possuem algumas desvantagens importantes: 01 Não há possibilidade de executar o arquivo suspeito por meio da linha de comando, passando qualquer tipo de argumento, por exemplo. Isso limita as possibilidades pois, nos casos em que o artefato é acionado por linha de comando, não funcionará em uma sandbox padrão. 02 Além disso, nos casos em que a parte maliciosa apenas se manifesta após algum tempo, as sandboxes podem deixar de analisar essa parte. javascript:void(0); Execução do malware Após tomadas todas as precauções já citadas, é hora de executar o artefato. Embora possa parecer simples executar um binário clicando duas vezes ou executando-o via linha de comando, pode ser complicado iniciar DLLs maliciosas, pois o Windows não possui uma forma direta para executá-las. Abordaremos uma maneira de iniciar DLLs para poder realizar a análise dinâmica. O programa rundll32.exe está incluído em todas as versões modernas do Windows e fornece um contêiner para executar uma DLL usando a seguinte sintaxe: rundll32.exe DLLname, Export argumentos Toda DLL exporta uma função e podemos verificar seu nome por meio da ferramenta PEview na tabela de exportação. Vejamos o exemplo a seguir. Exemplo João Wannacry verificou que havia uma dll estranha chamada resgate.dll e, ao analisá-la via PEview, percebeu que existiam duas funções de exportação: Criptografar e descriptografar. Curioso, João procurou na internet como executar a função de uma DLL, executando o seguinte comando: c:\>rundll32.exe resgate.dll, descriptografar. Nada aconteceu, então ele executou c:\>rundll32.exe resgate.dll, criptografar. Imediatamente, todos os arquivos de sua máquina começaram a ser criptografados e, após um tempo, surgiu uma mensagem na tela cobrando um resgate para recuperação dos mesmos. Isso aconteceu porque João realizou a execução em um ambiente que não era seguro. Monitoramento Process Monitor O Process Monitor, ou procmon, é uma ferramenta de monitoramento avançada para Windows que fornece uma maneira de monitorar certos registros, sistemas de arquivos, redes, processos e afins. javascript:void(0); Embora o procmon capture muitos dados, ele não captura tudo. Ele pode perder algumas atividades maliciosas ocultadas por rootkits e chamadas de gráficas. Mesmo sendo uma ferramenta útil, geralmente não é utilizado para registrar a atividade da rede, pois não funciona de forma consistente no Windows. O Procmon monitora todas as chamadas de sistema durante o seu funcionamento. Como existem muitas chamadas de sistema em uma máquina Windows, às vezes mais de 50.000 eventos por minuto, geralmente é impossível examinar todas elas. Para isso, utilizamos o filtro disponível para mostrar apenas determinadas operações que nos interessam. Ele fornece as seguintes informações por padrão: 1 Registro Ao examinar as operações de registro, você pode saber como um malware se instala no mesmo. 2 Sistema de arquivos Explorar a interação do malware com o sistema de arquivos pode revelar todos os arquivos criados, acessados e/ou modificados. 3 Atividade do processo A investigação da atividade do processo pode dizer se o malware gerou processos adicionais. 4 Rede A identificação de conexões de rede pode mostrar a porta e o host que o malware está usando para se comunicar. Process Explorer O Process Explorer é outra ferramenta útil para analisar os processos que estão em execução na memória, organizando-os em forma de árvore e mostrando a hierarquia entre eles. Além disso, pode mostrar todas as DLL que foram carregadas na memória ao clicar na propriedade do processo. Outra informação útil é a possibilidade de comparação de cadeia de caracteres da imagem estática do binário com as informações carregadas em memória. Essa opção mostra a diferença criada por um empacotador; em memória, todos os caracteres são revelados. Regshot Regshot é uma ferramenta de comparação de registro que permite tirar e comparar duas fotografias do registro. Seu uso é simples: Fonte: O autor. Wireshark Uma aplicação capaz de interceptar e analisar pacotes de rede é essencial ao analista. Usaremos o Wiresharkpara esse fim, uma plataforma de código aberto que recebe diversas atualizações e plugins da comunidade, fornecendo visualização, análise de fluxo de pacotes e análise aprofundada de pacotes individuais. O Wireshark pode ser usado tanto para o bem quanto para o mal: Depurar problemas javascript:void(0); javascript:void(0); javascript:void(0); Pode ser usado para analisar o tráfego de redes internas, a fim de depurar problemas de aplicativos e estudar protocolos em execução. compare_ arrows Detectar senhas Também pode ser usado para detectar senhas, fazer engenharia reversa de protocolos de rede, roubar informações confidenciais e capturar conversas trafegando nas redes vizinhas. Comentário O Wireshark irá nos ajudar a entender como o artefato malicioso realiza a comunicação de rede, interceptando os pacotes enquanto se comunica (ou enquanto tenta se comunicar). Para isso, basta conectar- se à Internet ou simular uma conexão, iniciar a captura de pacotescom o Wireshark e, por fim, executar o malware. ondemand_videoVídeo Falsificação de rede O artefato geralmente tenta se comunicar com um servidor de comando e controle, ou tenta fazer download de outro arquivo malicioso. Para isso, podemos criar uma rede falsa e obter rapidamente indicadores de rede, sem realmente se conectar à Internet. Esses indicadores podem incluir nomes DNS, endereços IP e assinaturas de pacote. Para falsificar uma rede com sucesso, devemos evitar que o malware perceba que está sendo executado em um ambiente virtualizado. Ao combinar as ferramentas discutidas aqui com uma configuração de rede de máquina virtual sólida, você aumentará muito suas chances de sucesso. Como isso deve ser feito? REMnux O REMnux é um sistema operacional personalizado criado para auxiliar a análise de malware e engenharia reversa e nós utilizaremos essa distribuição. Por que utilizar um sistema operacional? INetSim ondemand_videoVídeo Existe uma ferramenta fantástica criada para simular serviços comuns de Internet: INetSim, um pacote de software gratuito baseado em Linux. 01 O INetSim é a ferramenta gratuita mais fácil e ágil para fornecer serviços falsos, permitindo que você analise o comportamento de rede dos artefatos emulando serviços como HTTP, HTTPS, FTP, IRC, DNS, SMTP e outros. Por meio de um comando simples, as portas são definidas por padrão mas podem ser modificadas facilmente. 02 Alguns dos melhores recursos do INetSim são integrados à simulação de servidor HTTP e HTTPS. Por exemplo, o INetSim pode fornecer qualquer arquivo solicitado. No caso de um malware solicitar um JPEG de um site para continuar sua operação, o INetSim responderá com um JPEG formatado corretamente, de forma automática. javascript:void(0); javascript:void(0); 03 Embora essa imagem possa não ser o arquivo que o artefato esteja procurando, o servidor não retorna um erro 404, ou outro erro, e sua resposta, mesmo que incorreta, pode manter o artefato em execução. 04 O INetSim também pode registrar todas as solicitações e conexões de entrada, algo bastante útil para determinar se a atividade é legítima,se está se conectando a um serviço padrão ou para registrar as solicitações ilegítimas para futura análise. Por ser extremamente configurável, é possível definir a página ou o item retornado após uma solicitação. Exemplo Por exemplo, ao verificar que o malware está procurando uma página da web específica antes de continuar a execução, o INetSim fornece a página. Aula 3: Análise Estática Avançada e Codificação – Parte I Apresentação Nesta terceira aula, após aprendermos a realizar uma análise básica no artefato, tanto estática quanto dinamicamente, abordaremos a tão temida linguagem de máquina – Assembly. Para isso, revisaremos alguns tópicos necessários para o entendimento da arquitetura Intel x86 e o funcionamento padrão de um programa. Objetivo • Identificar características da arquitetura Intel x86; • Examinar as diferenças entre as bases numéricas; • Identificar comandos na linguagem Assembly. Arquitetura de computadores Para começar, é importante sabermos que: Os métodos básicos de análise estática e dinâmica de artefatos são satisfatórios para a triagem inicial, mas não fornecem informações suficientes para uma análise completa. Porém, estaremos apenas arranhando a superfície se quisermos entender toda a dinâmica e extensão dos danos. Análise básica Por meio de uma análise estática básica é possível identificar as funções que são importadas, mas ainda não é possível determinar como elas serão usadas ou se serão usadas em algum momento. compare_ arrows Análise dinâmica As técnicas dinâmicas básicas também apresentam algumas deficiências. Por meiodelas é possível entender o que um artefato precisa e como age ou responde ao receber um determinado pacote ou arquivo ao requisitá-lo de um determinado domínio. Entretanto, só será possível entender o formato e como toda a engrenagem funciona com aprofundamento no fluxo da aplicação. É nesse ponto que entraremos nas ferramentas de desmontagem (disassembly). Comentário Num primeiro momento, a desmontagem pode parecer algo sem sentido até mesmo para programadores experientes. Mas não desanime, nesta aula cobriremos algumas bases necessárias ao entendimento dos artefatos, dos comuns aos mais complexos. Como esse curso não é de engenharia reversa, não conseguiremos exaurir por completo este campo de estudo, mas daremos os primeiros passos. Níveis de abstração Dentro da arquitetura de computadores tradicionais há vários níveis de abstrações, que existem para facilitar os detalhes de implementação dos programas e sistemas. O que isso significa? Para entender mais facilmente basta imaginarmos que um sistema operacional como o Windows, por exemplo, pode ser executado em diversos tipos de hardware sem que haja qualquer tipo de ajuste. Isso só é possível porque os componentes físicos não são levados em consideração, ou abstraídos, pelo sistema operacional. A Figura 1 mostra três níveis de codificação que serão abarcados em uma análise de um binário. Fonte: Sikorski (2012). Figura 1 - Exemplo de níveis de código Então: • O malware será criado em uma linguagem de alto nível, como a linguagem C, por exemplo. • Depois, utiliza-se um compilador que irá gerar o código de máquina correspondente às instruções criadas pelo autor e que será executado pela CPU. Partiremos desse ponto em nossos exemplos e, é desse ponto também que os analistas de malware trabalham e analisam os binários. A ferramenta de desmontagem (disassembly) transforma o código de máquina em uma linguagem de baixo nível, também conhecida como Assembly. Nesse sentido, o gerenciamento de vulnerabilidde envolve: Hardware Nível físico, consiste em circuitos elétricos que implementam combinações complexas de operações lógicas e não são facilmente manipulados pelo Software. https://stecine.azureedge.net/webaula/estacio/go0682/aula3.html#collapse01-01 Micro-código Também conhecido como firmware, opera apenas no circuito exato para o qual foi projetado. Contém microinstruções que fornecem uma interface de tradução do código de máquina para o hardware. Não será nosso foco, pois é geralmente específico para cada hardware. Código de máquina Consiste basicamente em opcodes (muito importante), que são dígitos hexadecimais que dizem ao processador qual instrução deveser executada. Normalmente implementado com várias instruções de microcódigo para que o hardware subjacente possa executar o código, sendo criado quando uma linguagem de alto nível é compilada. Linguagens de Baixo Nível Versão legível por humanos do conjunto de instruções de uma arquitetura de computador. Sua versão mais comum é a linguagem Assembly. Operaremos nesse nível porque o código de máquina é muito difícil para um ser humano compreender. Linguagens de Alto Nível A maioria dos programas é criada em linguagens de alto nível, pois elas fornecem grande abstração no nível da máquina e facilitam o uso de lógica de programação e dos mecanismos de controle de fluxo. Possuem como exemplos as linguagem C, C++, dentre outras. Essas linguagens são normalmente transformadas em código de máquina por um compilador por meio de um processo conhecido como compilação. Linguagens Interpretadas Essas linguagens não são compiladas em código de máquina; em vez disso, são traduzidas em bytecode — uma representação intermediária específica da linguagem de programação. O bytecode é executado dentro de um interpretador, que é um programa que traduz o bytecode em código de máquina executável durante a execução. São exemplos de linguagens interpretadas: C#, Perl, .NET e Java. Arquitetura Intel x86 Os componentes internos da maioria das arquiteturas de computador modernas (incluindo x86) seguem a arquitetura de Von Neumann, conforme a Figura 2, e possuem trêscomponentes de hardware: Unidade de processamento central (CPU) que executa o código. https://stecine.azureedge.net/webaula/estacio/go0682/aula3.html#collapse01-02 https://stecine.azureedge.net/webaula/estacio/go0682/aula3.html#collapse01-03 https://stecine.azureedge.net/webaula/estacio/go0682/aula3.html#collapse01-04 https://stecine.azureedge.net/webaula/estacio/go0682/aula3.html#collapse01-05 https://stecine.azureedge.net/webaula/estacio/go0682/aula3.html#collapse01-06 Memória principal do sistema (RAM) que armazena todos os dados e códigos. Sistema de entrada/saída que faz interface com dispositivos como discos rígidos, teclados e monitores. Fonte: TANENBAUM (2010). Figura 2 - Arquitetura Von Neumann Conforme a Figura 2, é possível verificar que a CPU contém vários componentes que serão muito importantes para nosso entendimento: Fonte: Adaptado de Freepik. Unidade de controle Obtém instruções a serem executadas da memória RAM usando um registrador (chamado de ponteiro de instrução – EIP), que armazena o endereço da instrução a ser executada. Registradores Unidades básicas de armazenamento de dados da CPU e que são usados para economizar tempo, pois a CPU não precisará acessar a RAM. Unidade Lógica Aritmética (ULA) Responsável por executar a instrução obtida da RAM; armazena os resultados em registradores ou na memória. A memória principal (RAM) para um único programa pode ser dividida em quatro seções principais: 1. Dados 2. Código 3. Heap 4. Pilha Fonte: SIKORSKI (2012). Dados Área da memória reservada para receber variáveis com valores estáticos que serão usados no decorrer do programa ou com valores globais que estarão disponíveis para qualquer parte do programa. Código Área reservada para as instruções buscadas pela CPU para executar as tarefas do programa. Essa área possui as rotinas que definem o que o programa faz e como as tarefas do programa serão orquestradas. Heap Porção da memória utilizada para alocações dinâmicas durante a execução do programa para criar (alocar) novos valores e eliminar (liberar) outros de que o programa não precisa mais. O heap é conhecido como memória dinâmica porque seu conteúdo pode ser alterado com frequência durante a execução do programa. Pilha Área utilizada para variáveis locais e parâmetros para funções, além de auxiliar no controle do fluxo do programa. Linguagem de baixo nível – Assembly Agora que revisamos a arquitetura e a forma como funciona um computador, passaremos a abordar a linguagem de baixo nível assembly. Como em qualquer linguagem, o assembly possui diversas instruções, cada uma com seu propósito;cada instrução possui um mnemônico e zero ou mais operandos. Vejamos como isso funciona: Fonte: O autor. O mnemônico é uma palavra que identifica a instrução a ser executada e o operando identifica as informações usadas pela instrução, seja um registrador ou um dado. Parece confuso, mas vamos explicar melhor. No exemplo a seguir, movemos o valor de 42 em hexadecimal para o registrador ecx, ou seja, o valor de eax passará a ser 0x42 (em hexadecimal): movecx, 0x42 Cada instrução corresponde a opcodes (códigos de operação) que informam à CPU qual operação o programa deseja executar. Uma ferramenta de disassemble traduz opcodes em instruções legíveis para humanos. No exemplo anterior, a instrução movecx, 0x42 possui os seguintes opcodes: B9 42 00 00 00. • O valor B9 corresponde a movecx; e • 0x42000000 corresponde ao valor 0x42. Isso acontece porque a arquitetura x86 usa o formato little-endian na ordem dos bytes. O endianness dos dados descreve se o byte mais significativo (big-endian) ou menos significativo (little-endian) é ordenado primeiro (no menor endereço) dentro de um item de dados maior. Comentário Vamos simplificar. Se estivermos em um ambiente little-endian e quisermos mover 0x12345678 para o eax, os opcodes deverão ser: B9 78 56 34 12; se estivermos em um ambiente big-endian: B9 12 34 56 78. Mudar entre ordem de bytes é algo que o malware deve fazer durante a comunicação de rede, pois os dados de rede usam big-endian e um programa x86 usa little-endian. Portanto, o endereço IP 127.0.0.1, em hexadecimal 127 – 0x7f; 0 – 0x00; 0 – 0x00; e 1 – 0x01, será representado como 0x7F000001 no formato bigendian (pela rede) e 0x0100007F no formato little-endian (localmente na memória). Atenção Como analista de malware, você deve estar ciente da ordem de bytes para garantir que não inverta acidentalmente a ordem de importantes indicadores, como um endereço IP. Os operandos são usados para identificar os dados usados por uma instrução. Existem três tipos de dados que podem ser usados: 1 Imediatos operandos de valor fixo, como no exemplo (0x42); 2 Registradore operandos são registradores, como no exemplo (ecx). 3 Endereço de memória operandos apontam para uma área da memória que contenha algum valor de interesse. Pode ser um valor ou registrador entre colchetes ([ecx] ou [0x11223344]). ondemand_videoVídeo Bases numéricas É importante lembrarmos: Um bit possui dois valores: 0 ou 1, ligado ou desligado. Os computadores trabalham em modo binário, pois são circuitos eletrônicos (complexos). Nossa matemática é baseada em números decimais: 0, 1, 2, 3, 4, 5, 6, 7, 8 e 9. Ao chegar ao limite, adiciona-se uma unidade na frente do número e reinicia a contagem. Fonte: Adi Goldstein / Unsplash. Não entendeu? Quanto é 9 + 1? Não existe uma resposta com o uso de apenas um dígito, então reiniciamos a contagem e adicionamos uma unidade na frente: 10. Isso é simples. Não é à toa que estudamos esse princípio desde a educação básica. No entanto, vamos quebrar alguns paradigmas. Em um sistema binário existem apenas 0 e 1. Quanto é 1 + 1? Para responder precisamos nos lembrar de que a resposta não pode ser representada por um único dígito (no sistema binário só existe 0 e 1). Então, como no decimal, vamos reiniciar a contagem e adicionar uma unidade na frente: 10. Estranho, não? Em binário: 1+1=10; em decimal: 1+1=2. Agora vamos expandir esse conceito para um outro sistema, o hexadecimal. Como você pode imaginar, para representar um valor de 32 bits, na arquitetura x86, são necessários 32 dígitos (0s e1s); para facilitar a sua representação, o hexadecimal é utilizado. Comentário A diferença é que existem algumas opções a mais de dígitos: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E e F. Tabela 1: Correlações entre bases Binário Decimal Hexadecimal 0 0 0 1 1 1 10 2 2 11 3 3 100 4 4 101 5 5 110 6 6 111 7 7 1000 8 8 1001 9 9 1010 10 A 1011 11 B 1100 12 C 1101 13 D 1110 14 E 1111 15 F Fonte: Autor. Como pode ser visto na Tabela 1, o uso de números em hexadecimais economiza na razão 4:1 da quantidade de números binários. Ou seja, para cada 4 binários é necessário apenas 1 hexadecimal para representar seu valor. É importante lembrarmos que um byte são oito bits, portanto, são necessários 2 hexadecimais para representar o mesmo byte. Registradores O que é um registrador? Um registrador nada mais é do que uma pequena quantidade de armazenamento de dados disponíveis para a CPU, cujo conteúdo pode ser acessado mais rapidamente do que em outro lugar. Os processadores x86 têm uma coleção de registros disponíveis para uso como armazenamento temporário, e os mais comuns se enquadram em quatro categorias (SIKORSKI,2012): 1 Registradores gerais Usados pela CPU durante a execução. 2 Registradores Usados para rastrear seções de memória. 3 Flags de status Usados para armazenar dados para tomada de decisões. 4 Ponteiros de instrução Usados para rastrear a próxima instrução a ser executada. A tabela a seguir demonstra os registradores separados por categoria: Tabela 2: Relação de registradores Gerais Segmento Status Ponteiros EAX (AX, AH, AL) CS EFLAGSEIP EBX (BX, BH, BL) SS ECX (CX, CH, CL) DS EDX (DX, DH, DL) ES EBP (BP) FS ESP (SP) GS ESI(SI) Fonte: Autor. Numa arquitetura de x86, os registradores gerais possuem 32 bits, mas podem ser referenciados em 32 ou 16 bits. Para acessar sua parte de 16 bits, basta retirar a letra “E” de seu mnemônico. Existem ainda quatro registradores (EAX, EBX, ECX e EDX), com os quais é possível acessar 8 bits da parte superior e inferior de seu registrador de 16 bits. Portanto, para estes registradores é possível acessar os 32 bits, 16 bits, 8 bits superiores e inferiores da porção de 16 bits, conforme figura a seguir: Tabela 3: Porções do Registrador EAX EAX – 32 BITS AX – 16 BITS AH – 8 BITS AL – 8 BITS Fonte: Autor. Registradores de uso geral Os registradores gerais normalmente armazenam dados ou endereços de memória e costumam ser usados de forma dinâmica para realizar as tarefas no programa. Apesar de o nome sugerir o uso geral, por definição, algumas instruções utilizam registros específicos. As instruções de multiplicação e divisão, por exemplo, sempre usarão os registradores EAX e EDX, mas isso não afetará o uso, nem o entendimento. Comentário Existem algumas convenções usadas pelos compiladores que devem ser de conhecimento de um analista de malware, pois isso permitirá que examine o código mais rapidamente. Um exemplo dessa convenção é que o EAX geralmente é usado para armazenar o valor de retorno nas chamadas de função. Portanto, ao verificar o uso do registrador EAX imediatamente após uma chamada de função, provavelmente verá a manipulação do valor de retorno da função utilizada. Flags (EFLAGS) O registrador EFLAGS é um registrador que armazena os status das operações realizadas durante a execução do programa. Na arquitetura x86, o tamanho do registrador é de 32 bits e cada bit é uma flag. Durante a execução, cada flag possui o valor (1) ou (0) para controlar as operações da CPU ou indicar os resultados de alguma operação realizada pela CPU. Para nossa análise, vamos focar nas seguintes flags: Clique nos botões para ver as informações. Flag zero (zero flag – ZF) A flag zero recebe o valor de 1 quando o resultado de uma operação é igual a 0. Não confunda: Se o resultado de uma operação for zero, a flag zero terá o valor 1. Para os outros casos, ela será zero. Flag de carregamento (Carryflag – CF) A flag de carregamento recebe o valor de 1 quando o resultado de uma operação é muito grande ou muito pequeno para o operando de destino. Por exemplo, um registrador possui o valor de 0xffffffff, ou https://stecine.azureedge.net/webaula/estacio/go0682/aula3.html#collapse01-01 https://stecine.azureedge.net/webaula/estacio/go0682/aula3.html#collapse01-02 seja, o valor máximo paraum registrador de 32 bits. Érealizada uma operação de soma um nesse registrador, o valor do registrador passará a ser 0x00000000 e a flag será ativada. Nos outros casos, ela será zero. Flag de sinal (signflag – SF) A flag de sinal recebe o valor de 1 quando o resultado de uma operação é negativo, e o valor de 0 quando o resultado é positivo. Esse sinalizador também é definido quando o bit mais significativo é definido após uma operação aritmética. Flag de trap – TF A flag de trap é usada para depuração. O processador x86 executará apenas uma instrução por vez se esse sinalizador for definido. ondemand_videoVídeo Registrador de instrução Na arquitetura x86: 01 O EIP, também conhecido como ponteiro de instrução ou, ainda, contador de programa é um registrador que contém o endereço de memória da próxima instrução a ser executada por um programa. O único propósito do EIP é dizer ao processador o local da próxima instrução a ser executada. 02 Apesar de parecer um registrador simples, o EIP é fundamental para uma aplicação pois, quando corrompido, ou seja, se ele apontar para um endereço de memória que não contém código de programa legítimo, a CPU não será capaz de buscar código legítimo para executar, causando um erro e o fechamento do programa em questão. 03 https://stecine.azureedge.net/webaula/estacio/go0682/aula3.html#collapse01-03 https://stecine.azureedge.net/webaula/estacio/go0682/aula3.html#collapse01-04 Além disso, o controle do EIP significa um controle por parte do fluxo do programa. Por isso, os invasores tentam obter o seu controle por meio de exploração de falhas da aplicação. Instruções em Assembly Instrução mov Anteriormente apresentamos um exemplo simples utilizando mov, o comando mais comum que serve para copiar dados de um lugar para outro. Atenção Apesar de o nome do comando ser mov, de “mover”, o comando não move o valor de um local para outro. E qual é a diferença? O ato de mover é retirar algo de um lugar e colocar em outro, ou seja, você limpa a origem e move-a para o destino. Você verá que um programa ou o sistema operacional não tem o costume de limpar áreas da memória após sua utilização;basta torná-la um local usável e ignorar o seu conteúdo. Vamos utilizar a sintaxe Intel de comandos assembly (a mais utilizada no mundo, a outra sintaxe é da AT&T). Portanto, o formato do comando será mov destino, origem. Ou seja, “movemos” o valor do operando da direita para o operando da esquerda. Vejamos a seguir alguns exemplos para entender e fixar o conhecimento. Vale lembrarmos que, ao colocar qualquer operando entre colchetes, acessaremos o valor da memória apontada por ele. movecx, eax movebx, [0x45678] moveax,[ebx+eax] Copia o conteúdo de EAX para o registrador ECX (sem modificar EAX). Copia os 4 bytes que estão na memória em 0x45678 para ebx. Copia os 4 bytes que estão localizados na memória na posição especificada pela equação ebx+eax para o registrador eax. Comentário Este último exemplo só pode ser usado para calcular posições de memória, ou seja, se o colchete não fosse utilizado receberíamos um erro por ser uma instrução inválida. Uma instrução semelhante ao mov é o lea, que significa carregar endereço efetivo (loadeffectiveaddress). Seu formato de instrução é o mesmo do mov: lea destino, origem. Instrução lea A instrução lea é usada para escrever um endereço de memória no destino. Não confunda a instrução mov com a instrução lea. Vejamos a diferença entre elas: leaeax, [ebx + 8] Armazenará em EAX o valor de EBX + 8 em EAX. compare_ arrows moveax, [ebx + 8] Carregará os dados do endereço de memória especificado por EBX + 8 em EAX. Ou seja, leaeax, [ebx + 8] equivale a moveax, ebx + 8 (se essa instrução fosse válida). Instruções aritméticas Num programa, várias instruções aritméticas são usadas, como soma, subtração e operações lógicas. Adição e subtração O formato da adição e da subtração é o mesmo das instruções anteriores: add destino, origem e sub destino, origem. Com um detalhe: O resultado da soma ou da subtração é armazenada no destino. Atenção Devemos lembrar que essas operações podem modificar as flags de zero ou de carregamento, se uma operação tiver como resultado zero ou se ultrapassar o valor máximo de um registrador, respectivamente. Outras instruções importantes são o inc e dec, que incrementam ou decrementam um registrador pelo valor de um. Multiplicação e divisão A multiplicação e a divisão atuam em um registrador predefinido, de modo que o comando é simplificado a uma instrução mais o valor pelo qual o registrador será multiplicado ou dividido. Seu formato de instrução é: mulvalor e divvalor. A atribuição do registrador no qual será armazenado o valor da multiplicação ou da divisão pode ocorrer muitas instruções antes; portanto, pode ser necessário pesquisar em um programa para encontrá-la. A instrução de multiplicação sempre utiliza o registrador EAX pelo valor passado como operando. O resultado é armazenado como um valor de 64 bits em dois registradores: EDX e EAX. O EDX armazena os 32 bits mais significativos e o EAX armazenaos 32 bits menos significativos. Exemplo Vamos supor que o resultado de uma multiplicação seja 800.000.000.000 ou 0xBA43B74000. Como o valor é muito grande para apenas um registrador, edx receberá o valor de 0xBA e eax receberá o valor de 0x43B74000. Já a divisão divide o valor armazenado em edx e eax pelo operando valor, o resultado é armazenado em eax e o resto armazenado em edx. Operadores lógicos Outra operação muito utilizada são os operadores lógicos, como OR, AND e XOR. Sua forma de operação é semelhante à soma e à subtração. Eles executam a operação especificada entre os operandos de origem e destino e armazenam o resultado no destino. Destacamos que as operações lógicas são realizadas na forma bit a bit. Instruções shre e shl As instruções shre shl, usadas para deslocar registradores, também são muito utilizadas. O formato da instrução, tanto do shl quanto do shr, é shl destino, valor. Basicamente, as instruções shr e shl deslocam os bits no destino para a direita ou para a esquerda, respectivamente, pelo número de bits especificado no segundo operando. Preenche-se com bits 0 os valores deslocados durante a mudança. Parece confuso mas é bem simples. Vejamos um exemplo: Exemplo Se tivermos o valor binário 1000 e deslocá-lo para a direita em 1, o resultado será 0100. Se tivermos o valor binário 1000 e deslocá-lo para a esquerda em 1, o resultado será 10000. ondemand_videoVídeo Aula 4: Análise Estática Avançada e Codificação – Parte II Apresentação Nesta quarta aula aprofundaremos a linguagem de máquina – Assembly, com exemplos mais elaborados e sua correlação com estruturas comuns na linguagem em C. Veremos a utilização de uma ferramenta poderosa na análise de malware, finalizando o básico da linguagem para prosseguimento da disciplina. Objetivo • Identificar chamadas de funções e passagem de parâmetros em assembly; • Identificar as funções básicas da ferramenta IDA Pro; • Distinguir Linguagem de alto e baixo nível. Assembly Na última aula introduzimos o básico da linguagem assembly, bem como realizamos alguns exercícios para fixar os conhecimentos. É difícil fazer generalizações, pois toda regra possui uma exceção, mas todos os códigos complexos e bem escritos possuem funções. O que são funções? As funções são partes do código dentro de um programa que executam uma tarefa específica, uma rotina, e que são relativamente independentes do código restante. O código principal chama e transfere temporariamente a execução para funções antes de retornar ao código principal. Ressaltamos que a função pode ser implementada pelo autor do código ou pode ser empregada para abrir uma conexão, um arquivo ou escrever algo na tela. Já mencionamos que todas as operações de um programa são realizadas na memória, e a pilha é o espaço reservado para que isso aconteça. Todas as operações que precisam ser armazenadas temporariamente são armazenadas na pilha. Na arquitetura x86, os parâmetros passados para uma função são passados para a pilha (Stack) para serem manipulados. A instrução utilizada para armazenar dados na pilha é o push, lembrando que os dados são armazenados no tipo FIFO – primeiro a entrar, último a sair –; pense numa pilha de pratos, o primeiro a ser colocado é o último a ser tirado. Saiba mais Existem outros pontos que podem ser necessários, mas que não teremos condições de abordar por falta de tempo. Alguns pontos serão verificados nas próximas sessões, os demais podem ser pesquisados e aprofundados no manual disponível pela própria Intel em: https://software.intel.com/content/www/us/en/develop/articles/int el-sdm.html IDA Pro O Interactive Disassembler Professional (IDA Pro) é um desmontador extremamente poderoso lançado pela empresa Hex-Rays. Embora o IDA Pro não seja o único, é o desmontador mais utilizado na atualidade. Recentemente, a NSA – Agência de Segurança Nacional dos EUA lançou uma ferramenta com os mesmos propósitos chamada Ghidra, que está fazendo muito sucesso. O IDA Pro é uma solução paga; existem duas versões comerciais e a diferença entre elas são os suportes aos processadores. A versão avançada oferece suporte a muitos processadores, e suporta diversos formatos de arquivos, como o Portable Executable (PE) para a plataforma Windows e o Executable and Linking Format (ELF) para a plataforma Linux. Comentário Concentraremos nossa discussão nas arquiteturas x86 e x64 e no formato de arquivo PE para Windows. Utilizaremos uma versão gratuita do IDA Pro, o IDA Pro Free, disponível em http://www.hex- rays.com/idapro/idadownfreeware.htm. Saiba, porém, que esta versão tem funcionalidades limitadas. Ela não é indicada para uso profissional, mas será mais do que suficiente para javascript:void(0); javascript:void(0); javascript:void(0); javascript:void(0); nós. Não se limite ao que for ensinado aqui e procure explorar ainda mais; lembre-se de que a experiência vem com a prática. Basicamente, o IDA Pro processará o programa e realizará tarefas como, mas não limitadas a: Fonte: O autor. Veremos, nessa aula, as técnicas básicas de como traçar um paralelo entre a análise feita pela ferramenta e o código-fonte da aplicação. O IDA Pro possui uma base de dados de assinaturas de código que permitem reconhecer e rotular as funções desmontadas. A ferramenta foi criada para ser interativa; todo o processo de desmontagem pode ser modificado, manipulado, reorganizado ou redefinido. 01 Um dos melhores aspectos do IDA Pro é a sua capacidade de salvar e documentar todo o progresso da análise, sendo possível adicionar comentários, rótulos e nome de funções e, em seguida, salvar seu trabalho em um banco de dados IDA Pro (conhecido como idb) para retorno posterior. O IDA Pro também oferece suporte para adição de extensões próprias ou de terceiros para auxiliar na análise. 02 Ao carregar um executável no IDA Pro, ele tenta reconhecer o formato do arquivo e a arquitetura do processador. No exemplo da figura a seguir (Figura 1), o arquivo é automaticamente reconhecido como formato PE e com a arquitetura Intel x86. Outra característica da ferramenta é o mapeamento do arquivo em memória como se tivesse sido carregado pelo sistema operacional. 03 Uma opção útil é carregar o arquivo como um binário bruto, pois o mesmo pode possuir mecanismos de proteção e não carregar dados adicionais, parâmetros de criptografia e até mesmos outros executáveis na memória quando o malware for executado pelo Windows ou carregado no IDA Pro. Fonte: O autor. Figura 1: Carregamento de arquivo no IDA Pro Por padrão, o IDA Pro não inclui o cabeçalho PE ou as seções de recursos em sua desmontagem; esses locais podem ser utilizados para esconder códigos maliciosos pelo artefato. Basta selecionar a opção de carregamento manual (Manual Load) que a ferramenta perguntará se você deseja carregar cada seção, uma por uma, incluindo o cabeçalho do arquivo PE. Isso será importante para que essas seções não escapem da análise. É possível analisar o código em modo gráfico e em modo de texto. No modo gráfico, a cor e a direção das setas ajudam a mostrar o fluxo do programa durante a análise. A cor da seta informa se o caminho é baseado em uma decisão específica que foi tomada: Vermelho, se determinada condição não for atendida. Verde se for atendida. Azul para um salto incondicional. Exemplo Por exemplo, digamos que determinado trecho de código verifica se existe conexão com a internet; caso haja, o programa executará determinada ação – seta verde;em caso contrário, executará outras ações – seta vermelha. A direção da seta mostra o fluxo do programa; setas para cima normalmente denotam uma situação de loop. É possível também destacar um texto; assim, todas as instâncias do mesmo texto são destacadas, auxiliando a encontrar padrões e repetições. Fonte: O autor. Figura 2: Modo gráfico do IDA Pro Já o modo de texto é uma visãomais tradicional da análise do binário e pode ser usado para análises mais profundas, verificando, por exemplo, outras seções do mesmo. A Figura a seguir exibe a visualização do modo de texto de um binário; o endereço de memória (0040105B) em vermelho, o nome da seção (seg002) e os opcodes em verde, e a instrução correspondente, ao lado direito, em amarelo. Fonte: O autor. Figura 3: Modo texto do IDA Pro Várias outras janelas do IDA Pro destacam itens específicos em um executável. Os itens a seguir são os mais significativos para nossos propósitos: • Janela de funções Lista todas as funções no executável e mostra o tamanho de cada uma. Você pode classificar por comprimento de função e filtrar por funções grandes e complicadas que provavelmente sejam interessante. • Janela de nomes Lista todos os endereços com um nome, incluindo funções, código, dados e strings. • Janela Strings Mostra todas as strings. Por padrão, essa lista mostra apenas strings ASCII com mais de cinco caracteres. Você pode alterar isso clicando com o botão direito na janela e selecionando Setup. • Janela de importações Lista todas as importações de um arquivo. • Janela de exportação Lista todas as funções exportadas para um arquivo. Esta janela é bastante útil quando analisamos DLLs. • Janela de estruturas Lista o layout de todas as estruturas de dados ativas. Essas janelas também oferecem um recurso de referência cruzada que é particularmente útil para localizar códigos interessantes. Exemplo Por exemplo, para encontrar todos os locais de código que chamam uma determinada função, você pode usar a janela de importação, clicar duas vezes na função importada de interesse e usar o recurso de referência cruzada para localizar a chamada de importação na listagem de código. É possível realizar buscas por determinados textos dentro da janela atual no IDA Pro; basta selecionar o menu Search e a opção texto (Text). Outra busca bastante útil é a busca por sequências de bytes, caso seja necessário fazer uma busca binária dentro do contexto. Pode-se buscar, também, por combinações de opcodes e por dados específicos. Outra possibilidade do IDA Pro é a referência cruzada, citada como xref no IDA Pro, que informa onde uma função é chamada ou onde uma string é usada, como pode ser visto na Figura 3. Vejamos um caso de uso. Você identifica uma função útil e precisa saber os parâmetros com os quais ela é chamada; você pode usar uma referência cruzada para navegar rapidamente até o local em que os parâmetros são colocados na pilha através da referência cruzada. Gráficos interessantes também podem ser gerados com base em referências cruzadas, que são úteis para realizar análises. Por padrão, o IDA Pro mostra apenas algumas referências cruzadas para as funções; normalmente existem muitas chamadas a uma função durante a execução de um programa. Caso queira ver todas as referências cruzadas para uma função, basta clicar no nome da função e pressionar a tecla ‘x’; surgirá uma janela que conterá uma lista com todos os locais em queesta função é chamada. Basta dar um clique duplo no item da lista para ir ao local da memória referenciado. Conforme falamos nas aulas anteriores, a análise estática de strings pode frequentemente ser usada como ponto de partida para sua análise. Se você vir uma string interessante, use o recurso de referência cruzada do IDA Pro para saber exatamente onde e como essa string é usada no código. Basta realizar o mesmo procedimento da função: Selecionar a cadeia de caracteres a ser verificada e pressionar a tecla ‘x’. Outra característica muito utilizada é a edição de nomes. Ao carregar um binário dentro do IDA Pro, as funções e variáveis recebem nomes sem muito sentido. Durante a análise, ao encontrar o significado da função, você pode renomear o nome da mesma. Basta modificar o nome desta função ou variável em apenas um local; a ferramenta propagará o nome em todas as referências cruzadas e ficará muito mais simples identificá-la no código. Comentário A capacidade do IDA Pro de realizar a desmontagem do binário é apenas uma das partes de sua funcionalidade; sua capacidade interativa é o seu maior fator de facilitação. Códigos em C x Assembly Na aula anterior, revisamos a arquitetura x86 e suas instruções mais comuns. Entretanto, analistas de malware experientes não avaliam cada instrução individualmente, a menos que seja estritamente necessário. O processo é muito tedioso e as instruções para um programa inteiro desmontado podem chegar a milhares ou até milhões. Como analista de malware, você deve ser capaz de obter uma imagem de alto nível da funcionalidade do código, analisando as instruções como grupos, focando em instruções individuais apenas quando necessário. Essa habilidade leva tempo para ser desenvolvida. Para começar a desenvolver essa habilidade, vamos pensar em como um autor de malware desenvolve o seu código. O artefato é normalmente desenvolvido usando uma linguagem de alto nível; para nosso estudo utilizaremos a linguagem C. A estrutura do código é um nível de abstração que define uma propriedade funcional, mas não os detalhes de sua implementação. Exemplos de estruturas de controle de código incluem: Laços de repetição, instruções de decisão, listas encadeadas, instruções do tipo escolhas múltiplas e outras. Os programas podem ser divididos em construções individuais que, quando combinadas, implementam a funcionalidade geral do programa. Vamos analisar algumas construções em linguagem de alto nível e seu respectivo código em assembly. O analista normalmente faz o caminho inverso, porém aprender na direção reversa é geralmente mais fácil. Por isso, vamos nos concentrar em como as construções mais comuns, como laços de repetições e instruções condicionais, são compiladas. Comentário Lembre-se de que seu objetivo é compreender a funcionalidade geral de um programa, não analisar todas as instruções. Mantenha isso em mente e não se prenda a minúcias. Concentre-se na maneira como os programas funcionam em geral, não em como eles fazem cada coisa em particular. Iniciaremos com simples operações matemáticas e sua correspondente instrução em assembly. Mas, antes de iniciarmos, devemos preparar o ambiente para testes. Além de todas as recomendações já mencionadas, utilizaremos uma ferramenta para programar e compilar os códigos criados. Dica Usaremos o programa Dev-C++ disponível em: https://orwelldevcpp.blogspot.com/ DI ou web, site de fonte não acadêmica (blog). Por favor, verificar se é para manter ou não. Fonte: O autor. Figura 4: Aritmética Simples Na Figura 4 podemos verificar algumas aritméticas simples. Nesse exemplo, x e y são variáveis locais porque são referenciadas pela pilha: x = esp+0c e y = esp+8 – lembrando que o registrador ESP aponta para o topo da pilha. Por questões de performance, as variáveis foram tratadas apenas na memória, não sendo rotuladas pelo IDA Pro. Primeiro, a variável é inicializada com os valores 4 e 5, respectivamente, nas instruções 1 e 2. Depois, acrescentamos 12 unidades (0x0C em hexadecimal) na terceira instrução. Então, a variável y é movida (copiada) para eax e subtrai-se de x o valor contido em eax, instruções 4 e 5. Por fim, as últimas duas instruções incrementam e decrementam em uma unidade o valor de y e x, respectivamente. Apesar de ser um exemplo simples, começamos a entender como as coisas acontecem dentro do processador. ondemand_videoVídeo Fonte: O autor. Figura 5: Estrutura condicional javascript:void(0); As estruturas de controle são bastante utilizadas para alterar a execução do programa com base em certas condições. A figura acima exibe uma instrução em C e com o assembly correspondente. Em uma estrutura condicional deve haver um salto condicional, mas nem todos os saltos condicionais correspondem a uma estrutura condicional. Como você pode
Compartilhar