13 enero, 2017

De 0 a exploiting (III)

Buenas amigos, soy Fare9. Vengo con la tercera entrega de "De 0 a exploiting" donde, paso a paso, vamos a ir viendo como funciona esto de los temas de explotación de vulnerabilidades.

Como siempre los preparativos de este tema (de momento):

###############################################

Desactivar la aleatoriedad en las direcciones de la pila, para ello debeis ejecutar el comando (como root):
echo 0 > /proc/sys/kernel/randomize_va_space

Compilar (hoy si) con:
gcc -g -fno-stack-protector -z execstack codigo.c -o programa

###############################################

Hoy voy a realizar una introducción a las shellcodes, explicando: qué son, de qué se componen, de que manera podemos crear una nuestra...

Lo primero que vamos a necesitar son unos pocos conocimientos en nuestro lenguaje favorito ENSAMBLADOR (Aquí unos apuntes que pueden venir bien de ensamblador de 8086 ensamblador).
Podemos tener dos tipos de sintaxis:

  • Intel: clasicota de windows, es muy usada en muchos debuggers, es la que encontrareis en los apuntes de arriba.
  • AT&T: usada por el compilador GAS usado en Linux para ensamblador, es el que GDB muestra por defecto.
Dejaré aquí unas cuantas claves mostradas en el libro que estoy siguiendo:

  • Valores constantes:
    • Intel: 0x8c,80,0xFF. Escribimos los valores de forma directa.
    • AT&T: $0x8c,$80,$0xFF. Como vemos la diferencia es que estos valores constantes van con el símbolo DOLAR '$'.
  • Registros:
    • Intel: eax, ebx, ecx... Los escribimos directamente.
    • AT&T: %eax,%ebx,%ecx...Se escriben con el caracter %  
  • Terminaciones de varias instrucciones:
    • En Intel, tenemos que las instrucciones las escribimos como mov, push para uso de registros (se pueden añadir WORD, DWORD para modificar el valor)
    • En AT&T, tenemos que dependiendo del valor añadimos 'b' (byte), 'w'(word) o 'l'(long) a la instrucción.
  • Valor destino y origen:
    • En Intel, el primer valor es el destino y el segundo es el origen. Ejemplo: mov eax,ebx (eax es el destino del valor ebx).
    • En AT&T, es al revés, movl %eax,%ebx  En este caso movemos el valor de eax a ebx.
Como esto no es una clase de estructura de computadores, dejo aquí una imagen con los registros que usaremos y una pequeña descripción:

La primera pregunta:

¿Qué es un shellcode?
Es una gran pregunta, ya que bueno, una shellcode es eso que msfvenom nos devuelve en un formato que nosotros le digamos... Pero la pregunta importante es esos numeritos que aparecen que son y por qué son así.

"Nada más que cadenas de códigos en hexadecimal, extraidos de funciones de ensamblador. Se introducen en ciertas zonas de la memoria para finalmente intentar saltar a estas y ejecutarlos."

Para empezar es una gran explicación, ya que un procesador es una unidad hardware que "procesa", según se va encontrando cadenas de unos y ceros, va ejecutando así a choclon. No distingue si son datos o código o cálculos complejos en módulo 2 .Más o menos este gif explica como funciona un procesador tradicional ejecutando códigos uno tras otro:

Bueno, y una vez tenemos estos códigos hexadecimales, tenemos que introducirlos en un buffer, como ya hicimos en anteriores sesiones, debemos tener ciertas cosas en cuenta:
  • Tamaño del buffer (shellcode no puede ser de longitud infinita)
  • La cadena no puede contener bytes NULL ( \0 ), ya que si se copia a memoria, esto significa que aquí se acabaría esa cadena.
  • Los códigos no deben ser dependientes de direcciones de memoria (no sabemos en que dirección se introducirá cada código).
Nuestros objetivos serán: obtener una shell, leer fichero /etc/shadow, añadir usuarios con privilegios ... Cualquier cosa que sea posible programar.

Para esto vamos a pasar ya a la segunda sección:

System Calls, Syscalls o llamadas al sistema

