Verificando ciertos temas recientes en los que he participado en gran parte
Reto para los Hackersduda al seguir texto "Smashing The Stack For Fun And Profit"No puedo sobrescribir EIP (Linux)He decidido hacer un manual del uso del gdb para el reconocimiento de vulnerabilidades, y el mejor conocimiento de lo que hace nuestro hardware.
Aclarando no soy un experto en la materia, sin embargo tengo experiencia con estas cosas y la verdad que me gusta ayudar.
Bueno lo principal hay que hacer antes que nada es conseguir la documentacion oficial
http://sourceware.org/gdb/documentation/Cabe mencionar tambien la existencia de verciones modificadas de GDB, las cuales puenden hacer que este trabajo se vea mas facil o bonito cabe mencionar algunos de los mas populares:
- cgdb gdb en terminal, pero con colores usando ncurses
- xxgdb gdb en modo Grafico sencillo y carismatico
Alguna duda de como Instalarlos me avisan y lo pongo en otro post
El siguente texto es esencial muchos manuales se basan en el, y el analisis de las Vulnerabilidades son casi exactamente lo mismo que otros textos de
Lectura Obligada, que hay por la red asi que leer el siguiete texto
Smashing The Stack For Fun And ProfitLo siguente esta realizado sobre una Maquina con FreeBSD, con arquitectura x86 clasica, y es muy parecido a los resultados que nos mostraria cualquier distro de linux, o cualquier sistema "like UNIX".
Todo lo aqui mostrado varia dependiendo del Sistema, Version del (kernel/gcc/gdb) que usemos.
Primeramente para los que no saben mucho del tema recomiendo buscar informacion sobre el mismo, no es un post de ensamblador ni mucho menos. solo es como usar el gdb (para/y) (analizar/el analisis) ( /de) programas vulnerables.
ImportanteHay que mencionar que la mayoria de los códigos aqui mostrados se compilan para que incluyan informacion de depuracion
gcc -o binario código.c -g
o con lo mismo pero con las funciones llamadas compiladas estaticamente
gcc -o binario código.c -g -static
Bien primeramente veremos como reconocer que es normal y que no es normal.
xgdb_001.c
int main() {
return 0;
}ejecutamos gdb con el archivo binario como parametro
%gdb ./xgdb_001
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)
Despues de esto ejutamos un disassemble, o mas abreviado un disas, sinceramente no tengo la mas remota idea de porque en mi FreeBSD hace un chingo de madres despues del prologo, procedure prolog
(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 $0x8,%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>: mov $0x0,%eax
0x080481d5 <main+33>: leave
0x080481d6 <main+34>: ret
End of assembler dump.
(gdb)
para mi hubiese bastado con lo siguente, sin embargo que mas le hacemos!
push %ebp
mov %esp,%ebp
mov $0x0,%eax
leave
ret
Bien lo que nos hubiese dado el disas main, es lo normal que nos debe de aparecer, en nuestro sistema.
Analizare aqui, algunos códigos de Smashing The Stack For Fun And Profit, y otros mas sencillos y complejos para verificar lo aprendido.
Primeramente en el sistema donde estemos debemos de identificar las zonas de memoria en las que vamos a trabajar.
Code
Data
Stack
Heap
ya en ejecucion hay poca diferencia entre la 4, solo es neceario identificar 2 tipos de regiones, y tratar de subdividirlas mentalmente o por lo menos tenerlas presentes..
xgdb_001.c
char *cadena="Variable Global, definida";
int main() {
int a;
return 0;
}
%gdb xgdb_002
GNU gdb 6.1.1 [FreeBSD]
.....
(gdb) list
1
2 char *cadena="Variable Global, definida";
3
4 int main() {
5 int a;
6 return 0;
7 }
(gdb) break 5
Breakpoint 1 at 0x80481d0: file xgdb_002.c, line 5.
(gdb) run
Starting program: /usr/home/luis/gdb/xgdb_002
Breakpoint 1, main () at xgdb_002.c:6
6 return 0;
(gdb) printf "0x%x\n", &a
0xbfbfe924
(gdb) printf "0x%x\n", cadena
0x805b40a
(gdb) printf "%s\n", cadena
Variable Global, definida
(gdb) printf "0x%x\n", main
0x80481b4
Bien, en nuestro sistema, como en el de la mayoria de ustedes, la region del stack esta claramene en el rango de memorias que nos dio, generalmente < 0xbfffffff por ejemplo 0xbfbfe924, Estas direccions son las direcciones que nos ofrece el sistema operativo, mas no son direcciones fisicas...
El code, data, y el heap generalemen > 0x8000000, por ejemplo 0x80481b4 etc en mi caso.
He estado en equipos con muchas medidas de seguridad instaladas como la ejecucucion desde la pila desabilidada, y librerias como libsafe entre otras, esto es bueno, sin embargo si tu las tienes instaladas es posible que no te aparescan los mismos resultados que ami.
Bien ya conocidas los tipos de direcciones que tenemos disponibles podemos analizar ya nuestros códigos.
pintar.c
#include<stdio.h>
int main(int argc,char **argv) {
if(argc<2) {
printf("Se esperaban Parametros!!\nUso:\n\t%s <algo>\n",argv[0]);
exit(0);
}
else {
char cadena[1024];
strcpy(cadena,argv[1]);
printf("Usted paso como parametro lo siguiente:\n\n%s\n",cadena);
}
return 0;
}
El clasico BOF, el cual use para poner un reto hace unos dias descrito en el post
Reto para los HackersMuchas veces con solo ver un código sencillo en este caso es sufuciente para ver si es o no vulnerable. Sin embargo para los usuarios que usaron el gdb sin exito o con el, lo analizare aqui para mostrar que es lo que se busca exactamente.
%gdb pintar
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) list
1 #include<stdio.h>
2
3 int main(int argc,char **argv) {
4 if(argc<2) {
5 printf("Se esperaban Parametros!!\nUso:\n\t%s <algo>\n",argv[0]);
6 exit(0);
7 }
8 else {
9 char cadena[1024];
10 strcpy(cadena,argv[1]);
11 printf("Usted paso como parametro lo siguiente:\n\n%s\n",cadena);
12 }
13 return 0;
14 }
15
Bien en primera instancia, con list, se puede obtener el código fuente.
(gdb) break 10
Breakpoint 1 at 0x80481f8: file pintar.c, line 10.
con break 10, de decimos al programa que ponga un breakpoint. en determiada linea del código.
(gdb) run `perl -e '{ print "A"x1024}'`
Starting program: /usr/home/buffer/bin/pintar `perl -e '{ print "A"x1024}'`
Breakpoint 1, main (argc=2, argv=0xbfbfe768) at pintar.c:10
10 strcpy(cadena,argv[1]);
El programa lo ejecutamos con un parametro de 1024 bytes, justo el espacioque tiene el buffer.
(gdb) bt
#0 main (argc=2, argv=0xbfbfe568) at pintar.c:10
Si verificamos la que hay de interesante en la pila con bt y vemos que solo estan las direcciones del parametro que pasamos, y cerca de ahi esta el sp, y el ret, el cual nos interesa sobrescribir.
(gdb) next
11 printf("Usted paso como parametro lo siguiente:\n\n%s\n",cadena);
Depues de ejecutar next nos informa que esta por ejecutar el printf, lo que nos indica que ya se ejecuto el strcpy, vemos nuevamente la pila, y todo sigue bien, ya que el buffer que le metimos no sobrescrio nada.
(gdb) bt
#0 main (argc=2, argv=0xbfbfe768) at pintar.c:11
(gdb) next
Usted paso como parametro lo siguiente:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
13 return 0;
(gdb) next
14 }
(gdb) next
0x080480fe in _start ()
(gdb) next
Single stepping until exit from function _start,
which has no line number information.
Program exited normally.
Bien vemos que esto esta bien, y no salio error.
(gdb) run `perl -e '{ print "A"x1600}'`
Starting program: /usr/home/buffer/bin/pintar `perl -e '{ print "A"x1600}'`
Breakpoint 1, main (argc=2, argv=0xbfbfe328) at pintar.c:10
10 strcpy(cadena,argv[1]);
Ahora vemos que nuestro breakpoint sigue activo, y ademas que le hemos paso 1600 bytes como parametro.
(gdb) next
11 printf("Usted paso como parametro lo siguiente:\n\n%s\n",cadena);
(gdb) bt
#0 main (argc=1094795585, argv=0x41414141) at pintar.c:11
(gdb) printf "0x%x\n"
Wrong number of arguments for specified format-string
(gdb) printf "0x%x\n", argv
0x41414141
(gdb) printf "0x%x\n", argc
0x41414141
(gdb) printf "0x%x\n", &argc
0xbfbfe2e0
(gdb) x 0xbfbfe2e4
0xbfbfe2e4: 0x41414141
(gdb) x 0xbfbfe2e0
0xbfbfe2e0: 0x41414141
(gdb) x 0xbfbfe2dc
0xbfbfe2dc: 0x41414141
(gdb) x 0xbfbfe2d8
0xbfbfe2d8: 0x41414141
(gdb) x 0xbfbfe2d4
0xbfbfe2d4: 0x41414141
(gdb) printf "0x%x\n", cadena
0xbfbfded0
(gdb) printf "0x%x\n", cadena + 4
0xbfbfded4
(gdb) printf "0x%x\n", cadena + 8
0xbfbfded8
(gdb) printf "0x%x\n", cadena + 16
0xbfbfdee0
(gdb) printf "0x%x\n", cadena + 1024
0xbfbfe2d0
(gdb) x 0xbfbfe2d0
0xbfbfe2d0: 0x41414141
(gdb) printf "0x%x\n", cadena + 1600
0xbfbfe510
(gdb) printf "0x%x\n", cadena + 1592
0xbfbfe508
(gdb) x 0xbfbfe508
0xbfbfe508: 0x41414141
(gdb) x 0xbfbfe50c
0xbfbfe50c: 0x41414141
Vemos que sobreescribimos un monton de datos... xD
(gdb) x 0xbfbfe510
0xbfbfe510: 0x41414100
Sin embargo si solo mandamos 1600 bytes por que en la posicion 0xbfbfe510, todavia encontramos nuestras letras A, bueno eso sera otro tema.
(gdb) next
Usted paso como parametro lo siguiente:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
13 return 0;
(gdb)
14 }
(gdb)
Warning:
Cannot insert breakpoint 0.
Error accessing memory address 0x41414141: Bad address.
(gdb)
Cannot find bounds of current function
Lo interante es que hemos sobre escrito el retorno con mucho exito. y el programa trato de saltar a la dieccion de memoria 0x41414141, el cual nos informa que es una direccion incorrecta.
tendriamos que insertar la direccion del código que queramos ejecutar.
Pues como vemos sobre escribimos el ret de main y un muchos datos mas, bueno por hoy le dejo.