54

RevistaH2HC_8

Embed Size (px)

DESCRIPTION

revista

Citation preview

  • H2HC MAGAZINEEDIO 8

    AGOSTO DE 2O14

    Direo GeralRodrigo Rubira Branco

    Filipe Balestra

    Direo de Arte / Criao Amanda Vieira

    Coordenao Administrativa / Mdias Sociais

    Laila Duelle

    Redao / Reviso TcnicaGabriel Negreira Barbosa

    Ygor da Rocha Parreira Jordan Bonagura

    Leandro Bennaton

    Agradecimentos

    Equipe do Renegados CastJulio Moreira

    Raghudeep KannavaraFernando Mercs

    A H2HC MAGAZINE NAO SE RESPONSABILIZA PELO CONTEUDO DOS ARTIGOS, A RESPONSABILIDADE E DE SEUS RESPECTIVOS AUTORES.

  • ndice

    CURIOSIDADES

    HORSCOPO

    ARTIGOS

    14 a 15

    52 a 53

    4 a 13

    16 a 19

    20 a 43

    44 a 51

    ENGENHARIA REVERSA DE SOFTWARE

    FUNDAMENTOS PARA COMPUTAO OFENSIVA

    H2HC WORLD POR RENEGADOS CAST

  • A falha Heartbleed e seus Impactos nos Negcios

    POR JULIO MOREIRA

    O mundo da tecnologia (em especial o da segurana da informao) ficou em polvorosa quando, em abril/2014, foi divulgada uma falha crtica na biblioteca de criptografia OpenSSL[1], que ficou conhecida como HeartBleed [2][3]. A discusso que se viu em fruns e na mdia, especializada ou no, colocava em dvida qual o real impacto desta falha: seria possvel invadir o site? Interceptar comunicao criptografada? Qual a abrangncia do impacto causado? Apenas os sites que usam SSL? E os demais servios (e-mail, webmail, VPN), estariam seguros? Quais os ambientes afetados ( Windows, *NIX)?

    Como diria Jack, o Estripador, vamos por partes: antes de qualquer coisa importante entender, ainda que superficialmente, o que o OpenSSL e quais so as suas aplicaes. Uma vez esclarecida sua utilidade, devemos ento entender qual foi a falha descoberta, como ela pode ser explorada e o que ela nos d de informao do ambiente comprometido para, por fim, estabelecer uma estratgia de correo, com um plano de comunicao estabelecido (e adequado aos diversos nveis hierrquicos da empresa), a fim de no causar um temor desnecessrio tampouco ignorar os problemas futuros que possam ocorrer.

    Comeando pelo comeo: o que o tal do OpenSSL ?

    O OpenSSL um projeto colaborativo e de cdigo aberto que desenvolve e mantm um conjunto de ferramentas para implementao dos protocolos Secure Socket Layer (SSL v2/3) e Transport Layer Security ( TLS v1), bem como uma biblioteca robusta de criptografia para propsitos gerais [4].

    De acordo com a wikipedia[5], O Transport Layer Security - TLS (em portugus: Segurana da Camada de Transporte) e o seu antecessor, Secure Sockets Layer - SSL (em portugus: Protocolo de Camada de Sockets Segura), so protocolos criptogrficos que fornecem segurana de comunicao

    na Internet para servios como email (SMTP), navegao por pginas (HT TPS) e outros tipos de transferncia de dados. As informaes sensveis trafegadas variam de acordo com a aplicao executada no servidor em questo, mas, de uma forma geral, possvel citar informaes de autenticao (usurio e senha), transaes bancrias, e-mails com contedo confidencial e nmeros de carto de crdito, apenas para citar os mais facilmente identificveis.

    Entendendo um pouco mais o seu funcionamento, o protocolo SSL prov a confidencialidade (privacidade) e a integridade de dados entre duas aplicaes que comuniquem pela Internet. Isso ocorre atravs da autenticao das partes envolvidas e da cifra dos dados transmitidos entre as partes.

    Esse protocolo ajuda a prevenir que intermedirios entre as duas pontas da comunicao tenham acesso indevido ou falsifiquem os dados transmitidos.[5]

    A autenticao utilizada pelo protocolo SSL baseia-se na utilizao de um certificado digital, geralmente armazenado em um arquivo, que contm informaes referentes entidade (que pode ser uma empresa, pessoa, aplicao ou mesmo um computador) para qual ele foi emitido, alm da chave pblica desta entidade, de modo a identific-la unicamente dentro de um processo de autenticao.

    Esta chave pblica utilizada durante o processo de estabelecimento da conexo, a fim de trocar algumas informaes entre o cliente e o servidor, dentre elas a chave secreta que ambos utilizaro durante as trocas de pacotes subsequentes.

    importante ressaltar que o processo de handshake utiliza criptografia assimtrica; uma vez estabelecida a conexo, e durante as demais trocas de pacotes, a criptografia simtrica passa a ser utilizada.

    O processo de conexo, chamado de TLS Handshake, representado pela figura 1:

    4

  • Pode-se notar, nas linhas 3 e 5, a troca das chaves entre as partes. Agora que temos uma noo bsica de como o protocolo se comporta, vamos falar sobre a falha encontrada.

    A vulnerabilidade foi introduzida no cdigo h aproximadamente 2 anos (no vale a pena discutir se a insero foi proposital ou apenas falha de programao), porm no se sabe ao certo por quanto tempo ela foi utilizada para explorao de ambientes vulnerveis.

    A falha ocorre em um determinado trecho do cdigo do OpenSSL para checar se ambos os lados da comunicao esto vivos ( importante ressaltar que no se trata de um bug ou backdoor na implementao da criptografia no protocolo SSL/TLS, e sim no controle da comunicao entre as partes). Como o processo de estabelecimento da conexo e/ou da comunicao entre as partes pode sofrer com atrasos, seja por conta da

    rede ou de algum de seus elementos (roteadores, proxies e outros), os desenvolvedores valeram-se da extenso heartbeat, onde as partes envolvidas verificam se a outra parte permanece viva de modo que, se no houver resposta de um dos lados, a conexo encerrada.

    Exemplificando, o cliente (que voc) envia um determinado contedo dentro do pacote de heartbeat para o servidor (que pode ser do seu banco, por exemplo) e o servidor entrega o mesmo contedo de volta. Se algo der errado durante uma transao (por exemplo, se voc fechar o browser porque o site do banco est demorando a responder), o outro lado vai saber (atravs dos dados do heartbeat, que ficaro fora de sintonia) e encerrar a conexo.

    A estrutura sugerida pela RFC 6520[8] para determinar o pacote do heartbeat composta por 4 partes: type (que pode ser heartbeat_request para requisitar ou heartbeat_response para responder), o payload_length (um inteiro sem sinal de 2 bytes usado para indicar o tamanho do payload enviado na requisio), o payload e padding. A extrao desta estrutura pode ser vista na listagem 1:

    struct { Hear tbeatMessageType type;uint16 payload_length;opaque payload[Hear tbeatMessage.payload_length];opaque padding[padding_length];} Hear tbeatMessage;

    A falha no cdigo conhecida (e considerada clssica) no desenvolvimento: trata-se de um buffer over-read bug, cuja explicao mais simples a de poder ler os dados que esto alm do final do buffer que foi especificado na memria.

    A RFC diz que a resposta do servidor deve conter o payload recebido no request. Porm, no momento de codificar a extenso, o programador no previu testar se o valor que veio no campo payload_length mesmo o tamanho da mensagem encaminhada no campo payload.

    Assim, se o lado cliente manda um pacote pequeno de heartbeat e insere o valor 0xFFFF no campo payload_length, a funo vai copiar da memria 65.535 bytes e retornar ao cliente, sem reclamar.

    Colocando de uma forma mais didtica, vamos acompanhar as figuras 2 e 3:

    A vulnerabilidade foi introduzida no cdigo h aproximadamente

    2 anos, porm no se sabe ao certo

    por quanto tempo ela foi utilizada

    para explorao de ambientes vulnerveis

    Figura 1 Handshake de iniciao do protocolo SSL/TLS, baseado em [6]

    Listagem 1 Estrutura do pacote heartbeat

    5

  • No passo 1 do fluxo normal (figura 2), o cliente envia o request passando como mensagem a palavra MSGHBEAT e setando o tamanho para 8. Cabe ressaltar que, normalmente, o payload composto de 2 bytes fixos sequenciais seguidos de 16 bytes aleatrios. O OpenSSL recebe este request e retorna um outro pacote, contendo a palavra enviada (MSGHBEAT ) e o tamanho setado para 8 (passo 2).

    A vulnerabilidade, conforme j explicado anteriormente e ilustrada pela figura 3, consiste em enviar um pacote com uma mensagem pequena (neste caso, MSGHBEAT no passo 1) mas com o valor mximo que o campo tamanho suporta ( em hexa: 0xffff ). Ressalta-se que, para realizar o ataque, s realmente necessrio definir os 2 primeiros campos, type e

    palyload_length. A verso do OpenSSL que est vulnervel devolve a palavra chave e tudo o que estiver na memria subsequente ela, at o limite de 65.535 bytes (passo 2). No se tem preciso de quais informaes podem ser capturadas, porm a experincia mostra que fazendo-se diversas requisies, onde em cada uma o atacante consegue obter cerca de 64kb de memria do servidor, pode-se recuperar certificados, contas de usurios de sistemas que o servidor hospeda, chaves privadas do certificado e outras informaes sensveis.

    Agora, vamos imaginar as consequncias disso para usurios de bancos, servios de e-mail, armazenamento de fotos: com a chave privada na mo, possvel realizar ataques de Man-in-the-middle (forma de ataque em que os dados trocados entre duas partes, por exemplo, voc e o seu banco, so de alguma forma interceptados, registrados e possivelmente alterados pelo atacante). H diversas outras informaes que podem ser capturadas: tudo que estiver na memria naquele momento como, por exemplo, credenciais, documentos, emails e etc. O cu o limite!

    Vamos extrapolar um pouco mais: e se ficarmos coletando informaes de um appliance de VPN que usa a verso do OpenSSL que est vulnervel? Neste caso, podemos obter, por exemplo, credenciais vlidas de acesso rede

    corporativa, podendo ento utiliz-las a fim de se obter uma conexo vlida com esta rede. Normalmente, um servio de VPN configurado para registrar as atividades em log; ainda assim, uma conexo com esta caracterstica (credenciais vlidas) demora mais tempo para ser detectada do que se tentssemos faz-lo utilizando-se alguma outra tcnica (ataque de fora bruta, por exemplo).

    A correo para este problema muito simples, porm requer alguns cuidados: deve-se realizar o upgrade da verso do OpenSSL para a mais recente, que corrige esta falha no cdigo, solicitar a troca das credenciais de acesso de todos os usurios que utilizam este ativo, alm de revogar todos os certificados instalados nestes servidores, solicitando novas emisses. Sim, isso mesmo! No apenas comprar novos: temos que revogar os atuais! No, eu no trabalho em nenhuma empresa que vende certificados. - E por que cargas dgua voc est recomendando isso? Simples: A falha pode ter sido explorada desde que foi introduzida no cdigo, logo no podemos afirmar que nossos certificados, credenciais de acesso, e-mails e etc no tenham sido coletados e estejam sendo usados para outros fins.

    Para finalizar este artigo, vamos abordar a questo crucial: - E como eu conveno os executivos

    Figura 2 Fluxo normal de Heartbeat, baseado em [9]

    Figura 3 explorando a vulnerabilidade, baseado em [9]

    6

  • o problema e discutir a soluo com voc voc foi contratado para solucionar problemas, no ficar compartilhando com ele as possveis solues!

    Para no ficar nestas frmulas mgicas que todos ns vemos por a que parecem mais auto-ajuda (no menosprezo nenhum tipo de literatura a este respeito, s acho que, na maioria das vezes, o cenrio desenhado por este tipo de literatura no condiz em nada com nossa realidade), vou colocar na prtica a estratgia que usei para ganhar o suporte e a confiana dos executivos da empresa que trabalho para realizar a atualizao dos servidores e assegurar a compra de novos certificados.

    To logo eu recebi a informao desta vulnerabilidade, pesquisei na Internet (fruns, sites de notcia, site da comunidade mantenedora do OpenSSL, o prprio CVE do MITRE, blogs, etc) tudo que pudesse me clarificar do que se tratava e quais as medidas corretivas necessrias para elimin-la ou, ao menos, control-la. Li diversas discusses a

    da minha empresa acerca dos problemas causados por essa vulnerabilidade para que suportem o plano de ao que estabeleci (inclusive com verba para comprar novos certificados, se for o caso algumas autoridades certificadoras se propuseram a fazer a revogao e nova emisso sem custo) para elimin-la do meu ambiente?.

    O primeiro passo, e o mais importante na minha opinio, no fazer FUD (Fear, Uncertanly and Doubt termo usado para definir abordagens que pressionam os executivos pela ameaa e por gerar incerteza) a chance de se ganhar um sonoro NO grande. A abordagem que costuma dar certo comigo consiste em voc embasar seu discurso naquilo que o executivo entende, de forma direta e pragmtica: explicar que existe um problema (neste caso, que no afeta apenas a nossa empresa), que j temos a soluo e um plano para a execuo, que o time j est mobilizado para realizar as atividades, que haver um custo (se realmente houver) que precisa ser aprovado e qual o impacto (financeiro mais palpvel para eles - ou indireto) que eliminaremos com a ao em curso.

    Importante: no pea permisso, seja proativo e diga que j est executando as correes necessrias. Nestas horas, ser diretivo d mais confiana ao executivo de que voc est no caminho certo e de que ele no precisar entender

    respeito do que poderia ser capturado com este ataque (Conseguimos capturar a chave privada ou no? D acesso ao arquivo de logins ou senhas ou no? Que outros dados so passveis de vazamento?), quais ambientes esto comprometidos (Linux, Unix, Windows, Mac OS). Em seguida, e com base nas informaes de ambientes comprometidos e o que poderia ter sido capturado (assumi que o certificado era uma das possveis informaes vazadas), estabeleci uma lista dos ativos que poderiam estar comprometidos e qual(is) processo(s) crtico(s) dependia(m) destes ativos.

    Com a lista estabelecida, entrei em contato com o time que suporta a operao do Datacenter e solicitei que: (1) confirmassem qual a verso do OpenSSL que estava sendo executada (minha diretiva neste ponto foi clara: deveramos saber todos os servidores que estavam com o OpenSSL vulnervel (IMPORTANTE: verses anteriores a verso 1.0.1 no esto vulnerveis falha do HeartBleed especificamente, mas podem estar vulnerveis a inmeros outros problemas!) , no apenas os que foram identificados anteriormente) e (2) executassem uma mudana emergencial para realizar o upgrade da verso do OpenSSL, comeando obviamente pelos ativos que suportavam processos crticos mas no se limitando a eles, uma vez que manter o ambiente com

    O primeiro passo, e o mais importante na minha opinio, no fazer FUD - a

    chance de se ganhar um sonoro NO

    grande

    7

  • era preventiva, porque a correo em si j estava sendo conduzida pelo time do Datacenter e que, to logo fosse finalizada, eles seriam comunicados a respeito.

    Com a aprovao deles, restou apenas coordenar as atividades de substituio e revogao dos certificados nos ambientes.

    Resumo: em menos de uma semana estvamos com o parque atualizado, certificados trocados e os executivos cientes que eu e o time da TI fizemos o que tinha que ser feito.Vejam que, na abordagem usada, em nenhum momento eu usei termos tcnicos ou entrei no detalhe de como a falha ocorria e era explorada; apenas expus, com fatos e argumentos no-tcnicos, o que precisava ser feito.

    O resto histria.

    uma verso desatualizada em servidores no crticos pode se tornar um ponto de partida para se obter informaes para atacar o restante do ambiente.

    Em paralelo, solicitei a nossa parceira emissora de certificados que iniciasse o processo de gerao de novos certificados (como no tnhamos muitos, o custo foi, de certa forma, irrisrio), que envolviam a aprovao dos executivos (a famosa validao telefnica).

    Uma vez acertado com a emissora, fui at o Comit Executivo e expliquei, sem entrar em detalhes tcnicos, que havamos descoberto uma falha em um componente de mercado que era responsvel por garantir o sigilo de nossas transaes, que este componente era largamente usado (inclusive por nossos concorrentes) e que, por precauo, devamos trocar nossos certificados (nas minhas palavras, aquele arquivo que permite fechar o cadeado no Internet Explorer quando voc est acessando o site do banco e que garante que ningum alm de voc est vendo suas transaes) atuais por novos. Por este motivo, eu precisaria da disponibilidade da agenda deles para fazer a validao por telefone para emitir os novos certificados e que o custo seria absorvido por ns, economizando algum dinheiro em alguma negociao com fornecedores para renovar licenas. Deixei claro a eles que esta medida

    [1] - http://w w w.openssl.org/, acessado em 10/06/2014[2] - http://w w w.openssl.org/news/secadv_20140407.tx t [3] - http://hear tbleed.com/, acessado em 10/06/2014[4] w w w.openssl.org/about/, traduo livre em 15/06/2014.[5] - http://pt.wikipedia.org/wiki/Transpor t_Layer_Securit y, acessado em 15/06/2014[6] https://devcentral.f5.com/ar ticles/ssl-profiles-par t-1[7] CVE acrnimo de Common Vulnerabilities and Exposures, um dicionrio de nomes comuns (identificadores) para vulnerabilidades de segurana da informao para fins de conhecimento pblico. A coordenao do CVE per tence ao MITRE, uma organizao sem fins lucrativos que opera centros de pesquisa e desenvolvimento patrocinados pelo governo federal dos EUA.[8] http://tools.ietf.org/html/r fc6520[9] http://fronterahouse.com/blog/ultimate-hear tbleed- guide-for-non-techies/

    JULIO CEZAR DE RESENDE MOREIRATem 39 anos, formado em Tecnologia de Processamento de Dados pela Univ. Mackenzie em 1996 e ps-graduado em Gesto Empresarial pela FEI em 2006, trabalha com Tecnologia da Informao desde os 16 anos. Comeou sua carreira atuando em desenvolvimento de sistemas e teve passagens por suporte tcnico e arquitetura. Atua com segurana da informao desde 2001. Atualmente gerente de segurana numa multinacional francesa do varejo. apaixonado por tecnologia, artes marciais e msica (esta ltima como ouvinte apenas).Possui certificaes CISSP, ISO 27001 Lead Auditor e MCSO.

    8

  • FALTA POUCO PARA A PRXIMA H2HC !

    VOC EST PRONTO PARA A SUA MAIOR

    AVENTURA TECNOLGICA NA SELVA?

    GARANTA J SEU INGRESSO EM NOSSO SITE

    www.h2hc.com.br

  • Segurana de Software Open Source atravs de Anlise Esttica.

    POR RAGHUDEEP KANNAVARA

    Para maiores detalhes, bem como referncias afirmaes feitas neste ar tigo, o leitor pode consultar a fonte que deu origem ao texto: [1].

    Apesar da SCA (Static Code Analysis - Anlise Esttica de Cdigo) no ser uma nova tecnologia, ela tem recebido muita ateno e est sendo rapidamente adotada como uma atividade fundamental no Ciclo de Desenvolvimento de Software, visando melhorar a qualidade, confiabilidade e segurana do software. A maioria dos estabelecimentos de desenvolvimento de software tm uma equipe dedicada de profissionais de validao de software, onde entre as responsabilidades est includa a execuo de ferramentas de anlise esttica no software em desenvolvimento, seja em um ambiente gil ou em um modelo em cascata tradicional. Ferramentas de SCA so capazes de analisar o cdigo desenvolvido em diversas linguagens de programao e frameworks que incluem e no se limitam a Java, .Net e C/C++.

    Seja o objetivo desenvolver um aplicativo de software ou um firmware embarcado de misso crtica, ferramentas de anlise esttica provaram ser um dos primeiros passos para a identificao e eliminao de erros de software, sendo fundamentais para o sucesso global do projeto de software. Licenciamento e aplicao exaustiva de ferramentas de anlise esttica em um projeto de desenvolvimento de software so tarefas caras, mas so geralmente utilizadas por empresas de software proprietrio para melhorar a qualidade do produto.

    O que ento permanece como um vazio expansivo e inexplorado so os domnios interminveis de cdigos open source, geralmente vistos como tendo sido bem revisados por terem sido utilizados e reutilizados em um nmero incontvel de aplicaes por inmeras instituies acadmicas e comerciais em todo o mundo. 'Expansivo' indicando que est constantemente adicionando novos cdigos fonte e 'Inexplorado' indicando a ausncia de uma entidade imparcial

    dedicada a analisar estaticamente cada linha de cdigo open source.

    Adicionalmente, nos ltimos tempos, os projetos de cdigo aberto tm ciclos de lanamento relativamente mais rpidos em comparao com cdigo fechado. Por exemplo, o Android tem lanamentos a cada 3 meses enquanto o Windows a cada 3 anos. A taxa de inovao que est sendo conduzida pelo open source atravs das indstrias mobile, cloud e big data enorme.

    Mesmo empresas de SCA como Klocwork e Coverity terem tomado iniciativa em analisar cdigos open source e compartilhar os resultados com a comunidade, a taxa com que novas verses de software open source so lanados ou atualizados apresenta uma barreira a estes esforos. Embora tal esforo seja, por muitos, atribudo parania, evidente que a crise financeira e a diminuio de verba de TI levaram o software open source a entrar em aplicaes comerciais, por exemplo, Linux, Apache, MySQL e OpenSSL. Alm disso, esforos como os programas do Centro de Software Assegurado (CAS) da NSA que apresentaram um estudo de ferramentas de anlise esttica para C/C++ e Java no ano 2010 usando casos de teste disponveis como Juliet Teste Suites, so um passo na direo correta, mas, mesmo assim, no h mtricas absolutas para a escolha de uma ferramenta SCA particular.

    Na maioria das instituies de desenvolvimento e teste de software, apesar do produto de software como um todo ser submetido a anlise dinmica, como fuzzing ou teste de caixa preta, e o cdigo de software recentemente desenvolvido ser submetido a uma rigorosa anlise esttica, cdigos open source incorporados no software geralmente no esto sujeitos mesma rigorosa anlise esttica. Isto pode estar baseado no pressuposto de que o software de cdigo aberto mais seguro e possui menos bugs do que o software de cdigo fechado devido ao fato de o cdigo fonte estar disponvel de forma

    10

  • Tendo dito isto, ressalta-se que as vulnerabilidades detectadas somente por SCA no sero abrangentes, uma vez que algumas falhas so dependentes de run-time, mas uma certa classe de vulnerabilidades pode ser detectada por SCA, incluindo buffer overflows, integer overflows/underflows, erros de sinais de inteiros e inicializao imprpria de memria. Estas so algumas das vulnerabilidades que tm sido frequentemente exploradas para lanar ataques maliciosos em diversas aplicaes de software.

    Assim, observado o fluxo de trabalho convencional, ilustrado na Figura 2, que sujeita o cdigo recm-desenvolvido para uma rigorosa SCA enquanto o cdigo open source geralmente no, e, assim, ter afirmado que uma certa classe de vulnerabilidades

    gratuita e de haver muitas pessoas olhando para ele. Outra razo que pode haver restries de licena relacionadas alteraes realizadas em cdigo open source.

    Apesar do fato de essa suposio ter resistido ao teste do tempo, e provvel que no possa ser provada como errada, na realidade, e no surpreendentemente, executando uma ferramenta popular de SCA contra uma base de cdigo open source muito popular como o kernel do Linux, v2.6.32.9, revela-se que um determinado subconjunto das vulnerabilidades publicadas no NVD (National Vulnerability Database), aps o lanamento desta verso do kernel, poderia ter sido detectado muito mais cedo caso a anlise esttica diligente tivesse sido executada anteriormente, por exemplo, antes do lanamento do kernel. O nmero de vulnerabilidades encontradas no kernel do Linux por anlise esttica, juntamente com suas reas, esto ilustradas na Figura 1.

    pode ser detectada precocemente por SCA, o que naturalmente inclui vulnerabilidades em cdigo aberto, torna-se bvio que benfico incluir a sada da ferramenta SCA tanto para software recentemente desenvolvido quanto para software open source adotado, no pacote de

    reviso formal de software.Qualquer bug de software encontrado pela anlise esttica corrigido em ambos os cdigos, open source e recm desenvolvido, antes de ser submetido a anlise dinmica e bem antes de ser eventualmente lanado para o mercado. Este processo pode no encontrar todos os bugs, mas vai ajudar a pegar alguns erros no incio, proporcionando uma oportunidade para corrigi-los mais cedo. Mas, em praticidade, embora a anlise esttica de cdigo open source adotado seja til na identificao de certos bugs de software desde o incio, h desafios e trade-offs tcnicos e de projeto que podem no fazer desta uma proposio vivel em determinadas Figura 1- Nmero de vulnerabilidades por categoria significativa no kernel do Linux (v2.6), publicada

    no NVD (2010-11).

    Figura 2 - Processo de desenvolvimento de software convencional

    11

  • gerados sejam claros, mas a outra parte da equao o sensvel processo de utilizar desenvolvedores mais experientes dentro da organizao para auxiliar na anlise, bem como providenciar treinamento adequado a quem for necessrio. No entanto, uma vez que os falsos positivos so eliminados, comunicar os problemas genunos encontrados para as equipes de desenvolvimento corrigirem faz-se necessrio. s vezes, isso pode exigir as correes serem comunicadas aos mantenedores do software open source antes do lanamento do produto, com base nos termos da licena do software open source.

    Uma vez que o processo com segurana reforada para incorporao de software open source, ilustrado na Figura 3, envolve uma enorme quantidade de esforo e relativamente desafiador, uma forma de enderear

    situaes, como discutido mais adiante. Ferramentas SCA tendem a produzir um grande nmero de falso-positivos. Rever e eliminar falso-positivos podem ser tarefas intimidadoras tanto para as equipes quality assurance quanto para as de desenvolvimento, especialmente quando os projetos esto enfrentando severas restries de recurso, tempo e oramento. Alm disso, falso-positivos podem ser reais ou perceptuais. A primeira categoria so casos em que a ferramenta apenas est errada, precisa ser ajustada ou o verificador necessita somente ser desligado para aquela particular base de cdigo.

    A outra categoria de falso-positivos (perceptual) mais um problema de educao e/ou priorizao do desenvolvedor. Muitas vezes, especialmente no caso de falhas de segurana ou erros de confiabilidade mais sutis, a ferramenta est correta, mas o desenvolvedor no compreende por que um problema ou no se preocupa tanto com o problema especfico, ou seja, educao ou priorizao. Alm disso, diferentes vendedores de SCA tendem a encontrar problemas diferentes em uma mesma base de cdigo, mas essa pesquisa detectou que utilizando 3 diferentes ferramentas de anlise esttica pode-se garantir uma boa cobertura de cdigo. Compete ao fornecedor das ferramentas garantir que os relatrios de bugs

    este desafio poderia ser identificar os componentes crticos (componentes com histrico de vulnerabilidades) do projeto e concentrar esforos de SCA sobre eles, por exemplo, componentes de 'rede'.

    Outra forma poderia ser se concentrar em componentes de maior complexidade no cdigo open source adotado. Arquivos de maior complexidade tm maior probabilidade de gerar erros durante a correo, melhoria ou refatorao do cdigo fonte. Na maioria dos projetos de cdigo aberto, a maior parte do esforo de desenvolvimento comunicado atravs de listas de discusso. Os desenvolvedores esto espalhados por todo o mundo e tm diferentes nveis de habilidades de desenvolvimento de software. uma tarefa desafiadora para qualquer entidade central responsvel pela coordenao dos esforos

    Figura 3 - Processo de desenvolvimento de software com segurana aprimorada

    12

  • necessrio para o produto no processo de validao geral do software. Uma analogia pode ser feita com a abordagem de build. Ao utilizar uma biblioteca open source, o desenvolvedor deveria baixar um binrio e o inclui-lo diretamente no build ou baixar o cdigo fonte e compil-lo nos milestones do projeto? Por no se utilizar o binrio diretamente e baixar o cdigo fonte e compil-lo nos milestones do projeto, o projeto estaria protegido contra detalhes do ambiente de compilao de terceiros, que podem no ser relevantes ao projeto.

    Se assim for, por que no incluir esse mesmo cdigo open source na execuo da anlise esttica juntamente com o cdigo recm-desenvolvido? bem compreendido na indstria de software que quanto mais cedo um bug possa ser detectado, mais barato ser para corrigi-lo, evitando assim caras aes judiciais ou danos irreparveis

    reputao da empresa. De muitas formas, este esforo extra fundamental para melhorar a qualidade, confiabilidade e segurana gerais do produto de software. Resultados recentes indicam que projetos de cdigo aberto com uma comunidade de desenvolvimento ativa e com comprometimento com a qualidade esto implementando com sucesso anlise esttica e outras medidas de controle de qualidade da mesma forma que projetos comerciais. Por fim, as organizaes que podem arcar com o custo de ferramentas SCA e das mudanas no processo, e tm uma forte necessidade de segurana, encontraro valor neste esforo.

    Referncias:[1] Raghudeep Kannavara, "Securing Opensource Code via Static Analysis", 2012 IEEE Sixth International Conference on Software Testing, Verification and Validation, pp. 429-436.

    de desenvolvimento. Concentrar SCA nestes componentes de maior complexidade ou criticidade pode economizar verba, tempo e recursos por reduzir o escopo da reviso. Alm disso, somente SCA no suficiente; pode-se solicitar reviso de cdigo, fuzzing e outras atividades de validao para melhorar a segurana de software.

    Em resumo, fortificar o cdigo open source que incorporado em um software comercial to importante quanto fortificar o software proprietrio em si. As linhas entre projetos comerciais e projetos open source esto ficando mais fracas devido ao aumento contnuo da adoo do software de cdigo aberto no desenvolvimento de software comercial. O Gartner prev que, at 2014, 50% das organizaes Global 2000 vo vivenciar desafios de tecnologia, custo e segurana pela falta de governana open source. Open source onipresente, inevitvel; ter uma poltica contra o open source impraticvel e coloca a organizao em desvantagem competitiva.

    Por outro lado, a necessidade imediata ter polticas para obter formalmente software open source e entender, gerenciar e mitigar seus riscos de adoo. Juntamente com a validao cuidadosa de software proprietrio recentemente desenvolvido utilizando SCA, tambm altamente desejvel incluir anlise esttica de qualquer cdigo open source

    RAGHUDEEP KANNAVARA

    Raghudeep Kannavara atualmente trabalha como Security Architect/Researcher e Technology Analyst na Intel Corp., Hillsboro, OR, USA. especialista em threat assessment, vulnerability assessment, validao de segurana, security development lifecycle e design for security. Possui PhD em Engenharia da Computao e tem publicado extensivamente no IEEE sobre diversos temas de segurana.

    13

  • FOREWORDS Por Gabriel Negreira Barbosa

    A par tir de agora, as edies da H2HC Magazine contam com a coluna Curiosidades. A principal ideia dessa coluna abordar temas curiosos de maneira descomplicada. Desta forma, sero discutidos somente os detalhes estritamente necessrios para a clara compreenso do leitor.

    Convidamos os leitores a enviar sugestes de assuntos a serem abordados nas edies futuras. Para os interessados em se aprofundar nos temas tratados, no deixem de nos escrever: ser um prazer trocar ideais e compar tilhar material mais detalhado a respeito! Esperamos que gostem! Boa leitura!

    CURIOSIDADES

    O HOST EST REALMENTE INDISPONVEL?POR YGOR DA ROCHA PARREIRA

    Em um ambiente de rede local comum testar a disponibilidade de um determinado equipamento utilizando o comando ping. Quando no h resposta assume-se que o equipamento est desligado ou indisponvel. Mas ser que isto sempre verdade? Podemos realmente assumir que estando em um mesmo ambiente de rede local1, quando um determinado host no responde ao comando ping porque ele encontra-se indisponvel? O que mais poderamos verificar para chegar a uma concluso mais acertada?

    Os sistemas operacionais mais comumente encontrados em ambiente de rede local so alguns dos sabores de Windows. Estes sistemas operacionais j vem com um firewall ativo, por padro j com algum comportamento pr-definido. Nas verses mais recentes do Windows, por padro este comportamento definido de acordo com o perfil de classificao da rede (pblica, particular, etc), onde quando a rede definida como sendo pblica o sistema operacional bloqueia as solicitaes feitas pelo comando ping. Para exemplificar, a Figura 1 mostra um ambiente tpico de rede local, onde temos um host Windows 8.1 que vai ser testado a partir de outro host Windows XP.

    A Listagem 1 mostra o host 192.168.1.162 executando o comando ping contra o host 192.168.1.158 ( Windows 8.1), onde no obtida resposta do host.

    Figura 1 Topologia do ambiente testado

    Listagem 1 Testando com o comando ping contra o host Windows 8.1

    1 -Por ambiente de rede local etentende-se um conjunto de mqunas no mesmo segmento fsico e lgico, sem roteadores e f irewalls de rede no meio do caminho

    14

  • Sabendo que os dois hosts esto ligados e ativos na rede, por que o Windows 8.1 no responde? Isto acontece porque o firewall do sistema operacional bloqueia as solicitaes de ping. Ento o que mais podemos verificar para checar a disponibilidade do host Windows 8.1? Conhecendo como ocorre uma comunicao via rede, sabemos que antes dos pacotes do ping serem enviados, pacotes de resoluo de endereos fsicos (endereos MAC Media Access Control) devem ser trocados. Neste caso, o endereo MAC resolvido o do host testado, pois se encontram no mesmo segmento de rede fsico e lgico. Apesar da maioria dos f irewalls (inclusive o do host testado) terem a capacidade de filtrar estes tipos de pacotes, quase nunca o fazem.

    Assim sendo, uma entrada inserida na tabela de cache ARP local do host que executou o comando ping, esta tabela pode ser consultada para determinar se o host testado realmente se encontra indisponvel. A Listagem 2 mostra esta verificao:

    possvel notar que apesar do Windows 8.1 no responder ao comando ping, o host se encontra ativo visto que respondeu a solicitao de resoluo de endereo fsico.

    Caso o host testado (Windows 8.1) estivesse de fato indisponvel, o mapeamento fsico no apareceria na tabela de cache ARP. Quando o sistema que realiza o teste um Linux, para este mesmo comportamento (host indisponvel), criada uma entrada do tipo na tabela de cache ARP local.

    Listagem 2 Verificando a tabela cache ARP local do Windows XP

    Ygor da Rocha Parreira faz pesquisa com computao ofensiva, trabalha como consultor de segurana de aplicaes na Trustwave e um cara que prefere colocar os bytes frente dos ttulos.

    YGOR DA ROCHA PARREIRA

    TREINAMENTO

    15

  • FOREWORDS Por Fernando Mercs

    Imediatamente aps terminar a leitura da nova coluna "Fundamentos para Computao Ofensiva", pensei na existncia de uma coluna com uma didtica similar, mas com foco em engenharia reversa. Cer tamente as duas colunas juntas se reforariam, j que o aprendizado de ambos os assuntos podem ter sequncia juntos. Pois aqui estamos, com a nova coluna sobre engenharia reversa de soft ware . Tenho a honra de inaugur-la e o compromisso de conduzir o leitor nesse estudo dirigido.

    Por que estudar engenharia reversa?

    "Algumas pessoas vem coisas que existem e perguntam, Por que?Algumas pessoas sonham com coisas que nunca existiram e perguntam, Por que no?

    Algumas pessoas precisam ir pro trabalho e no tm tempo para isso tudo." (George Carlin)

    Mas se queres motivos, posso citar vrios. O aprendizado de como um programa *realmente* se compor ta ao ser executado no sistema operacional um deles. Outra util idade reimplementao de recursos, por exemplo, suponha que um programa proprietrio salve um formato de arquivo tambm proprietrio. Formato este que voc gostaria de abrir (ler o arquivo) sem ter de pagar por um programa s para isso, j que seu interesse est no contedo do arquivo, no no soft ware que o mostrar. Com engenharia reversa voc pode verificar o algoritmo que o programa proprietrio segue para abrir o tal formato e implementar seu prprio algoritmo similar, de forma livre. Agradea engenharia reversa por ter clientes de IM ( Instant Messenger) l ivres que se comunicam com vrias redes de mensageria, por abrir arquivos do Office fora dele e por mais centenas de recursos implementados em diversos soft ware e hardware , l ivres ou no.

    Em segurana, um uso comum a anlise de vulnerabilidade (sem o cdigo) e a anlise de malware . O mercado est em alta. O cracking (neste caso, remoo de proteo contra cpias i legais) de soft ware tambm tem sua base na engenharia reversa, no entanto vale lembrar que em alguns pases criminalizado como pirataria.

    A engenharia reversa nomeada de tal forma porque, com ressalvas, como "ler, e poder alterar o cdigo fonte do programa sem t-lo". Entre aspas porque na realidade o cdigo fonte no vai para o programa compilado.

    Os exemplos citados aqui no esgotam suas possibilidades de uso. Como sempre "Criatividade mais impor tante que conhecimento" (Einstein), ou seja, o que voc pode fazer com engenharia reversa (e com outras ar tes) s depende de voc. No h limites. E sim, a ER (como a chamarei algumas vezes daqui em diante) uma ar te. possvel criar a par tir do criado, rever ter, distorcer, adicionar, remover, refazer o que foi feito. O engenheiro reverso , com efeito, um ar tista. :)

    ENGENHARIA REVERSA DE SOFTWARE

    INTRODUO ENGENHARIA REVERSAPOR FERNANDO MERCS

    "No sabendo que era impossvel, foi l e fez" (Jean Cocteau/Mark Twain)

    Tratando-se de linguagens compiladas (C, C++, Delphi, etc), o processo prtico de criao de um programa , basicamente:

    1. Escrita de cdigo (em texto mesmo).2. Compilao.

    3. Link-edio (linking).

    Quando o foco a criao de um programa para ser executado nos principais sistemas operacionais para PC, o resultado final deste processo , geralmente, um executvel ou uma biblioteca. E assim um software distribudo, podendo ter vrios executveis, bibliotecas e outros arquivos em seu pacote

    16

  • de distribuio, e/ou ainda um programa de instalao. Sem acesso a seu cdigo fonte (o que normalmente acontece quando o software proprietrio), como saber exatamente o que o programa faz? Como garantir que o binrio faz realmente o que o cdigo-fonte diz?

    A maioria dos desenvolvedores de software concentra seus estudos na primeira etapa do processo descrito (escrita de cdigo) j que as outras duas so de responsabilidade do ambiente de compilao. De fato, a maioria dos programadores no faz ideia do que um executvel e de que ele pode ser revertido (analisado por engenharia reversa) e at alterado.

    Mas possvel saber o que o programa faz e como faz. Tudo com engenharia reversa. Vamos analisar um primeiro programa que faz, simplesmente, nada. :)

    Usando uma distribuio Linux qualquer com o gcc, crie um arquivo nada.c com o seguinte contedo (testado com Debian 7 64-bits, kernel 3.8.0, GNU Make 3.81 e gcc 4.7.3).

    int main() { return 9; }

    E depois execute:

    $ make nadacc nada.c - o nada

    Como pode ver, o ambiente de compilao chamado para compilar o arquivo nada.c e gerar o executvel nada. No Linux, normalmente o cc um link para o compilador gcc. Nesta construo, o make no precisa de um Makefile. ;)

    O que voc acabou de fazer em uma linha envolve processos bem complexos. Aps validar toda a sintaxe da linguagem C, o ambiente de compilao gerou um cdigo compreensvel para o processador da arquitetura que voc utilizou, resolveu nomes de funo (que voc tenha escrito, s a main, neste caso) e linkou seu programa com a biblioteca padro da linguagem C (libc). No caso das distros Linux convencionais, a libc geralmente utilizada a glibc (GNU C Library).

    Alm disso, o executvel gerado segue um padro, um formato. No caso dos executveis no Linux, esse formato geralmente o ELF [1].

    Percebe quanto trabalho feito depois da escrita do cdigo, normalmente tida como trmino da construo do programa? ;)

    O exemplo nada, apesar de meio vago (hehe), um timo exemplo, pois suponha que voc se depare com este programa compilado e o execute. Como ele "no vai fazer nada", ficar aquela sensao de "ih.... O que aconteceu?", ou no ? Nem pense duas vezes, ER nele!

    Antes de propriamente reverter o binrio, vamos dividir o processo em dois estgios. O disassembly, que o processo de gerar cdigo ASM (como chamarei a linguagem Assembly em alguns casos daqui em diante) a partir do cdigo de mquina presente no executvel ou biblioteca, e a depurao (ou debugging), que o processo de executar um certo nmero de instrues, uma de cada vez, a fim de observar o comportamento gradual do programa.

    Tenha em mente que o processo de compilao gerou um arquivo binrio, ou seja, uma srie de bytes "um ao lado do outro" no disco. A maior parte desses bytes no representa aquela nica linha de cdigo fonte do programa nada, mas sim a estrutura do ELF. J que este arquivo no passa de um monte de bytes (estrutura ELF, cdigo de mquina e etc), vamos olhar tais bytes com um visualizador hexadecimal:

    $ hd nada00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 | .ELF.... . . . . . . . . |00000010 02 00 3e 00 01 00 00 00 00 04 40 00 00 00 00 00 | . .>..... . .@.....|00000020 40 00 00 00 00 00 00 00 70 11 00 00 00 00 00 00 |@..... . .p.... . . . |00000030 00 00 00 00 40 00 38 00 09 00 40 00 1e 00 1b 00 | . . . [email protected]...@.....|00000040 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 00 | . . . . . . . .@..... . . |00000050 40 00 40 00 00 00 00 00 40 00 40 00 00 00 00 00 |@.@.....@.@.....|00000060 f8 01 00 00 00 00 00 00 f8 01 00 00 00 00 00 00 | . . . . . . . . . . . . . . . . |

    17

  • O hd (hexdump), criado originalmente para o BSD, um visualizador hexadecimal (no um editor porque ele somente l). Dos conceitos de computao, sabemos que um byte (na arquitetura Intel IA-32, a qual estamos admitindo aqui) corresponde a 8 bits, logo, pode variar de 0 a 255 (assumindo que estamos falando de nmeros inteiros sem sinal), ou seja, 2^8 possibilidades. O que o hexdump faz mostrar, por padro, 16 bytes por linha, cada um separado por espao e dois grupos de 8 bytes separados por 2 espaos, mas ao invs de mostrar em decimal (0-255), ele o faz em hexadecimal, que vai de 00 at FF (em decimal, de 0 a 255, respectivamente). Por que em hexadecimal? Porque dessa forma voc precisa de menos caracteres para representar maiores quantidades, j que a base 16. O prprio 255, por exemplo, precisa de 3 caracteres para ser representado em decimal, enquanto em hexa bastam dois: ff.

    Na primeira coluna o hd mostra o offset (posio relativa) do byte. No exemplo acima, o byte na posio relativa 0x60 ao incio do arquivo 0xf8, enquanto o byte na posio relativa 0x61 0x01. E o byte na posio relativa 0x68 ? :)

    A ltima coluna a representao ASCII [2] dos bytes apresentados, quando h. Se um byte est na faixa coberta pela tabela ASCII, sua representao ASCII mostrada, do contrrio um ponto exibido para informar que no h representao ASCII para o byte em questo. Veja que o primeiro byte, 0x7f, no possui representao ASCII, enquanto os trs bytes seguintes, 0x45, 0x4c e 0x46, possuem. Consulte uma tabela ASCII online e veja o motivo. ;)

    DICA: Para entender mais sobre o funcionamento de um dumper hexa (como tambm se chamam os visualizadores hexadecimais), estude o cdigo do hdump [3], que livre e muito simples. Ele apresenta uma sada idntica do hd, com a vantagem de ser multiplaforma e j possui verses compiladas para Windows de 32 e 64-bits. O cdigo bastante enxuto (cerca de 100 linhas) e est comentado em Portugus.

    A minha verso do binrio nada ficou com 8.468 bytes de tamanho, por isso suprimi

    a sada do hd aqui no texto. O incio do arquivo no representa o incio do cdigo do programa em si, mas sim campos inerentes especificao do formato ELF. Mesmo que visualizemos com o hd os bytes referentes ao cdigo de mquina gerado pelo processo de compilao da nossa nica linha de cdigo fonte, estes provavelmente no seriam inteligveis ao serem lidos pois seriam somente uma sequncia de nmeros hexadecimais (a no ser que o leitor esteja mapeando cada byte com as instrues IA equivalentes). Por isso o processo de disassembly necessrio. Para tal, vamos usar agora o disassembler objdump:

    $ objdump -M intel - d nada

    A opo -M intel do objdump configura o disassembler para utilizar a sintaxe Intel assim como linguagens de programao, o cdigo assembly pode ser representado de mais de uma forma. J a opo -d pede ao objdump que faa o disassembly somente das sees que contenham cdigo, o que possvel porque o objdump conhece a estrutura dos binrios ELF. Voc vai perceber que h vrias funes no colocadas pelo programador (no cdigo fonte), em nosso caso elas fazem parte da libc e de seu processo de inicializao (mais informaes podem ser obtidas nos artigos da seo Fundamentos para Computao Ofensiva). Mas vamos main:

    00000000004004ec : 4004ec: 55 push rbp 4004ed: 48 89 e5 mov rbp,rsp 4004f0: b8 09 00 00 00 mov eax,0x9 4004f5: 5d pop rbp 4004f6: c3 ret

    Um disassembler tem uma sada muito mais interessante para cdigo que um dumper hexa. Enquanto este ltimo mostra offset dos bytes, os bytes em si e a representao ASCII deles (se houver), um disassembler mostra endereo (endereo base estimado para o binrio + offset), bytes e as instrues que estes bytes representam. Tomemos a primeira instruo da funo main deste exemplo, PUSH RBP. Essa instruo codificada pelo byte 0x55 ele aparecer muito frequentemente em incio de funes.

    18

  • J a instruo MOV RBP, RSP representada pela sequncia de bytes 0x45 0x89 0xe5. E assim sucessivamente.

    Estudar engenharia reversa analisar, dentre outras coisas, cdigos assembly. Vamos ento entender linha a linha:

    push rbp // coloca o valor do registrador RBP na pilha mov rbp,rsp // copia (sim, a instruo MOV ser ve para copiar) o valor do registrador RSP para RBP mov eax,0x9 // coloca o valor l iteral 9 no registrador EAX pop rbp // retira o valor do topo da pilha e o coloca no registrador RBP ret // simboliza, nesse caso, o fim da funo, retomando a execuo para onde parou antes da chamada da funo main(). Para mais informaes a respeito, favor ler os ar tigos da coluna Fundamentos para Computao Ofensiva

    Para maiores informaes sobre a chamada de funes, favor consultar os artigos da coluna Fundamentos para Computao Ofensiva.

    No escopo desse artigo discutir os mecanismos que envolvem chamar e sair de uma funo, mas por agora o leitor deve saber que o 9 da linha return 9 o que aparece na instruo mov eax,0x9.

    No shell do Linux a varivel especial $? contm o cdigo de retorno de um programa. Para ento se certificar de que este programa est retornando 9, podemos fazer:

    $ ./nada $ echo $? 9

    Se o resultado for 9 como no exemplo, voc fez tudo certo.

    E ateno, voc j est fazendo engenharia reversa! Olhar um binrio compilado e entend-lo j pra l de interessante. No prximo artigo vamos estudar mais sobre identificao de funes, offsets, endereos e iniciar o estudo de patching, onde modificaremos o binrio depois de compilado. At l!

    [1] http://w w w.asciitable.com/[2] https://refspecs.linuxbase.org/elf/elf.pdf[3] http://github.com/merces/hdump/

    FERNANDO MERCSFernando Pesquisador de Ameas na Trend Micro. Com foco em segurana de aplicaes e sistemas, desenvolve solues de proteo contra ameaas eataques, principalmente no Brasil. Tem uma forte ligao com o mundo open source, sendo colaborador da comunidade Debian, desenvolvedor de projetoslivres na rea de segurana como pev, aleph e T50. J apresentou pesquisas em eventos como H2HC, FISL e LinuxCon e um constante estudioso da evoluo deataques cibernticos.

    19

  • FUNDAMENTOS PARA COMPUTAO OFENSIVA

    POR YGOR DA ROCHA PARREIRAStack Frames - O Que So e Para Que Servem? Parte II

    Este ar tigo est dividido em duas par tes onde a primeira par te, publicada na edio nmero 7 dessa revista, mostrou o funcionamento da stack e esta segunda par te mostra o uso dos stack frames . As duas par tes abusam de exerccios prticos como forma de comprovar os conceitos apresentados.

    0x0 Stack Frames

    Sempre que uma funo chamada, cria-se um novo stack frame1 no topo da stack. Desta forma mesmo que se faa uso de chamadas recursivas, o conjunto de variveis locais no interfere com as variveis locais2 de outra instncia da funo. A Figura 1 ilustra como seria o empilhamento dos stack frames do programa apresentado na Listagem 1, durante a execuo da funo quadrado().

    Geralmente o registrador EBP utilizado para identificar uma posio fixa dentro do stack frame da funo chamada3, e conhecido como stack frame base pointer, ou simplesmente frame pointer. Ele permite acesso fcil a parmetros passados na stack, ao return instruction pointer, bem como s variveis locais criadas pelo procedimento.

    root@research:~/H2HC_Magazine/Fundamentos/Stack_Frame# cat stack_frame.c// To Compile: gcc - o stack_frame stack_frame.cint soma(int, int);int quadrado(int);int main(){ soma(4, 3); // Primeira Chamada. return 0;}int soma(int a, int b){ int res; res = a + b; quadrado(res); // Segunda Chamada. return res;}int quadrado(int num){ int resultado; resultado = num * num; return resultado;}root@research:~/H2HC_Magazine/Fundamentos/Stack_Frame# gcc -o stack_frame stack_frame.c // Compila o programa.root@research:~/H2HC_Magazine/Fundamentos/Stack_Frame#

    Listagem 1 Fonte e processo de compilao do programa stack_frame, utilizado para demonstrar o empilhamento dos stack frames durante sua execuo

    1 - Stack frames so abstraes originadas no hardware e herdadas pela ABI/Sistema Operacional.2- Faz-se obvio aqui que estamos falando apenas de variveis locais que so armazenadas na stack. A forma com que cada tipo de varivel (dinmicas, automticas, estticas, etc) so armazenadas na memria no o escopo principal deste ar tigo, e ser tratado num ar tigo futuro.3- Se compilado com otimizao o GCC na verso util izada neste ar tigo no faz uso do EBP da forma como explicado aqui.

    20

  • Assim como uma API (Application Programming Interface) fornece padronizao de interface para o cdigo fonte, a ABI (Application Binary Interface) fornece padronizao de interface para duas ou mais partes de software em uma determinada arquitetura. Ela define como a aplicao deve interagir com ela mesma, como deve interagir com as bibliotecas compartilhadas e at mesmo com o kernel. Enquanto a API garante compatibilidade de fontes, a ABI garante compatibilidade binria.

    Apesar da IA-32 no requerer alinhamento de stack, a ABI do Linux define um alinhamento em fronteiras de words (32 bits nesta arquitetura)4. Tambm definido que os argumentos so passados na stack em ordem inversa a do prottipo da funo (ltimo argumento deve ser inserido na stack primeiro), e devem respeitar o alinhamento requerido. Isto significa que, caso necessrio, um argumento pode aumentar de tamanho para se tornar mltiplo de words. Assim como na IA-32, a ABI do Linux tambm define que todos os argumentos presentes na stack residam no stack frame do chamador.

    A Figura 2 mostra o formato de um stack frame. A Listagem 2 mostra a execuo passo a passo da funo main() do programa stack_frame, at a chamada da funo soma() e criao do novo stack frame.

    4 - O tamanho de uma word controverso em diversas arquiteturas, ou mesmo em uma mesma arquitetura como no caso deste documento, que versa sobre a IA-32 (manual da Intel define como 16 bits, e a ABI do Linux define como 32 bits). Para os fins deste contex to adotamos o tamanho de 32 bits, que o mesmo definido pela ABI do Linux para a arquitetura em questo.

    0xBFFFFFFF (Base da Stack)Argumentos de linha de comando e variveis de ambiente.

    Stack frame de main()

    Stack frame de soma()

    Stack frame de quadrado()

  • (gdb) break *0x080483dc // Criando break-point no endereo encontrado.Breakpoint 1 at 0x80483dc(gdb) rStar ting program: /root/H2HC_Magazine/Fundamentos/Stack_Frame/stack_frame

    Breakpoint 1, 0x080483dc in main ()(gdb) disassemble mainDump of assembler code for function main:=> 0x080483dc : push %ebp // Processo parado aqui (break-point) indicado pela seta no incio da l inha. 0x080483dd : mov %esp,%ebp 0x080483df : and $0xfffffff0,%esp 0x080483e2 : sub $0x10,%esp 0x080483e5 : movl $0x3,0x4(%esp) 0x080483ed : movl $0x4,(%esp) 0x080483f4 : call 0x8048400 0x080483f9 : mov $0x0,%eax 0x080483fe : leave 0x080483ff : retEnd of assembler dump.(gdb) i r $ebp $esp // Verifica o contedo de EBP e onde (topo da stack) ele ser colocado.ebp 0xbffffc68 0xbffffc68esp 0xbffffbec 0xbffffbec(gdb) x/x $esp // Verifica o endereo de retorno de main().0xbffffbec: 0xb7e8ce46 // Endereo de retorno de main(), endereo dentro do mapeamento da LibC.(gdb) x/4i __libc_start_main+227 // Verifica para onde main() retorna 5. 0xb7e8ce43 : call *0x8(%ebp) // Aqui faz sentido o endereo de main() ser o primeiro parmetro ltimo argumento a ser colocado na stack antes do call da rotina de inicializao da LibC. 0xb7e8ce46 : mov %eax,(%esp) // Retorna pra c. 0xb7e8ce49 : call 0xb7ea5550 0xb7e8ce4e : xor %ecx,%ecx(gdb) ni0x080483dd in main ()(gdb) disassemble mainDump of assembler code for function main: 0x080483dc : push %ebp // Incio do prlogo de main().=> 0x080483dd : mov %esp,%ebp // Execuo parada aqui Fim do prlogo. 0x080483df : and $0xfffffff0,%esp 0x080483e2 : sub $0x10,%esp 0x080483e5 : movl $0x3,0x4(%esp) 0x080483ed : movl $0x4,(%esp) 0x080483f4 : call 0x8048400 0x080483f9 : mov $0x0,%eax 0x080483fe : leave 0x080483ff : retEnd of assembler dump.(gdb) i r $ebp $espebp 0xbffffc68 0xbffffc68esp 0xbffffbe8 0xbffffbe8(gdb) x/x $esp0xbffffbe8: 0xbffffc68 // Contedo do topo da stack (antigo frame pointer).(gdb) ni0x080483df in main ()(gdb) disassemble main

    5 - Ver a terceira questo da sesso 0x2 Perguntas Mais Frequentes.

    22

  • Dump of assembler code for function main: 0x080483dc : push %ebp 0x080483dd : mov %esp,%ebp=> 0x080483df : and $0xfffffff0,%esp // Alinhando a stack em fronteiras de 16 bytes 6. 0x080483e2 : sub $0x10,%esp 0x080483e5 : movl $0x3,0x4(%esp) 0x080483ed : movl $0x4,(%esp) 0x080483f4 : call 0x8048400 0x080483f9 : mov $0x0,%eax 0x080483fe : leave 0x080483ff : retEnd of assembler dump.(gdb) i r $ebp $espebp 0xbffffbe8 0xbffffbe8 // Pronto, EBP j contm o frame pointer do stack frame corrente.esp 0xbffffbe8 0xbffffbe8(gdb) ni0x080483e2 in main ()(gdb) disassemble mainDump of assembler code for function main: 0x080483dc : push %ebp 0x080483dd : mov %esp,%ebp 0x080483df : and $0xfffffff0,%esp=> 0x080483e2 : sub $0x10,%esp // Aloca espao na stack. 0x080483e5 : movl $0x3,0x4(%esp) 0x080483ed : movl $0x4,(%esp) 0x080483f4 : call 0x8048400 0x080483f9 : mov $0x0,%eax 0x080483fe : leave 0x080483ff : retEnd of assembler dump.(gdb) i r $espesp 0xbffffbe0 0xbffffbe0 // Stack alinhada.(gdb) ni0x080483e5 in main ()(gdb) disassemble mainDump of assembler code for function main: 0x080483dc : push %ebp 0x080483dd : mov %esp,%ebp 0x080483df : and $0xfffffff0,%esp 0x080483e2 : sub $0x10,%esp=> 0x080483e5 : movl $0x3,0x4(%esp) // Passa o segundo parmetro da chamada soma(4, 3), em ordem inversa conforme call ing convention definida pela ABI. 0x080483ed : movl $0x4,(%esp) 0x080483f4 : call 0x8048400 0x080483f9 : mov $0x0,%eax 0x080483fe : leave 0x080483ff : retEnd of assembler dump.(gdb) i r $espesp 0xbffffbd0 0xbffffbd0 // Espao alocado na stack. (gdb) ni0x080483ed in main ()(gdb) disassemble main

    6 - O motivo disto explicado posteriormente.

    23

  • Dump of assembler code for function main: 0x080483dc : push %ebp 0x080483dd : mov %esp,%ebp 0x080483df : and $0xfffffff0,%esp 0x080483e2 : sub $0x10,%esp 0x080483e5 : movl $0x3,0x4(%esp)=> 0x080483ed : movl $0x4,(%esp) // Passa o primeiro parmetro da chamada soma(4, 3). 0x080483f4 : call 0x8048400 0x080483f9 : mov $0x0,%eax 0x080483fe : leave 0x080483ff : retEnd of assembler dump.(gdb) x/x $esp+40xbffffbd4: 0x00000003 // Segundo parmetro da chamada soma(4, 3) j em seu lugar.(gdb) ni0x080483f4 in main ()(gdb) disassemble mainDump of assembler code for function main: 0x080483dc : push %ebp 0x080483dd : mov %esp,%ebp 0x080483df : and $0xfffffff0,%esp 0x080483e2 : sub $0x10,%esp 0x080483e5 : movl $0x3,0x4(%esp) 0x080483ed : movl $0x4,(%esp)=> 0x080483f4 : call 0x8048400 // Chama a funo soma(), criando um novo stack frame. Esta instruo coloca o endereo da prxima instruo (0x080483f9) no topo da stack, e salta para o endereo referenciado (0x8048400). 0x080483f9 : mov $0x0,%eax 0x080483fe : leave 0x080483ff : retEnd of assembler dump.(gdb) x/x $esp0xbffffbd0: 0x00000004 // Primeiro parmetro da chamada soma(4, 3) j em seu lugar.(gdb) stepi // Entra na funo chamada (soma()).0x08048400 in soma ()(gdb) disassemble somaDump of assembler code for function soma:=> 0x08048400 : push %ebp // Incio do prlogo de soma(). 0x08048401 : mov %esp,%ebp 0x08048403 : sub $0x28,%esp 0x08048406 : mov 0xc(%ebp),%eax 0x08048409 : mov 0x8(%ebp),%edx 0x0804840c : add %edx,%eax 0x0804840e : mov %eax,-0xc(%ebp) 0x08048411 : mov -0xc(%ebp),%eax 0x08048414 : mov %eax,(%esp) 0x08048417 : call 0x8048421 0x0804841c : mov -0xc(%ebp),%eax 0x0804841f : leave 0x08048420 : retEnd of assembler dump.(gdb) i r $espesp 0xbffffbcc 0xbffffbcc(gdb) x/x $esp // Verificando o endereo de retorno de soma().0xbffffbcc: 0x080483f9 // Endereo de retorno de soma().(gdb)

    Listagem 2 Execuo passo a passo da funo main() do programa stack_frame, at a criao do novo stack frame

    24

  • Durante a sesso de execuo passo a passo apresentada na Listagem 2, observa-se que main() alinha a stack em fronteiras de 16 bytes, e no de 4 bytes como requerido pela ABI do Linux para esta arquitetura. Mas porque isto? Apesar da IA-32 ser descrita como uma arquitetura do tipo soft alignment, ou seja, que no exige alinhamento de memria, ela possui uma extenso do seu conjunto de instrues onde a maioria destas exigem o alinhamento em fronteiras de 16 bytes. Exemplos destas instrues podem ser encontrados em extenses SIMD (Single Instruction, Multiple Data), que na Intel recebeu nomes de SSE, SSE2, SSE3, SSSE3 e SSE47.

    O GCC utiliza a opo de compilao -mpreferred-stack-boundary=num para indicar qual o fator de alinhamento da stack, onde num o expoente de base dois deste fator. Como o padro num = 4, 24 = 16 8. At mesmo a alocao de memria subsequente desta funo (instruo no endereo 0x080483e2) continua respeitando este alinhamento.

    A instruo call cria um novo stack frame e salva no topo da stack o endereo da instruo subsequente a ela, de forma que o programa consiga prosseguir sua execuo quando a funo chamada terminar. Normalmente em todo incio de

    funo executado o que conhecido como prlogo9, que composto das seguintes instrues:

    push %ebpmov %esp, %ebp

    Estas instrues servem para salvar o frame pointer do stack frame anterior, e configurar o frame pointer para o stack frame corrente.

    A Listagem 2 tambm mostra que o endereo de retorno salvo para quando main() encerrar sua execuo aponta para cdigo dentro da rotina de inicializao da LibC (instruo __libc_start_main+230), o que corrobora a informao de que as rotinas de inicializao da LibC so executadas antes de main()10. Tambm nota-se a conformidade da passagem dos parmetros com as especificaes da ABI, ou seja, so passados para a stack em ordem inversa da especificada na funo em C11.

    A Figura 3 mostra passo a passo o que ocorre na stack e em alguns registradores da CPU, durante a execuo da funo main() do programa stack_frame. A Figura 4 mostra como ficou a organizao dos stack frames, aps a chamada da funo soma() no programa stack_frame.

    7 - Manual da Intel, Volume 1: Basic Architecture.8 - Este valor padro pode variar entre verses diferentes do gcc.9 - Isso pode variar de acordo com a call ing convention e arquiteturas adotadas. Algumas l iteraturas tambm consideram a alocao de espao para variveis locais como par te do prlogo.10 -Ver a primeira par te do ar tigo, na edio n. 7 da H2HC Magazine.11 -Ver a primeira questo da sesso 0x2 Perguntas Mais Frequentes.

    0xBFFFFFFF

    0xB7E8CE46

  • A Listagem 3 mostra a execuo passo a passo da funo soma() no programa stack_frame.

    (gdb) disassemble somaDump of assembler code for function soma:=> 0x08048400 : push %ebp // Prlogo de soma(). 0x08048401 : mov %esp,%ebp // Fim do prlogo de soma(). 0x08048403 : sub $0x28,%esp 0x08048406 : mov 0xc(%ebp),%eax 0x08048409 : mov 0x8(%ebp),%edx 0x0804840c : add %edx,%eax 0x0804840e : mov %eax,-0xc(%ebp) 0x08048411 : mov -0xc(%ebp),%eax 0x08048414 : mov %eax,(%esp) 0x08048417 : call 0x8048421 0x0804841c : mov -0xc(%ebp),%eax 0x0804841f : leave 0x08048420 : retEnd of assembler dump.(gdb) i r $esp $ebpesp 0xbffffbcc 0xbffffbccebp 0xbffffbe8 0xbffffbe8(gdb) x/x $esp // Verificando o endereo de retorno de soma().0xbffffbcc: 0x080483f9 // Endereo de retorno de soma().(gdb) ni0x08048401 in soma ()(gdb) disassemble somaDump of assembler code for function soma: 0x08048400 : push %ebp=> 0x08048401 : mov %esp,%ebp 0x08048403 : sub $0x28,%esp 0x08048406 : mov 0xc(%ebp),%eax 0x08048409 : mov 0x8(%ebp),%edx 0x0804840c : add %edx,%eax 0x0804840e : mov %eax,-0xc(%ebp) 0x08048411 : mov -0xc(%ebp),%eax 0x08048414 : mov %eax,(%esp) 0x08048417 : call 0x8048421 0x0804841c : mov -0xc(%ebp),%eax 0x0804841f : leave 0x08048420 : retEnd of assembler dump.(gdb) x/x $esp0xbffffbc8: 0xbffffbe8 // O frame pointer do stack frame anterior (relativo a funo main()) j est no topo da stack primeiro passo do prlogo.(gdb) ni0x08048403 in soma ()(gdb) disassemble somaDump of assembler code for function soma: 0x08048400 : push %ebp 0x08048401 : mov %esp,%ebp=> 0x08048403 : sub $0x28,%esp // Aloca memria para variveis locais. 0x08048406 : mov 0xc(%ebp),%eax 0x08048409 : mov 0x8(%ebp),%edx

    26

  • 0x0804840c : add %edx,%eax 0x0804840e : mov %eax,-0xc(%ebp) 0x08048411 : mov -0xc(%ebp),%eax 0x08048414 : mov %eax,(%esp) 0x08048417 : call 0x8048421 0x0804841c : mov -0xc(%ebp),%eax 0x0804841f : leave 0x08048420 : retEnd of assembler dump.(gdb) i r $ebp $espebp 0xbffffbc8 0xbffffbc8 // Frame pointer ajustado para o stack frame corrente (relativo a funo soma()) ltimo passo do prlogo.esp 0xbffffbc8 0xbffffbc8(gdb) ni0x08048406 in soma ()(gdb) disassemble somaDump of assembler code for function soma: 0x08048400 : push %ebp 0x08048401 : mov %esp,%ebp 0x08048403 : sub $0x28,%esp=> 0x08048406 : mov 0xc(%ebp),%eax // Copia o segundo argumento de soma(4, 3) para dentro do registrador EAX. 0x08048409 : mov 0x8(%ebp),%edx 0x0804840c : add %edx,%eax 0x0804840e : mov %eax,-0xc(%ebp) 0x08048411 : mov -0xc(%ebp),%eax 0x08048414 : mov %eax,(%esp) 0x08048417 : call 0x8048421 0x0804841c : mov -0xc(%ebp),%eax 0x0804841f : leave 0x08048420 : retEnd of assembler dump.(gdb) i r $espesp 0xbffffba0 0xbffffba0 // Memria alocada para variveis locais.(gdb) x/x $ebp+0xc0xbffffbd4: 0x00000003 // Segundo parmetro de soma(4, 3).(gdb) i r $eaxeax 0xbffffc94 -1073742700 // Lixo contido em EAX.(gdb) ni0x08048409 in soma ()(gdb) disassemble somaDump of assembler code for function soma: 0x08048400 : push %ebp 0x08048401 : mov %esp,%ebp 0x08048403 : sub $0x28,%esp 0x08048406 : mov 0xc(%ebp),%eax=> 0x08048409 : mov 0x8(%ebp),%edx // Copia o primeiro argumento de soma(4, 3) para dentro do registrador EDX. 0x0804840c : add %edx,%eax 0x0804840e : mov %eax,-0xc(%ebp) 0x08048411 : mov -0xc(%ebp),%eax 0x08048414 : mov %eax,(%esp) 0x08048417 : call 0x8048421 0x0804841c : mov -0xc(%ebp),%eax 0x0804841f : leave

    27

  • 0x08048420 : retEnd of assembler dump.(gdb) i r $eaxeax 0x3 3 // Segundo argumento j em EAX.(gdb) x/x $ebp+0x80xbffffbd0: 0x00000004 // Primeiro argumento de soma(4, 3).(gdb) i r $edxedx 0x1 1 // Lixo contido em EDX.(gdb) ni0x0804840c in soma ()(gdb) disassemble somaDump of assembler code for function soma: 0x08048400 : push %ebp 0x08048401 : mov %esp,%ebp 0x08048403 : sub $0x28,%esp 0x08048406 : mov 0xc(%ebp),%eax 0x08048409 : mov 0x8(%ebp),%edx=> 0x0804840c : add %edx,%eax // Faz a soma dos dois argumentos passados para a funo, e armazena o resultado em EAX. 0x0804840e : mov %eax,-0xc(%ebp) 0x08048411 : mov -0xc(%ebp),%eax 0x08048414 : mov %eax,(%esp) 0x08048417 : call 0x8048421 0x0804841c : mov -0xc(%ebp),%eax 0x0804841f : leave 0x08048420 : retEnd of assembler dump.(gdb) i r $edx $eaxedx 0x4 4 // Primeiro argumento em EDX.eax 0x3 3 // Segundo argumento em EAX.(gdb) ni0x0804840e in soma ()(gdb) disassemble somaDump of assembler code for function soma: 0x08048400 : push %ebp 0x08048401 : mov %esp,%ebp 0x08048403 : sub $0x28,%esp 0x08048406 : mov 0xc(%ebp),%eax 0x08048409 : mov 0x8(%ebp),%edx 0x0804840c : add %edx,%eax=> 0x0804840e : mov %eax,-0xc(%ebp) // Copia o resultado da soma para a varivel local res. 0x08048411 : mov -0xc(%ebp),%eax 0x08048414 : mov %eax,(%esp) 0x08048417 : call 0x8048421 0x0804841c : mov -0xc(%ebp),%eax 0x0804841f : leave 0x08048420 : retEnd of assembler dump.(gdb) i r $eaxeax 0x7 7 // Resultado da soma armazenado em EAX.(gdb) x/x $ebp-0xc0xbffffbbc: 0x0804849b // Lixo contido na posio da varivel local res, da funo soma().(gdb) ni0x08048411 in soma ()(gdb) disassemble soma

    28

  • Dump of assembler code for function soma: 0x08048400 : push %ebp 0x08048401 : mov %esp,%ebp 0x08048403 : sub $0x28,%esp 0x08048406 : mov 0xc(%ebp),%eax 0x08048409 : mov 0x8(%ebp),%edx 0x0804840c : add %edx,%eax 0x0804840e : mov %eax,-0xc(%ebp)=> 0x08048411 : mov -0xc(%ebp),%eax // Copia o contedo da varivel res para o registrador EAX. 0x08048414 : mov %eax,(%esp) 0x08048417 : call 0x8048421 0x0804841c : mov -0xc(%ebp),%eax 0x0804841f : leave 0x08048420 : retEnd of assembler dump.(gdb) x/x $ebp-0xc0xbffffbbc: 0x00000007 // Resultado da soma armazenado na varivel local res.(gdb) ni0x08048414 in soma ()(gdb) disassemble somaDump of assembler code for function soma: 0x08048400 : push %ebp 0x08048401 : mov %esp,%ebp 0x08048403 : sub $0x28,%esp 0x08048406 : mov 0xc(%ebp),%eax 0x08048409 : mov 0x8(%ebp),%edx 0x0804840c : add %edx,%eax 0x0804840e : mov %eax,-0xc(%ebp) 0x08048411 : mov -0xc(%ebp),%eax=> 0x08048414 : mov %eax,(%esp) // Passa o resultado da soma como argumento para a funo quadrado(). 0x08048417 : call 0x8048421 0x0804841c : mov -0xc(%ebp),%eax 0x0804841f : leave 0x08048420 : retEnd of assembler dump.(gdb) i r $eaxeax 0x7 7 // Contedo da varivel local res, armazenado em EAX.(gdb) x/x $esp0xbffffba0: 0x00000000 // Vendo o l ixo que se encontra no topo da stack.(gdb) ni0x08048417 in soma ()(gdb) disassemble somaDump of assembler code for function soma: 0x08048400 : push %ebp 0x08048401 : mov %esp,%ebp 0x08048403 : sub $0x28,%esp 0x08048406 : mov 0xc(%ebp),%eax 0x08048409 : mov 0x8(%ebp),%edx 0x0804840c : add %edx,%eax 0x0804840e : mov %eax,-0xc(%ebp) 0x08048411 : mov -0xc(%ebp),%eax 0x08048414 : mov %eax,(%esp)=> 0x08048417 : call 0x8048421 // Chama a funo quadrado(), criando um novo stack frame. Esta instruo coloca o endereo da prxima instruo (0x0804841c) no topo da stack, e salta para o endereo referenciado (0x8048421).

    29

  • 0x0804841c : mov -0xc(%ebp),%eax 0x0804841f : leave 0x08048420 : retEnd of assembler dump.(gdb) x/x $esp0xbffffba0: 0x00000007 // Argumento para a funo quadrado() passado.(gdb) i r $espesp 0xbffffba0 0xbffffba0 // Visualizando para onde o stack pointer est apontando (qual o endereo do topo da stack).(gdb) stepi0x08048421 in quadrado ()(gdb) disassemble quadradoDump of assembler code for function quadrado:=> 0x08048421 : push %ebp 0x08048422 : mov %esp,%ebp0x08048424 : sub $0x10,%esp 0x08048427 : mov 0x8(%ebp),%eax 0x0804842a : imul 0x8(%ebp),%eax 0x0804842e : mov %eax,-0x4(%ebp) 0x08048431 : mov -0x4(%ebp),%eax 0x08048434 : leave 0x08048435 : retEnd of assembler dump.(gdb) x/x $esp0xbffffb9c: 0x0804841c // Stack pointer decrementado, e endereo de retorno da funo quadrado() armazenado no novo stack frame.(gdb)

    Listagem 3 Execuo passo a passo da funo soma() do programa stack_frame, at a criao do novo stack frame

    A execuo passo a passo da funo soma() mostra que os parmetros so copiados para os registradores de uso geral EAX e EDX, somados, e depois o resultado armazenado na posio de memria alocada para a varivel local res. A passagem do parmetro para a funo quadrado() ocorre com duas instrues: Primeiro copia-se o contedo da varivel res para o registrador EAX, e em seguida copia-se o contedo de EAX para o topo da stack. Mas porque no copiar direto entre as posies de memria? Porque a IA-32 no permite cpia direta

    de uma posio de memria para outra. Finalizado as operaes da funo soma() e a passagem do argumento, a instruo call cria um novo stack frame e salva no topo da stack o endereo da instruo subsequente.

    A Figura 5 mostra passo a passo o que ocorre na stack e em alguns registradores da CPU durante a execuo da funo soma() no programa stack_frame. A Figura 6 mostra como ficou a organizao dos stack frames, aps a chamada da funo quadrado() no programa stack_frame.

  • A Listagem 4 mostra a execuo passo a passo da funo quadrado().

    0xBFFFFFFF

    0x080483F9

  • => 0x08048422 : mov %esp,%ebp 0x08048424 : sub $0x10,%esp 0x08048427 : mov 0x8(%ebp),%eax 0x0804842a : imul 0x8(%ebp),%eax 0x0804842e : mov %eax,-0x4(%ebp) 0x08048431 : mov -0x4(%ebp),%eax 0x08048434 : leave 0x08048435 : retEnd of assembler dump.(gdb) x/x $esp0xbffffb98: 0xbffffbc8 // Frame pointer do stack frame anterior, salvo no topo da stack no stack frame corrente.(gdb) ni0x08048424 in quadrado ()(gdb) disassemble quadradoDump of assembler code for function quadrado: 0x08048421 : push %ebp 0x08048422 : mov %esp,%ebp=> 0x08048424 : sub $0x10,%esp 0x08048427 : mov 0x8(%ebp),%eax 0x0804842a : imul 0x8(%ebp),%eax 0x0804842e : mov %eax,-0x4(%ebp) 0x08048431 : mov -0x4(%ebp),%eax 0x08048434 : leave 0x08048435 : retEnd of assembler dump.(gdb) i r $esp $ebpesp 0xbffffb98 0xbffffb98ebp 0xbffffb98 0xbffffb98 // Frame pointer ajustado para o stack frame corrente.(gdb) ni0x08048427 in quadrado ()(gdb) disassemble quadradoDump of assembler code for function quadrado: 0x08048421 : push %ebp 0x08048422 : mov %esp,%ebp 0x08048424 : sub $0x10,%esp=> 0x08048427 : mov 0x8(%ebp),%eax // Copia o argumento passado para o registrador EAX. 0x0804842a : imul 0x8(%ebp),%eax 0x0804842e : mov %eax,-0x4(%ebp) 0x08048431 : mov -0x4(%ebp),%eax 0x08048434 : leave 0x08048435 : retEnd of assembler dump.(gdb) i r $esp $eaxesp 0xbffffb88 0xbffffb88 // Espao para variveis locais alocado com sucesso.eax 0x7 7 // Lixo contido em EAX.(gdb) x/x $ebp+80xbffffba0: 0x00000007 // Argumento passado no stack frame anterior.(gdb) ni0x0804842a in quadrado ()(gdb) disassemble quadradoDump of assembler code for function quadrado: 0x08048421 : push %ebp 0x08048422 : mov %esp,%ebp 0x08048424 : sub $0x10,%esp 0x08048427 : mov 0x8(%ebp),%eax

    32

  • => 0x0804842a : imul 0x8(%ebp),%eax // Multiplica o argumento do tipo inteiro passado no stack frame anterior com sua cpia contida em EAX, e armazena o resultado em EAX. 0x0804842e : mov %eax,-0x4(%ebp) 0x08048431 : mov -0x4(%ebp),%eax 0x08048434 : leave 0x08048435 : retEnd of assembler dump.(gdb) i r $eaxeax 0x7 7 // Argumento armazenado em EAX.(gdb) ni0x0804842e in quadrado ()(gdb) disassemble quadradoDump of assembler code for function quadrado: 0x08048421 : push %ebp 0x08048422 : mov %esp,%ebp 0x08048424 : sub $0x10,%esp 0x08048427 : mov 0x8(%ebp),%eax 0x0804842a : imul 0x8(%ebp),%eax=> 0x0804842e : mov %eax,-0x4(%ebp) // Armazena o resultado da multiplicao contido em EAX no espao reser vado para a varivel local resultado. 0x08048431 : mov -0x4(%ebp),%eax 0x08048434 : leave 0x08048435 : retEnd of assembler dump.(gdb) i r $eaxeax 0x31 49 // Resultado da multiplicao de inteiros.(gdb) x/x $ebp-0x40xbffffb94: 0xb7ea55f5 // Lixo contido no espao reser vado para a varivel local resultado.(gdb) ni0x08048431 in quadrado ()(gdb) disassemble quadradoDump of assembler code for function quadrado: 0x08048421 : push %ebp 0x08048422 : mov %esp,%ebp 0x08048424 : sub $0x10,%esp 0x08048427 : mov 0x8(%ebp),%eax 0x0804842a : imul 0x8(%ebp),%eax 0x0804842e : mov %eax,-0x4(%ebp)=> 0x08048431 : mov -0x4(%ebp),%eax // Coloca o resultado da multiplicao em EAX. A ABI define que os retornos de funes devem estar contidos no registrador EAX. 0x08048434 : leave 0x08048435 : retEnd of assembler dump.(gdb) x/x $ebp-0x40xbffffb94: 0x00000031 // Resultado armazenado no espao reser vado para a varivel local resultado.(gdb) ni0x08048434 in quadrado ()(gdb) disassemble quadradoDump of assembler code for function quadrado: 0x08048421 : push %ebp 0x08048422 : mov %esp,%ebp 0x08048424 : sub $0x10,%esp 0x08048427 : mov 0x8(%ebp),%eax 0x0804842a : imul 0x8(%ebp),%eax 0x0804842e : mov %eax,-0x4(%ebp)

    33

  • 0x08048431 : mov -0x4(%ebp),%eax=> 0x08048434 : leave 0x08048435 : retEnd of assembler dump.(gdb) i r $eaxeax 0x31 49 // Valor retornado pela funo quadrado() colocado em seu devido lugar (registrador EAX ) antes do eplogo.(gdb)

    Listagem 4 Execuo passo a passo da funo quadrado() no programa stack_frame, at antes da execuo do eplogo

    interessante notar que durante a execuo das funes o frame pointer sempre aponta para um ponto fixo dentro do stack frame corrente, onde tanto os parmetros passados como as variveis locais so referenciadas dando seu deslocamento em relao ao EBP. Ou seja, quase sempre EBP + Deslocamento referencia argumentos e EBP - Deslocamento referencia variveis locais. Adicionalmente, a ABI define que valores de

    retorno de funes devem estar contidos no registrador EAX.

    A Figura 7 mostra passo a passo o que ocorre na stack e em alguns registradores da CPU, durante a execuo da funo quadrado() no programa stack_frame. A Figura 8 mostra como ficou a organizao dos stack frames, at antes das instrues de eplogo da funo quadrado().

    0xBFFFFFFF

    0x0804841C

  • A sequncia final das duas instrues nas funes apresentadas conhecida como eplogo e serve para desalocar o stack frame corrente, recuperar o frame pointer do stack frame do chamador e continuar a execuo de suas instrues no ponto subsequente que ocorreu a chamada da funo/procedimento recm terminado.

    A Listagem 5 mostra a execuo passo a passo do eplogo da funo quadrado().

    (gdb) disassemble quadradoDump of assembler code for function quadrado: 0x08048421 : push %ebp 0x08048422 : mov %esp,%ebp 0x08048424 : sub $0x10,%esp 0x08048427 : mov 0x8(%ebp),%eax 0x0804842a : imul 0x8(%ebp),%eax 0x0804842e : mov %eax,-0x4(%ebp) 0x08048431 : mov -0x4(%ebp),%eax=> 0x08048434 : leave // Primeiro passo do eplogo desaloca memria e recupera o frame pointer do stack frame anterior. 0x08048435 : retEnd of assembler dump. (gdb) i r $esp $ebpesp 0xbffffb88 0xbffffb88ebp 0xbffffb98 0xbffffb98(gdb) ni0x08048435 in quadrado ()(gdb) disassemble quadradoDump of assembler code for function quadrado: 0x08048421 : push %ebp 0x08048422 : mov %esp,%ebp 0x08048424 : sub $0x10,%esp 0x08048427 : mov 0x8(%ebp),%eax 0x0804842a : imul 0x8(%ebp),%eax 0x0804842e : mov %eax,-0x4(%ebp) 0x08048431 : mov -0x4(%ebp),%eax 0x08048434 : leave=> 0x08048435 : ret // Pega o valor que est no topo da stack (endereo de retorno), coloca em EIP e continua a execuo.End of assembler dump.(gdb) i r $esp $ebpesp 0xbffffb9c 0xbffffb9c // ESP anterior menos 4 (do pop %ebp) .ebp 0xbffffbc8 0xbffffbc8 // Frame pointer do stack frame anterior (funo soma()).(gdb) x/x $esp0xbffffb9c: 0x0804841c // Endereo para onde retornar. A instruo ret retira este endereo do topo da stack, coloca no registrador EIP e desta forma a execuo do programa continua.(gdb) i r $eipeip 0x8048435 0x8048435 // EIP aponta para a prxima instruo a ser executada, que no caso a instruo ret da funo quadrado().(gdb) ni0x0804841c in soma ()(gdb) disassemble somaDump of assembler code for function soma: 0x08048400 : push %ebp 0x08048401 : mov %esp,%ebp 0x08048403 : sub $0x28,%esp

    35

  • 0x08048406 : mov 0xc(%ebp),%eax 0x08048409 : mov 0x8(%ebp),%edx 0x0804840c : add %edx,%eax 0x0804840e : mov %eax,-0xc(%ebp) 0x08048411 : mov -0xc(%ebp),%eax 0x08048414 : mov %eax,(%esp) 0x08048417 : call 0x8048421 => 0x0804841c : mov -0xc(%ebp),%eax // Copia resultado da soma (contedo da varivel res) em EAX, que como a funo retorna valor ao chamador. 0x0804841f : leave 0x08048420 : retEnd of assembler dump.(gdb) i r $esp $eipesp 0xbffffba0 0xbffffba0 // ESP decrementado de 4 depois que o contedo do seu topo foi colocado no EIP.eip 0x804841c 0x804841c // EIP aponta para a instruo dentro da funo soma(), que a subsequente a da chamada para quadrado(). Logo o fluxo normal de execuo do programa retomado.(gdb)

    Listagem 5 Execuo passo a passo do eplogo da funo quadrado() do programa stack_frame

    NA IA-32, o registrador EIP que faz o papel do contador de programa (program counter)12, ou seja, ele aponta para a prxima instruo a ser executada. O endereo que a instruo call empilha na stack o contedo de EIP, onde este endereo salvo utilizado posteriormente no eplogo da funo de forma a garantir que a execuo do programa continue aps o termino da funo. O eplogo possui duas instrues, que so:

    leaveret

    A instruo leave copia o contedo de EBP para o ESP, fazendo com que o topo da stack aponte para o frame pointer salvo do stack frame anterior. Em seguida ela desempilha o frame pointer salvo e o armazena em EBP, ou seja, atualiza o frame pointer atual para apontar para o stack frame anterior. A Tabela 1 mostra uma decomposio do que a instruo leave executa.

    A instruo ret desempilha o contedo do topo da pilha, neste caso o endereo de retorno salvo quando ocorreu execuo da instruo call, colocando seu valor no registrador EIP, e em seguida a execuo do programa continua. Cabe notar que se um usurio conseguir controlar o contedo do endereo de retorno em qualquer stack frame, quando for executado o retorno desta funo ele controlar o fluxo de execuo do programa e poder executar cdigos arbitrrios dentro do contexto da aplicao explorada. Geralmente este um dos objetivos das exploraes de corrupo de memria.

    O registrador EIP no pode ser referenciado diretamente, logo no possvel mostrar uma decomposio da instruo ret com instrues reais vlidas. Mas como forma de facilitar o entendimento desta instruo, a Tabela 1 usa abstraes de lgica para mostrar o que ela executa.

    12- Program Counter um termo genrico util izado na l iteratura de teoria de arquitetura de computadores para referenciar o registrador responsvel por apontar para o endereo da prxima instruo a ser executada, que na arquitetura aqui descrita (IA-32) trata-se do registrador EIP.

    36

  • Tabela 1 Equivalncia de Instrues

    A Figura 9 mostra como ficou o empilhamento dos stack frames aps o retorno da funo quadrado().

    A Listagem 6 mostra a execuo passo a passo do eplogo das funes soma() e main().

    0xBFFFFFFF (Base da Stack)Argumentos de linha de comando e variveis de ambiente.

    0xB7E8CE46

    Segm

    ento

    da Stack

    Frames das funes de inicializao da LibC

    0xBFFFFC68(ret addr de main())(FP do SF anterior)

    .

    .0x000000030x000000040x080483f9

    Stack Frame de main()

    Stack Frame de soma()

    (soma(4, 3);)(soma(4, 3);)

    0xBFFFFBE8

  • 0x08048406 : mov 0xc(%ebp),%eax 0x08048409 : mov 0x8(%ebp),%edx 0x0804840c : add %edx,%eax 0x0804840e : mov %eax,-0xc(%ebp) 0x08048411 : mov -0xc(%ebp),%eax 0x08048414 : mov %eax,(%esp) 0x08048417 : call 0x8048421 0x0804841c : mov -0xc(%ebp),%eax=> 0x0804841f : leave // Inicio do eplogo. 0x08048420 : retEnd of assembler dump.(gdb) i r $eaxeax 0x7 7 // Retornando o resultado da soma.(gdb) i r $esp $ebpesp 0xbffffba0 0xbffffba0ebp 0xbffffbc8 0xbffffbc8(gdb) ni0x08048420 in soma ()(gdb) disassemble somaDump of assembler code for function soma: 0x08048400 : push %ebp 0x08048401 : mov %esp,%ebp 0x08048403 : sub $0x28,%esp 0x08048406 : mov 0xc(%ebp),%eax 0x08048409 : mov 0x8(%ebp),%edx 0x0804840c : add %edx,%eax 0x0804840e : mov %eax,-0xc(%ebp) 0x08048411 : mov -0xc(%ebp),%eax 0x08048414 : mov %eax,(%esp) 0x08048417 : call 0x8048421 0x0804841c : mov -0xc(%ebp),%eax 0x0804841f : leave=> 0x08048420 : ret // Pega o valor que est no topo da stack, coloca em EIP e a execuo continua.End of assembler dump.(gdb) i r $esp $ebpesp 0xbffffbcc 0xbffffbcc // ESP anterior menos 4 (do pop %ebp).ebp 0xbffffbe8 0xbffffbe8 // Frame pointer do stack frame anterior (funo main()).(gdb) x/x $esp0xbffffbcc: 0x080483f9 // Endereo para onde retornar. A instruo ret retira este endereo do topo da stack, coloca no registrador EIP e a execuo continua.(gdb) ni0x080483f9 in main ()(gdb) disassemble mainDump of assembler code for function main: 0x080483dc : push %ebp 0x080483dd : mov %esp,%ebp 0x080483df : and $0xfffffff0,%esp 0x080483e2 : sub $0x10,%esp 0x080483e5 : movl $0x3,0x4(%esp) 0x080483ed : movl $0x4,(%esp) 0x080483f4 : call 0x8048400 => 0x080483f9 : mov $0x0,%eax // Valor retornado por main(). 0x080483fe : leave 0x080483ff : ret

    38

  • End of assembler dump.(gdb) i r $esp $eip $eaxesp 0xbffffbd0 0xbffffbd0 // ESP decrementado de 4 depois que o contedo do seu topo foi colocado no EIP.eip 0x80483f9 0x80483f9 // EIP apontando para instruo dentro da funo main(), seguinte a chamada para soma(), retomando o fluxo normal de execuo do programa.eax 0x7 7 // Valor retornado pela funo soma().(gdb) ni0x080483fe in main ()(gdb) disassemble mainDump of assembler code for function main: 0x080483dc : push %ebp 0x080483dd : mov %esp,%ebp 0x080483df : and $0xfffffff0,%esp 0x080483e2 : sub $0x10,%esp 0x080483e5 : movl $0x3,0x4(%esp) 0x080483ed : movl $0x4,(%esp) 0x080483f4 : call 0x8048400 0x080483f9 : mov $0x0,%eax=> 0x080483fe : leave // Incio do eplogo de main(). 0x080483ff : retEnd of assembler dump.(gdb) i r $eaxeax 0x0 0 // Valor retornado por main().(gdb) i r $esp $ebpesp 0xbffffbd0 0xbffffbd0ebp 0xbffffbe8 0xbffffbe8(gdb) ni0x080483ff in main ()(gdb) disassemble mainDump of assembler code for function main: 0x080483dc : push %ebp 0x080483dd : mov %esp,%ebp 0x080483df : and $0xfffffff0,%esp 0x080483e2 : sub $0x10,%esp 0x080483e5 : movl $0x3,0x4(%esp) 0x080483ed : movl $0x4,(%esp) 0x080483f4 : call 0x8048400 0x080483f9 : mov $0x0,%eax 0x080483fe : leave=> 0x080483ff : retEnd of assembler dump.(gdb) i r $esp $ebpesp 0xbffffbec 0xbffffbec // ESP anterior menos 4 (do pop %ebp).ebp 0xbffffc68 0xbffffc68 // Frame pointer do stack frame anterior (procedimento de inicializao da LibC ).(gdb) x/x $esp0xbffffbec: 0xb7e8be46 // Endereo para onde retornar. A instruo ret retira este endereo do topo da stack, coloca no registrador EIP e a execuo continua.(gdb) ni0xb7e8be46 in __libc_start_main () from /lib/i386-linux-gnu/i686/cmov/libc.so.6 // Neste ponto o programa que escrevemos j terminou sua execuo, e agora passou a bola para o procedimento de inicializao da LibC, onde a funo main() foi chamada.(gdb) i r $eipeip 0xb7e8be46 0xb7e8be46 // Confirmado que o fluxo de execuo est realmente na funo de inicializao da LibC.(gdb)

    Listagem 6 Execuo passo a passo dos eplogos das funes soma() e main() no programa stack_frame

    39

  • Aps a execuo do eplogo de main, o fluxo de execuo passado para a rotina de inicializao da LibC, que executa mais algumas verificaes e encerra o programa. O que esta rotina de inicializao executa assunto para um prximo artigo. :)

    0x1 Concluso

    Este artigo, composto por duas partes, mostrou um pouco da complexidade que envolve a execuo de um programa, e a troca de contexto entre os procedimentos/funes que o compe. O conhecimento aqui apresentado til em diversas reas da computao, como anlise de malware, anlise de crash, escrita de cracks, explorao de vulnerabilidades de corrupo de memria e outras. Por ser apenas um conhecimento pontual dentro dos diversos necessrios para se explorar um software, ele tambm mostra o quo complexo esta rea de quebra de sistemas.

    O segredo para se explorar software conhecer como as coisas realmente funcionam, pois no tem como voc encontrar erros em um sistema se voc nem sabe como ele deveria funcionar, e o entendimento de como manipulado os stack frames essencial para quem quer seguir no ramo de computao ofensiva.

    Os autores e a revista se preocupam com a corretude das informaes aqui apresentadas. Se voc encontrou algum erro ou gostaria de agregar alguma informao s apresentadas aqui, por favor, deixe-nos saber. Sugestes de melhoria ou de assuntos a abordar so muito bem vindas.

    0x2 Perguntas Mais Frequentes

    Questo 1: Vocs disseram que a ABI define que os argumentos deve