En Linux, a la hora de realizar ciertas funciones que requieren el uso del kernel, se realizan unas llamadas al sistema indicando un número, unos argumentos y ejecutando una instrucción en ensamblador  "int $0x80", con esto se genera un trap que el kernel recoge y decide si ejecutar o no dependiendo de permisos y capacidades. Por ejemplo las llamadas al sistema pueden ser: abrir archivos, escribir o leer archivos, ejecutar llamadas a programas, conexiones de red ...
Todas estas llamadas llevan asociadas un número, este número se introducirá en el registro AX, para que a la hora de ejecutar int $0x80, se sepa que llamada al sistema queremos realizar.
Aquí dejo el enlace con la lista: Syscall 

Un ejemplo sería realizar una llamada a exit(0), una llamada fácil, y la cual podemos escribir en ensamblador así:

mov $0x00, %ebx
mov $0x1,%eax
int $0x80

Esto lo metemos en un archivo con la extensión ".s" y lo compilamos de esta manera:

as salidaProg.s -o salidaProg.o
ld salidaProg.o -o salidaProg

Si lo ejecutamos veremos que... no pasa nada. Es normal estamos realizando una llamada a exit. 
Para obtener los opcodes de estas operaciones ejecutamos lo siguiente:

objdump -d salidaProg

Y obtendrems una salida como la siguiente:

Esto como shellcode no vale un pimiento, tenemos demasiados 00, lo cual cortaría la cadena, bien podemos aplicar varios trucos, por ejemplo en lugar de mover 0 a ebx, podemos realizar un XOR de si mismo, realiza el mismo trabajo pero es más eficiente, seguido, podemos hacer lo mismo con eax un XOR para ponerlo a 0, y realizar un incremento (inc) para obtener 1.

Como vemos, ahora tenemos OPCODES más válidos. Por tanto nos podríamos montar una cadena tal que así:

"\x31\xdb\x31\xc0\x40\xcd\x80"

Nuestro primer shellcode propio, que realmente no vale para nada...

Nuestro primer objetivo va a ser ejecutar una shell para poder ejecutar comandos, por ejemplo con la llamada "execve", con la cual podemos ejecutar una shell de la forma:

execve("/bin/sh\0",["/bin/sh\0",NULL],NULL)

Lo complicado aquí es referenciar una cadena como /bin/sh, para ello veremos dos métodos, uno de ellos usado por Aleph1 (escritor de Smashing the stack for fun and profit) y otro el cual es más directo:


Aleph1 Shellcode

Para crear la shellcode de Aleph1 , se basó en el funcionamiento de la pila al realizar un call. Ahora mostramos el proceso:
  (molan mis dibujitos ¿no?)
Explicamos un poco el código a continuación, tenemos que la primera instrucción a ejecutar es un salto a una etiqueta llamada "truco", tras saltar a truco, se ejecuta un call, a la etiqueta inicio, al realizar el call, en la pila se guarda la dirección siguiente a call, para poder retornar allí al acabar la función, ahora viene la magia, tenemos que la dirección siguiente a call, lo que contiene es una cadena, la cual queremos usar "/bin/sh". Dentro de inicio, hacemos un pop, para sacar la dirección de la pila y la guardamos en %esi (si os acordais es el registro fuente para cadenas). Por tanto ya tenemos referenciada la cadena.

Seguido vamos a mostrar el código original de Aleph1, para escribir el shellcode:

Como vemos tenemos el salto a "a1" donde tenemos un call a "a2", y abajo el string, en "a2", obtenemos en %esi, el puntero a la cadena, seguido en la dirección de memoria que guarda %esi + 8, metemos la dirección de la cadena (si, de nuevo), y ahora entre medias metemos un NULL byte para establecer un final de cadena. En %eax, metemos la syscall 11, la cual es execve, finalmente introducimos los argumentos en registros para que la función pueda obtenerlos (en %ebx la cadena completa, en %ecx, el puntero a la cadena y a \0 o NULL, y en %edx un NULL) finalmente ejecutamos la syscall, la cual ejecutará /bin/sh y nos devolverá una shell. (El resto de código es simplemente para realizar exit, pero no es necesario).

Si compilamos con el proceso anterior y ejecutamos objdump obtenemos la siguiente salida:

Como se puede observar a primera vista, tenemos muchos bytes NULL (00), por lo tanto no podríamos de primeras inyectar esta shellcode. Otra cosa extraña que podemos observar es después del CALL, hay unas instrucciones bastante extrañas, podemos ignorar esto, ya que es los OPCODES de nuestra cadena, corresponden a ciertas instrucciones en ensamblador.

Vamos entonces a aplicar los trucos que vimos antes, utilizar XOR, incrementos, utilizar los tamaños de registros más pequeños posibles, tenemos entonces aquí el código:

Como vemos, ahora para conseguir un valor 0, realizamos un xor en %eax, y es el valor que pasamos a los finales de cadena de %esi, luego el valor 11 de la syscall, en lugar de meterlo en %eax, vamos al registro más bajo %al, el cual puede guardar un byte. La syscall a exit, la comentamos, pues no es necesaria.
Vamos a ver que nos devuelve objdump: 

Si nos fijamos ahora, vemos que ya no tenemos NULL bytes (00), y podemos juntar todos estos OPCODES, unirlos y generar una shellcode, que nos devuelve una shell (ya la cosa no es tan inutil,¿no?).
 Si os acordais nuestro exploit hecho en python de la anterior sesión, utilizabamos este shellcode, y funcionaba, así que tan mal no era.


Pusheando Cadenas

bueno ahora vamos a un método un poco más directo, vamos a introducir directamente nuestra cadena en la pila. Para ello vamos a separar las cosas de 4 bytes en 4 bytes:

/bin/sh\0

Esta es la cadena que queremos insertar en la pila, pero principalmente nosotros no podemos introducir 00 en el shellcode puesto que dejaría de copiar ahí, ya veremos como lo hacemos. Separamos entonces de 4 en 4 bytes:

/bin            <- aquí van 4 bytes

//sh            <- para obtener el 4º byte añadimos otra /
\0               <- podemos limpiar un registro por ejemplo %eax, con xor %eax,%eax

Como vamos a insertarlo en la pila, lo insertaremos al reves (ya que las cosas se insertan de direcciones altas a bajas, y luego al ejecutarlo se ejecutará de direcciones bajas a altas) además cada 4 bytes por ser little endian se introducirán al reves (nib/,hs//) .

La primera llamada que se realizará será a setreuid(0,0), la cual hace que si un archivo con el bit suid activado deja los permisos de su propietario, los recupere (por ejemplo root). Seguidamente introducimos las variables en la pila y ejecutamos execve con el shellcode.


Vemos que primero limpiamos registro y de seguido preparamos la llamada a setreuid(0,0) recordemos que los parámetros se introducen en los registros. Finalmente llamamos int $0x80.
Luego limpiamos el registro %eax (pues contiene el valor de retorno de la función anterior), lo metemos en la pila (\0), metemos una cadena (//sh al reves), metemos otra cadena (/bin al reves), como esta cadena ahora es apuntada por %esp (al ser la cima de la pila), movemos esa dirección a %ebp, metemos en la pila un 0 (NULL), metemos la cadena /bin//sh\0, ahora hacemos que %ecx apunte a esos dos parametros (en C metemos arg[1], arg[0] y finalmente arg). Establecemos en al la syscall y la llamamos.
Bien vamos a compilar y ejecutar a ver que pasa:

Como vemos obtenemos una shell, ahora obtendremos los shellcode y los meteremos en el exploit de la anterior sesión de python:

Cogemos los opcodes y nos vamos al python:


Aquí las partes del código modificadas. Ejecutemos a ver que pasa:

Vaya, no pasó nada... Bueno esto es lo que me encontré al ejecutar la shellcode tal y como venía en el libro, el problema es que cuando realizamos el push de la cadena /bin//sh\0, el código que está abajo de esta cadena se sobreescribe con basura:
Vamos a ejecutar el programa esta vez así, para poder ver que pasa con un debugger visual, iremos directamente a la ejecución de la shellcode.
El trozo de código que nos interesa antes de meter en la pila /bin//sh\0.
El código tras realizar los push, coomo vemos la parte de abajo se ha modificado, pues estamos metiendo datos en la pila donde antes estaba nuestro código, por tanto hemos fastidiado toda posible ejecución.


El arreglo de Fare9

 El problema es que no hemos reservado pila para introducir esos valores, el caller necesita reservar algo de memoria, y como metemos 12 bytes, entonces tenemos que aumentar nuestro tamaño de pila, y como la pila crece hacia abajo, restamos 12 bytes a esp, vamos a ver entonces como quedaría el código:

Como vemos antes de limpiar %eax con XOR, realizamos un sub $0xC,%esp, con eso dejamos 12 bytes para poder introducir las variables en la pila. 
Compilamos, sacamos con objdump los opcodes y los metemos en el exploit. Ahora lo ejecutamos y a ver que pasa:

Vaya, vaya ahora sí que obtenemos una shell, acabamos de realizar un shellcode bastante "básico" y finalmente hemos logrado explotar una vulnerabilidad en un programa.


--------------------------------------------------------FIN

Para la proxima entrada tocaremos el tema de sockets para un shellcode, espero que esteis disfrutando de estas entradas y si recordad que podeis seguirme en twitter ( nombre Fare9 ). En cualquier caso podeis escribir en los comentarios e intentaré responder lo antes posible.

Nos vemos en el siguiente "de 0 a exploiting"

04 enero, 2017

Un minuto sin 01 con Richard Stallman

Hola a tod@s



Como todos sabéis en la última edición de Sec/Admin tuvimos como invitado al gran Richard Stallman. Hoy tenemos el placer de tenerle en Estación Informática, disfrutemos pues.


1º ¿Quién es Richard?
Soy el fundador del movimiento software libre.  Lucho para libertar a
los usuarios de la informática del poder de los programas privativos
porque someten a quienes los usen al poder de su propietario.

Los programas privativos son malos y no deberían existir, porque todo
programa debería respetar la libertad de sus usuarios.

Para hacer posible el uso de una computadora sin programas no libres,
lancé el desarrollo del sistema operativo GNU como reemplazo a los
sistemas operativos privativos.  Muchos usan GNU y erróneamente lo
llaman "Linux".  See https://gnu.org/gnu/linux-and-gnu.es.html.
 

2º ¿Que sueles hacer cuando tienes tiempo libre?  
Leo, como, a veces cocino para amigos, a veces escribo parodias, a
veces miro una película -- siempre sin DRM, sin aceptar un contrato
EULA, y sin identificarme a ninguna empresa -- entonces NO CON
NETFLIX.  Véase stallman.org/netflix.html!

A veces escucho música desde copias que tengo -- nunca por un servicio
injusto de streaming, como por ejemplo Spotify.  Out, out, damned
spotify!  Véase stallman.org/spotify.html!
 

3º Si no hubieras sido informático, ¿A qué te hubieras dedicado?
Pensaba hacer investigación física, pero por fin programar me daba más
satisfacción.
 

4º El último libro que has leído.
The Quest for Kibi.  Se trata de la historia del Japón y sus
relaciones con la Corea.

 

5º Tu plato favorito.
No tengo favorito, me gusta la variedad.  Véase
stallman.org/rms-lifestyle.html.  

6º El último sueño raro que tuviste.
No recuerdo mis sueños.  Qué lástima para mí.

7º ¿Qué música sueles escuchar?
Muchos tipos de música me gustan; véase
stallman.org/rms-lifestyle.html.
  

8º Lo último que piensas antes de dormirte.
No lo recuerdo.

 

9º Lo primero que piensas cuando te levantas por la mañana.
Varía cada día.

 

10º Lo primero que harías si fueras presidente.
Libertaría a todos los prisioneros de Guantánamo, excepto los a los
cuales hay un juicio.  El encarcelamiento sin juicio es una injusticia
enorme.  Quiero limpiar mi país de esta vergüenza.

19 diciembre, 2016

Carta a Papa Noel la saga tenía que continuar…

Hola a tod@s

Querido Papa Noel este año he optado por hacer pública mi carta anual y seguir la tradición que empezó Alejandro Ramos en Security by default. 

Este año he sido muy bueno, he sido papa, así que tendrás más trabajo cuando pases por casa. He organizado un congreso espectacular en Sevilla, repartiendo hacking por la ciudad hispalense, además nos llevamos de paseo por Sevilla a tu primo Richard, jo jo jo ;)

También me he portado muy en Mnemo y en el cliente sacando buenas notas, sin más dilación te describo a continuación los regalos que deseo para este año:

El deseo más anhelado de todos es que exista la paz en el mundo y que a nadie le falte dos cosas básicas en el siglo XXI como es el agua y la comida.

Si se cumple el primer deseo a mí me gustaría tener el teléfono móvil Pwn Phone, este dispositivo se ha hecho muy famoso tras aparecer en la serie Mr. Robot, aunque aquí en Estación Informática ya le dedique un artículo en la primavera del 2014. Se trata de un dispositivo móvil orientado a las pruebas de penetración, cuenta con una versión modificada de Android KitKat, con gran cantidad de aplicaciones de hacking preinstaladas. Además, posee un USB de tamaño estándar como el de cualquier PC al que se pueden conectar diferentes dispositivos (por ejemplo antenas o adaptadores bluetooth) para aumentar la potencia y el alcance de la señal del teléfono.



Como sabes me encanta los juguetes hacking, por eso me voy a pedir la LAN Turtle y la WiFiPineapple. La tortuga se trata de una herramienta de administración de sistemas y pruebas de penetración que se oculta en el sistema proporcionado acceso remoto, recopilación de datos, reconocimiento de red y capacidades de monitoreo tales como man in the middle. El caso de la piña se trata de una herramienta de auditoría red inalámbrica. Ya que entre wifis anda el juego puede ser que venga la piña con una Yagi, se trata una antena direccional que me será de gran ayuda en las auditorías wireless.




Sigamos, es el turno de Pwn Plug R3, el sueño de cualquier pentester. Cuenta con 802.11a/b/g/n Wireless, Bluetooth, funciona con Pwnix, una distro personalizada de Debian basada en Kali Linux y más de 100 herramientas.



PhantomKeystroker, si me llega a tiempo podré trolear a los compis del curro, tan sólo tengo que conectar el dispositivo en el ordenado de la víctima realizando molestos movimientos aleatorios en su ratón pensando que está infectado por algún virus.



Por otro lado me gustaría que me regalaras un KeyGrabber Wi-Fi Premium, estamos hablando de un keylogger inalámbrico equipado con dos microprocesadores de buen rendimiento, completo pila TCP/IP, transceiver WLAN y 4 gigabytes de memoria Flash. Este keylogger inalámbrico se conecta al Punto de Acceso Wi-Fi local, y manda E-mails que contienen el texto interceptado del teclado. Además, se puede conectar a distancia por TCP/IP en cualquier momento y consultar el archivo grabado de log. ¡Todo esto en un dispositivo de tan sólo 5 cm!



Y por último y no menos importante el Crazyradio PA para hacer “cosillas” de radio como Keysniffer digamos que es similar a un keyloger, pues el atacante captura todo lo que la víctima escribe en su teclado. A diferencia de un keylogger no tienes que conectar absolutamente nada en la máquina víctima, ya que la vulnerabilidad radica en teclados inalámbricos, además también podemos inyectar. :p



Sin otro particular, quedo a la espera de los regalos.

Atentamente: Javi.

PD: Ya no hace falta que me traigas la licencia de Shodan, me lo traje del Friday ;)



17 diciembre, 2016

De 0 a exploiting (II)

Buenas amigos hoy os traigo la segunda entrada de la serie "De 0 a exploiting", donde me obligo a leer un libro de exploting y traeros los conocimientos que obtengo (a mi manera).

Antes de nada, aquí vamos con los preparativos que diré siempre:

###############################################

Desactivar la aleatoriedad en las direcciones de la pila, para ello debeis ejecutar el comando (como root):
echo 0 > /proc/sys/kernel/randomize_va_space

Compilar (hoy si) con:
gcc -g -fno-stack-protector -z execstack codigo.c -o programa
 
###############################################


El otro día os dejé con una pregunta a partir de cuantas 'A's el programa empezaba a petar.

Vamos a explicar hoy el por qué peta (hoy toca algo de teoría) , pues es uno de los conceptos más importantes en el exploiting.



SOBREESCRIBIR EL REGISTRO EIP

 Empecemos por el procesador, un elemento del ordenador el cual procesa datos e instrucciones, para finalmente realizar cálculos para lo cual se suele usar una ALU (Unidad Aritmético-Lógica). Los procesadores pueden guardar los datos en diferentes sitios, para ello pueden usar unas cosas llamadas "registros" los cuales tenemos algunos de proposito general AX,BX,CX,DX , tenemos otros que apuntan a los segmentos dentro de la memoria SS,CS,DS... (Para más información teneis el libro Arquitectura de Computadores de Hennessy y Patterson). Además de los registros, para guardar datos tenemos la memoria (la memoria recuerda cosas....).

De los registros tenemos uno de suma importania, IP o Instruction Pointer o Program Counter. Este registro se encarga de ir apuntando la siguiente dirección de memoria , como el código suelen ser saltos a funciones, condiciones, rutinas ... Pues necesitamos un registro que guarde la siguiente dirección de memoria a ejecutar. Bien en el programa de ejemplo del otro día hacíamos una llamada a una función, eso en ensamblador se convierte en un "Call", el cual es una de las pocas funciones que pueden modificar IP, al volver de la función el programa debe saber donde volver, por tanto guarda en una memoria específica (llamada la Pila a partir de ahora) el valor de IP antes de llamar a la función. En la pila se guardan los argumentos de las funciones, IP, variables locales... Esto permite la recursividad en programación.

Veamos un ejemplo de la llamada a la función del otro día en ensamblador (la cual tenía un argumento):

push arg ;mete argumento en la pila
call func ;llama a la funcion mete valor IP en la pila

Bien una vez dentro de la función debemos reservar como una "Pila" propia de la función para las variables de la función, esto es lo que se llama marco de pila, tenemos un registro llamado BS que apuntará al principio de esa pila, y tenemos SP que apunta siempre al final de nuestra pila. Pues un marco de pila se crea algo como así:

push bs ;guardamos el valor de bs (para no cargarnoslo), luego lo recuperaremos
mov bs, sp ; metemos el valor de sp, en bs (ya tenemos la base de nuestra pila)
sub sp, X ;restamos X al valor de sp, asi agrandamos nuestra marco de pila

Os preguntareis ¿Por qué restas X, en vez de sumar? si lo que queremos es agrandar, bien la pila va desde las direcciones de memoria más altas, a las más bajitas, por tanto para crecer, tenemos que restar (Imaginaos la pila como un hombre algo rata, nos deja unas direcciones lejos de la dirección más baja de la pila, una alta, y para reservar memoria en la pila, tenemos que quitarle direcciones, pues restamos).
Bien pues veamos un dibujo de como quedaría la pila, y a donde apuntarían ahora BS y SP.


(me he currao el dibujito ¿no?)

Bueno vemos que en los registros antes ponemos una 'E', esto significa que es un procesador de 32 bits, y en lugar de guardar 16 bits en el registro, guardamos 32 (un sistema operativo de 32 bits, sus direcciones tienen 32 bits).
Como vemos arriba del todo (las direcciones más altas) tenemos un marco de pila de otra función (por ejemplo main), y seguido metemos unos argumentos, luego la dirección a la que volveremos después, seguido el valor de BP para volver a cogerlo al acabar la función, vemos que EBP, al realizar el mov ebp,esp , ahora ebp apunta a donde se puede ver, seguido se haría sub esp,32 , para guardar la variable nombre, por tanto ahora esp apunta al final del buffer nombre.

Ahora viene lo siguiente la...

¿Por qué? , por que mientras que el buffer Nombre, se reserva para abajo, crece para arriba, y nosotros al meter un gritón de 'A's, llenabamos el buffer, luego llenabamos el valor guardado de EBP y finalmente el valor guardado de EIP, por tanto al acabar la función en donde estaba el valor de EIP ahora hay  "AAAA", y el procesador intentaba saltar a la dirección "0x41414141", la cual no está mapeada en nuestras direcciones de memoria.
Y por eso el programa petaba.

Ahora vamos una vez acaba la teoría, con la parte práctica.
¿Qué vamos a aprender?
  1. Encontrar manualmente cuantos bytes necesitamos para petar el programa.
  2. Encontrar automáticamente cuantos bytes necesitamos para petar el programa.
  3. Explotar este fallo para conseguir una shell.
1. Encontrar manualmente cuantos bytes necesitamos para petar el programa

Bien para realizar esto, vamos a utilizar el debugger: edb-debugger (Descargable aquí: https://github.com/eteran/edb-debugger ).
Para empezar vamos a ejecutar nuestro programa con este debugger y vamos a meter como argumento por ejemplo nuestro nombre y ver como se ejecuta:


Bien ahora iremos al programa edb-debugger a ver que nos encontramos:

En el centro tendremos bien en grandote tenemos el códigooooo (de momento pasad de este, por que no nos vale para nada).
 Tenemos la pila, donde vemos por ejemplo los argumentos de char argv[], el primero es ./ejemplo1 (nombre del programa) y el segundo es Fare9 (nombre).

Y finalmente tenemos los registros, los 4 primeros son registros de proposito general, tenemos EBP, ESP que apunta justo a la cima de nuestra pila (imagen de arriba de la Stack), ESI y EDI (ahora mismo no nos interesan mucho). Y finalmente uno que nos interesa mucho EIP, el cual vemos que está apuntando al principio del código que tenemos (imagen de arriba de código).
Como vemos está apuntando ahora mismo a una librería, todavía no es nuestro código. Por tanto para establecer todo al principio de nuestro main ejecutaremos: F9 .


Ahora tenemos otro código diferente y los registros también han cambiado su valor (en concreto EIP ahora apunta a la primera instrucción de nuestro código). Vamos a intentar reconocer un poco lo que se está haciendo. Lo primero que vemos es un lea (siglas de load effective address) a insertar un valor en ecx, ese valor es  [esp+4]. Esto en ensamblador es una forma sencilla de meter en ecx el valor de esp + 4. Luego se realiza una operación lógica and, seguido de un push, el cual vale para insertar datos en la pila como hace push con [ecx-4] es coge el valor de ecx restale 4 y accede a la dirección de memoria que es igual a ese valor de la resta, y lo metes en la pila. Bien no es un curso de ensamblador para cualquier cosa podéis ir a las referencias de abajo.
Vamos a algo más clave, un cmp (código para compare), compara un valor que guarda la dirección de memoria guardada en eax, con 2 (igual que hacíamos en nuestro programa) estamos comparando argc con 2, en caso de ser iguales (jz [jump if zero] es igual a je [jump if equal])  y vemos que si son iguales salta a0x0804501 (un poquito más abajo).

Para poder avanzar en edb debugger tenéis F7 y F8 , la diferencia entre ambos es que F8 si encuentra un call (o función) la ejecuta y pasa por encima, y F7 NO.

Pues ejecutemos hasta realizar el salto:
Bien ya estamos después del salto, vemos que tenemos 3 instrucciones que lo que hacen es buscar el primer argumento argv[1], el cual es nuestro nombre, antes del call tenemos push eax, que lo que hace es meter la dirección donde se encuentra "Fare9" en la pila, para finalmente llamar a Func(args).
Si vamos observando la pila veremos que al llegar al call, lo que tendremos es Fare9.
Bien, ahora realizaremos el call, y como os he contado antes, se debe meter la dirección siguiente al call ( 0804:8512 ), para entrar al call avanzamos con F7 .
Como vemos en la cima de la pila, se ha guardado la dirección de retorno.
Y vamos a ver el código que tenemos:
Vamos a ver las 3 primeras lineas, estas crean como os conté antes el "Marco de Pila", como vemos reserva en un principio 40 bytes, pasaremos del sub esp,8 . Lo siguiente es la llamada a la función strcpy(Nombre,arg) que teníamos en el código original.
En ensamblador al llamar a una función tenemos que meterle en la pila sus argumentos, los cuales los meteremos de derecha a izquierda, por tanto al meter [ebp+8] metemos el argumento que pasamos antes ("Fare9"), con lea eax,[ebp-40] , estamos haciendo que eax apunte al principio del buffer (40 bytes más abajo), seguido lo metemos en la pila y finalmente llamamos a strcpy. Ahí es donde vendrá nuestra oportunidad de insertar datos y datos. Iremos llamando ahora con F8 hasta llegar al call:
Vemos que primero se metió "Fare9" (la dirección de esa cadena), seguido del lugar de la pila donde se copiará BYTE A BYTE hasta encontrar un \0. Ejecutaremos y veremos la dirección de la pila bffff380:
Bien entonces, vemos que en bffff380 (como se indicó arriba) se ha copiado la cadena Fare9, y abajo del todo en bffff3ac, tenemos la dirección de retorno a donde volveremos después de finalizar Func(), cojamos nuestra calculadora de programador y restemos bffff3ac - bfff:f380.  La respuesta es 2C (el sentido de la vida...) bueno esto es el valor hexadecimal de: 44. Que es el número de bytes que metiamos antes de petar el programa, tras insertar 44, los siguientes petarán el programa, pues como veis ahora GRÁFICAMENTE, estamos modificando el valor de retorno.
Hemos aprendido entonces como ver cuantos bytes necesitabamos para petar el programa manualmente.

2. Encontrar automáticamente cuantos bytes necesitamos para petar el programa.

ahora seremos más rápidos, sabemos que con gdb al ejecutar el programa y petarlo con tropecientas 'A's, nos decía gdb, el programa ha petado por intentar acceder a la dirección 0x41414141, bien¿ y si metemos  "AAAABBBBCCCCDDDDEEEE...."?, depende de con qué sobreescribamos EIP nos dirá que ha petado con otra letra o conjunto de ellas, y después pues calcular "si he metido tropecientas letras en la cadena, y ha petado en la 'E', y cada letra eran 4 veces repetidas..." Bueno si no quereis hacer calculos podéis usar los programas "Pattern_create.rb" y "Pattern_offset.rb" de Metasploit los cuales uno te genera una cadena de caracteres aleatorios, y el otro le dices la cadena y el hexadecimal (creo) de dónde ha petado, y te dice bytes para petar el programa. Peeeero, si queréis un poco que pueda seguir con estas entradas, os pido useis mi versión PatternPetater . Un script en python que te hace las dos cosas a la vez.
En principio vamos a ejecutar el patternpetater, para ello : python randomGenerator.py .
Primero lo ejecuté sin argumentos y después con 128, ha generado una cadena aleatoria de 128 bytes, ahora ejecutaremos el programa ejemplo1 con gdb, seguidamente haremos un RUN y copiamos y pegamos la cadena anterior, lo cual dará un fallo:

Primero llamamos a gdb, seguido dentro de gdb ejecutamos run junto con la cadena que generó PatternPetatter, finalmente tuvimos un error con lo de la dirección : 0x77526846 (se cortó en la imagen). Bien copiamos esta cadena y la pegamos en PatternPetater, que estaba esperando por nosotros:
Como vemos PatternPetater, nos dice que 44 es el máximo de bytes antes de petar el programa, pues el String que causó el error fue FhRw (el cual está dentro de la cadena antes generada).
Bien con esto sacamos automáticamente cuantos bytes tenemos hasta petar el programa y sobreescribir EIP, esto nos será importante para saber que payload (lo explicaré en la siguiente entrega), podemos insertar, ya que 44 bytes no es mucho, por ejemplo un Meterpreter no podríamos.

3. Explotar este fallo para conseguir una shell.

Ahora vamos a crear un primer exploit en python, con lo cual uniremos un payload que se mostrará en el código, junto con purrelez que tenemos que meter para llegar a 44 bytes, más la dirección de retorno que guardaremos en donde estaba EIP, que será el principio del buffer, para que se ejecute nuestro código que insertamos:
 Aquí tenemos el shellcode, los nops son código que el procesador ejecuta sin hacer nada los cuales los pondremos antes del shellcode, para cuando el procesador salte al principio del buffer, ejecute un NOP y siga ejecutando hasta encontrar el shellcode. Como veis, la dirección de retorno es diferente a la que sacamos antes, esto puede cambiar por eso tenemos la última linea (ahora comentada), que nos abriría el debugger, para sacar la dirección a la que tenemos que saltar. Al ejecutar este exploit debemos obtener una shell de comandos:

Como vemos, al ejecutar el exploit, se llamó al printf que teníamos después de strcpy, hizo caplof, y por arte de magia (ir al gif de magic), nos devolvió una SHELL, para poder ejecutar nuestras cosas de Hackers y todo eso, por ejemplo podríamos dejar una shell a la escucha con netcat o aún mejor ncat cifrada con clave pública.

--------------------------------------------------------FIN

Como vemos hoy hemos aprendido mucho, mucho. Vimos como sacar manualmente el número de bytes para petar el  programa, vimos como utilizar herramientas para conseguir esto, y además creamos un primer exploit (no digais que Fare9 no enseña cosas pa' aburrir) .
Ya sabeis que podeis encontrarme en Twitter ( como Fare9 ), o podeis escribir en comentarios e intentaré responderos lo antes posible.

Nos vemos en el siguiente "de 0 a exploiting"




Referencias:

Más información en los apuntes de laboratorio de este hombre: http://atc2.aut.uah.es/~rico/docencia.htm