lunes, 22 de agosto de 2016

"VulnHub CTF Breach2" recien salido del horno.





Proba tus habilidades con esta ISO recien salida del horno en su segunda version Breach 2.0. Como los creadores dicen, intentan ofrecer un escenario virtual lo mas similar posible a la realidad.

Datos del creador:

Second in a multi-part series, Breach 2.0 is a boot2root/CTF challenge which attempts to showcase a real-world scenario, with plenty of twists and trolls along the way.
The VM is configured with a static IP (192.168.110.151) so you'll need to configure your host only adaptor to this subnet. Sorry! Last one with a static IP ;)
A hint: Imagine this as a production environment during a busy work day.
Shout-out to knightmare for many rounds of testing and assistance with the final configuration as well as rastamouse, twosevenzero and g0blin for testing and providing valuable feedback. As always, thanks to g0tmi1k for hosting and maintaining #vulnhub.
If you run into any issues, you can find me on Twitter: https://twitter.com/mrb3n813 or on IRC in #vulnhub.
Looking forward to the write-ups, especially any unintended paths to local/root.
Happy hunting!
SHA1:AF85D25B1A5E14FB0E8539BAFCA832BFC17F425D

Pueden descargarlo del siguiente lugar: https://www.vulnhub.com/#modal159download

domingo, 21 de agosto de 2016

Chan.. Shadow Brokers NSA Hack Leaks 0-day Vulnerabilities

Right now there’s a ton of people talking about the NSA Hack, the severity, the repercussions and the value of what has been leaked. It seems the 0-day exploits in the cache of stolen aren’t super recent ones, as it appears they are from 2013.


















But even so, some of them haven’t been patched as both Cisco and Fortinet have warned customers about the vulnerabilities revealed in the data posted by Shadow Brokers.
A group calling itself the Shadow Brokers has started an online auction for top-of-the-range tools it claims were stolen from the Equation Group, a digital attack squad linked to the NSA.
The Shadow Brokers posted up news of the auction saying (in broken English) that they had been monitoring the Equation Group’s servers, had stolen the advanced hacking tools, and will auction them off to the highest bidder. The group said that if it gets Bitcoins worth $1m they will release the tools for free to everyone.
“We want make sure Wealthy Elite recognizes the danger cyber weapons, this message, our auction, poses to their wealth and control. Let us spell out for Elites. Your wealth and control depends on electronic data,” the group said [the link has since been taken down].
“You see what ‘Equation Group’ can do. You see what cryptolockers and stuxnet can do. You see free files we give for free. You see attacks on banks and SWIFT in news. Maybe there is Equation Group version of cryptolocker+stuxnet for banks and financial systems?”
Claims about stuff like this for sale online are often fake, so to prove their case the team posted sample code, which it says is around 40 per cent of the total, online. Postings on Github and other download sites have since been taken down, but not before some people got copies.

Now it seems NSA wasn’t hacked directly, but via an agency called Equation Group which is believed to be a digital cyber-terrorism arm of the NSA.
Even so, it brings up some well debated issues about the NSA reporting zero-day flaws to vendors rather than hoarding them (which the White House promised they would stop doing).
A preliminary analysis shows the revealed list seems to be focusing on router flaws, some of them quite old. Some files also share names with exploits listed in the NSA’s Tailored Access Operations hacking team’s catalogue for agents, revealed in 2013 by Edward Snowden.
Kaspersky, who first linked the Equation Group to the NSA, said it was analyzing the files but had no clue as to their veracity as yet. But Timo Steffens, a member of the German CERT-Bund team, is taking a skeptical line, although he acknowledged that if this is a fake, the scammers had put in a lot of effort.
Initial analysis by the likes of Kaspersky Labs, NSA whistleblower Edward Snowden, and a host of independent security researchers shore up claims by a hacking group calling itself Shadow Brokers that the exploits and toolsets it hopes to auction for millions of dollars in Bitcoins are legitimate Equation group weaponry.
Kaspersky Labs last year revealed the Equation group to be almost certainly a state-sponsored actor and, according to deep analysis of its activities, highly likely to be a wing of the National Security Agency given a series of very striking operational and technical similarities.
The Shadow Brokers group seems to likely originate from Russia, so this is a nation state vs nation state attack possibly at the highest levels of each countries intelligence agencies.
It’s an interesting story and it’s creating a lot of news and drama, it’s a tough call for NSA as they have to maintain their attack capabilities against Russia and China whilst also balancing the health of American commerce and the safety of all the users utilising equipment from those vendors.
Source: The Register

domingo, 14 de agosto de 2016

Resolviendo el "Starting VirtualBox kernel modules …failed" (Ubuntu 16.04 x64)

Bueno luego de desaparecer por mucho tiempo, i'm back.
Estos dias estuve preparando mi chiche nuevo de laptop con Ubuntu 16.04 64bits e instale el querido virtualbox, pero claro tuve un inconveniente al arrancarlo y levantar la imagen nueva de la virtual que había creado. El error que arrojaba era el siguiente:

WARNING: The vboxdrv kernel module is not loaded. Either there is no module
         available for the current kernel (4.4.0-22-generic) or it failed to
         load. Please recompile the kernel module and install it by

           sudo /sbin/rcvboxdrv setup

         You will not be able to start VMs until this problem is fixed.
Logicamente al tipear /sbin/rcvboxdrv setup no se resolvia facilmente. En mi caso arrojaba el siguiente error:

sudo /sbin/rcvboxdrv setup
Starting VirtualBox kernel modules ...failed!
(modprobe vboxdrv failed. Please use 'dmesg' to find out why)

#> COMO SOLUCIONARLO:

Vamos a proceder a instalar el paquete DKMS como bien lo indica en la wiki de virtualbox:


  • Note: Ubuntu/Debian users might want to install the dkms package to ensure that the VirtualBox host kernel modules (vboxdrvvboxnetflt and vboxnetadp)


# Instalamos DKMS:

$> sudo apt-get install dkms

Luego de esto, vamos a reiniciar el ubuntu y entrar al BIOS, debemos desactivar el BOOTEO SEGURO/UEFI. Reiniciamos nuevamente, iniciamos el ubuntu y ahora al tipear lo siguiente ya deberia funcionar:

$> sudo /sbin/vboxconfig 
vboxdrv.sh: Starting VirtualBox services.


Saludos.

jueves, 5 de febrero de 2015

How To Exploit: Segmentacion de Memoria.. (Paper 4).

Este es el cuarto paper que escribo sobre como ir encaminando los conocimientos de assembler, gdb, etc hasta llegar y ver de lleno explotaciones, caza de bugs, etc. 

No se queden con este paper porque intento que NO sea un texto de programacion o assembler, pero es inevitable escribir un paper desde cero sobre explotacion, sin repasar las cosas realmente importantes que se deben saber.

Escribire un poco de definiciones y luego un codigo para verlo en la practica via GDB. GNU/Debugger. Los primeros papers los pueden encontrar aca: 



-1- http://insecuritynotes.blogspot.com.ar/2013/03/how-to-exploit.html
-2- http://insecuritynotes.blogspot.com.ar/2013/03/how-to-exploit-un-poco-de-assembler-y.html
-3- http://insecuritynotes.blogspot.com.ar/2013/03/how-to-exploit-gdb-mas-fondo.html

Sin dudas algo fundamental que no se puede pasar por alto es saber como se divide la memoria de un programa compilado, y es algo que voy a tratar de explicar para que se entienda bien, SI NO SE TIENE CLARO ESTO, se va a complicar bastante el recorrido hacia explotar vulnerabilidades o realizar reversing a software. Es como caminar a ciegas.. Tratare de que sea lo menos aburrido posible. Trataré...

La memoria de un programa compilado se divide en 5 segmentos que son fundamentales y cada uno tiene un proposito especial:


  • Codigo (o texto).
  • Datos
  • Bss
  • Heap
  • Stack


- Codigo (o texto): Llamada de ambas maneras, en esta seccion no tendremos ningun permiso de escritura. Esto es intencional para asi poder evitar que se modifique el codigo del programa.
Tampoco es el lugar donde se almacenan las variables, por ende lo unico que encontraremos es 'codigo'. Si por alguna razon nosotros intentaramos escribir alli, el programa colgaria, o alertaria de que esta out-of-band y finalizaria. Tambien suele referirse al contenido de esa parte de memoria como 'static values' por lo que explique recien, y como 'global values' ya que esa zona al ser read-only los valores estan disponibles para cualquier parte del programa que lo necesite.

- Datos y Bss: En esta seccion como se ve en la imagen, es donde se almacenan las variables tanto estaticas como globales. Una vez mas si vemos la imagen, en el campo DATOS vemos que se almacenan las variables estaticas y globales 'inicializadas'. Mientras que en Bss, vemos que se encontraran las variables 'no inicializadas'

- Heap: (Seguramente hayan leido en algun lado sobre.. 'heap overflow'), en esta seccion de memoria, el programador tiene total permiso de escritura, es usada como memoria dinamica durante la ejecucion del programa para asignar (allocate) o liberar (free) valores que el programa necesite/no necesite. Es llamado dynamic memory por la frecuencia en que puede cambiar su contenido mientras el programa esta corriendo. No posee un tamaño 'fijo'. Por ende la altitud de la pila crecera o decrecera en base a la cantidad de memoria reservada para su uso. El crecimiento del heap es de abajo.. hacia arriba.

- Stack (o pila): Esta zona tambien tiene un tamaño dinamico de memoria, se usa como memoria temporal para almacenar variables de funcion locales y argumentos de llamadas a funcion.
Imaginenlo de esta manera, cuando un programa llama a una determinada funcion, esta funcion va a poseer su propio conjunto de variables locales, y el codigo de esta funcion estara en otra posicion de memoria como habiamos explicado anteriormente en Codigo (o Texto).
Como el contexto y el EIP deben cambiar una vez que se invoca a una funcion, se utiliza la stack para recordar todas las variables pasadas, la posicion a la que debe volver el puntero EIP una vez finalice la funcion y todas las variables locales usadas por esa funcion. (Recuerden, EIP es el puntero de instruccion, imaginenlo como el dedo indice de nuestra mano cuando vamos leyendo un libro, y vamos siguiendo la lectura con el dedo para no perdernos..).

La stack, es un conjunto ordenado de elementos que se agregan o se quitan. Las direcciones altas de memorias 'estan ABAJO' y las direcciones bajas de memoria 'estan ARRIBA'.

La cima de la pila, es conocida como TOP OF THE STACK o tope de la pila. Lo interesante que tiene la pila, es que como dijimos es un conjunto donde se agregan o quitan elementos (imaginenlo como un mazo de cartas), y la manera en que los elementos se apilan o desapilan es por: ULTIMO elemento apilado es el PRIMERO en salir. (Conocido en ingles como LIFO, Last In, First Out). Dos de las funciones basicas que veremos seguido sobre la pila, son "push" y "pop", push inserta un nuevo elemento al 'tope' de la pila, y pop hara lo contrario, lo eliminara del tope.

















Marcos de Pila, o stack frame:
(Sacado de Google, editado por mi, me gusto la definicion).

Cuando se invoca a una funcion, se apilan varias cosas juntas, en un marco de pila. En principio el registro "EBP" al cual llamaremos: Puntero de Marco, Frame Point. Se usa para hacer referencia a las variables de funcion local en el marco de pila actual. Cada marco de pila contiene los parametros de la funcion, las variables locales, dos punteros que son necesarios para volver a dejar las cosas como estaban: el puntero de marco anterior (SPF) y la direccion de retorno que se usa para devolver el EIP a la siguiente instruccion despues de la llamada de funcion. Esto restauraria el contexto de funcion del anterior marco de pila...





















A continuacion vamos a hacer una practica de esto, adjunto un codigo basico que va a ayudar a entender mejor todo esto, y luego lo analizaremos con GDB.

#include <stdio.h>

void SoyUnaFuncion(int a, int b, int c, int d, int e) {

   int variableLocal1; // Se declaran variables LOCALES de esta funcion.

   int variableLocal2;

   variableLocal1 = 99;

   variableLocal2 = 999;

}



int main() {

   SoyUnaFuncion(1,2,3,4,5); // Invocamos a una funcion "SoyUnaFuncion".

}


Se declaran dos funciones, la clasica main() que es donde iniciara el programa, y luego esta llamara a la funcion "SoyUnaFuncion" (que imaginacion la mia eh xD), y se le pasaran 5 argumentos.. 

Dentro de la funcion 'SoyUnaFuncion' se declaran dos variables locales. Llamadas: variableLocal1, y variableLocal2 (estoy hecho una luz de imaginacion xD), con sus respectivos valores, 99 y 999.
Como habiamos aclarado al principio, en la zona de la STACK/PILA, se almacenaran estas variables locales de funcion.. Vamos a ver esto con atencion desde el debugger.

Compilamos el archivo con el flag -g. Y lo debuggeamos con gdb:



















Presten atencion a lo que resalte en amarillo. Se lo llama "Prologo de procedimiento" o en su ingles "Procedure Prologue", estas primeras instrucciones "configuran el Marco de la Pila".
Reservan el puntero de marco en la pila, y reservan memoria de pila para las variables de funcion locales. 

Siguiendo con el codigo de la funcion main(), vimos que lo unico que hacia este basico programa era invocar a la funcion "SoyUnaFuncion" y pasarle 5 argumentos -> "SoyUnaFuncion(1,2,3,4,5)". Estos argumentos seran apilados en la pila, y habiamos comentado que la manera de apilar y desapilar era mediante LIFO -last in first out- osea, ultimo entrado, primero salido.
Veamos la parte resaltada ahora como podemos observar estos 5 numeros enteros pasados a la funcion "SoyUnaFuncion":

















Luego vemos que al pie del ultimo argumento, hay un "CALL [0x80483ed]", donde empezara nuestra funcion invocada "SoyUnaFuncion".. Luego de ese CALL tenemos la instruccion LEAVE que es la direccion de retorno que EIP seguira una vez que ese CALL finalice. 
Bien, aca es donde el contexto cambia, y hay que prestar atencion..


Cuando ese CALL se ejecute, la direccion de regreso sera agregada a la pila y el rumbo de la ejecucion pasara al principio de la funcion "SoyUnaFuncion" como lo muestra la imagen siguiente:














Observamos el prologo nuevamente de instrucciones que crearan el otro Marco de Pila.

Vemos como con el "PUSH ebp", se apila el valor actual que tiene EBP. Se le da el nombre de SFP (Saved Frame Pointer). Puntero de Marco Anterior, y luego se utilizara para devolver a EBP a su estado anterior.

Vemos la siguiente instruccion "MOV ebp, esp" esto copia el contenido del registro ESP a EBP.
De esta manera se creara el nuevo puntero de marco, y referenciara a las 'VARIABLES LOCALES' de la funcion. (recordemos el codigo "variableLocal1, y variableLocal2").

Por ultimo el "sub esp, 0x10" reservara memoria para estas dos variables dichas, restandole 10 a ESP en este caso.

En la imagen vemos claramente las dos variablesLocales que declaramos. Por sino se dieron cuenta 0x63, y 0x3e7, corresponden a 99 y 999. Los valores que les asignamos a las variables, rapidamente con pcalc vemos los valores de cada uno en Decimal - Hex - Binario:






Ahora vamos a poner algunos breakpoints, para que el debugger se detenga y nos muestre con claridad todo esto.. 






















(1) Como vemos, el gdb se detiene donde se lo pedimos.. en el primer breakpoint de la funcion main().
(2) El valor de ESP esta en 0xbffff0d4. Y el valor de EBP esta en 0xbffff0e8 (Recuerden este valor).

Este breakpoint se encuentra antes de crearse el marco de pila para el CALL a la funcion 'SoyUnaFuncion'. 

Si continuamos hasta el segundo breakpoint, ya habremos llegado a la segunda funcion, despues del prologo de procedimiento, donde ya se habra creado el marco de pila..


















Bien, para concluir con esto.. paso a explicar la imagen.

(1) El segundo breakpoint nos deja luego de la creacion del marco de pila, justo en el momento que se asigna la variableLocal1 que tiene 99 de valor. Y se mueve a la direccion de memoria [ebp-0x8] y la segunda variable local a [ebp-0x4]. En el punto (3) imprimimos la dirección destino en dos variables, para recordar esas direcciones.

El punto (2) nos muestra info de EBP y ESP. Vemos como la stack esta al tope en [0xbffff0bc].
Tipearemos 'nexti' dos veces para que el breakpoint donde habíamos parado avance dos instrucciones mas que era donde las variablesLocales estaban insertandose en la pila.. Una vez hecho esto Si examinamos esta zona de la pila entenderemos todo mejor.. 








En el punto (1) al final del marco de la pila vemos los 5 argumentos de la funcion que habiamos pasado, 5,4,3,2,1. En el punto (2) seguido a los argumentos, vemos la dirección 0x8048435, esa es la direccion de retorno, luego del CALL a la funcion!!..







En el punto (3), se encuentra el puntero de marco anterior, que era el EBP en el anterior marco de pila, (les dije que se lo recuerden ese valor mas arriba). En el punto (4) vemos ambas variablesLocales asignadas en la función, las cuales tenian valor 99 y 999..en hexa como vimos arriba, 0x63 y 0x3e7 ;D.

Para finalizar, el programar terminara concluyendo su trabajo, y todo el marco se desapilara de la stack..

http://insecuritynotes.blogspot.com - c0nfused.


viernes, 30 de enero de 2015

INetSim, virtualizando network para Análisis Dinámico de Malware.

Estos últimos días estuve trabajando en unos análisis de Malware, y sin dudas un software que me ayuda bastante para la etapa Dinámica del análisis es INetSim. (Internet Services Simulation Suite). 

Este software lo que hace es simular servicios de internet. Entre otras cosas como se le conocería en términos de ingles: "Faking Network". Muchas veces, cuando se intenta analizar un malware mediante análisis dinámicos, con un poco de experiencia es suficiente para darnos cuenta mediante librerias y funciones que importa o strings que sale a buscar a internet o reportar información, y a veces preferimos realmente estudiar su funcionalidad y su comportamiento de manera controlada y bajo nuestro dominio. 

A veces no queremos que el malware realmente salga a internet, o reporte a sus creadores de nosotros, es por eso que en ciertas circunstancias optamos por 'hacer una faking network' y menos ruido con sus creadores.. Una tool excelente es sin dudas InetSim, la cual permite ejecutar el malware y hacerle creer que esta conectandose a el mundo exterior cuando en realidad no hace otra cosa que interactuar con nosotros mismos, o mejor dicho con nuestro amigo inetsim y sus servicios.

Dejare una breve reseña de como funciona, y como puede sernos util, a la hora de realizar como dije un analisis dinamico de malware.

Mi red para esta ocasion esta compuesta de la siguiente manera, 2 SO's:

A - 192.168.0.102 -> PC Linux con Debian/Ubuntu donde estara corriendo el InetSim.
B - 192.168.0.107 -> VMWARE corriendo un Windows XP.. (Nuestro entorno con malware). Este es un entorno controlado, y el malware a ejecutar no es realmente maligno, es solo para simularlo, así que asegurense de tener un entorno controlado y seguro siempre que hagan pruebas.

> Instalando INetSim (Linux):

# Para usuarios Debian/Ubuntu Linux: http://www.inetsim.org/packages.html
# Para el resto de mortales:  http://www.inetsim.org/downloads/inetsim-1.2.5.tar.gz

Una vez instalado, usarlo es demasiado facil. Pero antes hay que revisar y editar algunas cosas de configuracion. Ustedes luego podran editar e ir metiendo mano y modificar a su gusto sin romper nada. Iniciar mas o menos servicios, etc. Pero en este caso edito estas lineas para la prueba:

$> sudo nano /etc/default/inetsim

Buscamos la siguiente linea y ponemos el ENABLED en '1', salvamos el cambio y salimos:

# Whether or not to run the internet simulation suite; set to 0 to disable.
ENABLED=1

Lo siguiente sera ir al archivo de configuracion:

$> sudo nano /etc/inetsim/inetsim.conf

Buscamos la siguiente linea, la descomentamos y asignamos la IP del Linux donde corre InetSim, mi caso era la siguiente IP:

service_bind_address    192.168.0.102

Luego buscamos la siguiente linea y si bien dice 127.0.0.1, que seria la del linux mismo, descomentamos y editamos por la IP que tiene asignada:

dns_default_ip          192.168.0.102

Con esto ya podria funcionar tranquilamente para la prueba.
Lo iniciamos:

$> sudo /etc/init.d/inetsim start

Abrimos otra terminal, verificamos con nmap que esto es asi..

$> nmap 192.168.0.102 -vv

Y como resultado se darán cuenta si todo funciona bien que ya tenemos como 20 puertos y servicios abiertos corriendo :O.. no se asusten, solo 'simulan' muy bien serlo ;).

Nos dirigimos ahora a la maquina virtual que corre Windows XP y antes de 'ejecutar el malware' editamos su configuracion de red, para que apunte a nuestra ip con inetsim. Le decimos que su gateway a internet vamos a ser Nosotros (inetsim) y que su DNS por ende tambien :).





Una vez que configuramos esto, optamos por ejecutar el malware.. y veremos que pasa. Los reportes que genera inetsim se guardan en /var/log/inetsim/report

Una vez que se ejecuta el malware luego de pasado unos minutos, detenemos el inetsim y vemos el reporte que nos genero. En mi caso quedo algo así:


















1) Vemos como en el primer recuadro de la imagen, se realiza una consulta DNS bastante rara..
"0kxwuhostingmax.iprisid.com"... 

2) En el segundo resaltado vemos como dos minutos después realiza una petición via HTTP GET para descargar de un dominio bastante raro "http://0xhosting01.aknoid.com/176867868754/autodwn.exe".
¿que sera? ;p

3) Y en el 3 resaltado, vemos como realiza una similar petición pero ahora baja una librería llamada ashid.dll.

Como ultimo comentario, me gustaría resaltar como ven en la imagen el InetSim "responde" ante la petición del malware (GET) y le envía un 'fake file'. 

Esto es demasiado útil, ya que supongamos si un Malware que estamos analizando donde no tenemos mucho conocimiento de su comportamiento sale a internet a buscar algún tipo de archivo ya sea un .exe o .dll o cualquier otro, y no lo logra, posiblemente el malware quede inoperativo, o quizás no demuestre mas comportamientos hasta que su tarea de bajar otro archivo le permita poder completar todos los pasos de su infección y explotación.

Espero sea útil, personalmente, cumple un rol fundamental como tool en mis primeras etapas de análisis dinámico de malware en mis trabajos.

Saludos.

miércoles, 28 de enero de 2015

Vulnerabilidad Ghost + PoC (Remote Linux Vulnerability Glibc)


Sin dudas una de las noticias de estos dias es el descubrimiento de la vulnerabilidad -CVE-2015-0235-. 
Afecta a la libreria "glibc". La gente de Qualys descubrio un interesante desbordamiento de buffer en una funcion de glibc llamada "the_nss_hostname_digits_dots()". Se puede tomar ventaja remotamente de esta vulnerabilidad desde la funcion gethostbyname() de glibc.

Al parecer las versiones de glibc-2.17 y glibc-2.18 se encuentran parcheadas. De hecho lo estaban desde el 2013 pero no se considero de mayor prioridad y se paso por alto en muchos desarrolladores, por ende los modulos de ciertas distribuciones siguen siendo aun vulnerabilides.

Algunas app conocidas que dependen de esta libreria son Apache, GnuPG, OpenSSH, entre otras.

A continuacion adjunto un PoC hecho por vpetkov, para que puedan testear la vulnerabilidad localmente.  Primero dense una idea de que libreria tienen instalada con el siguiente comando, desde mi debian/ubuntu:

$> ldd --version

Desde Redhat y CentOS:

$> rpm -q glibc


El PoC para verificar si es vulnerable o no el sistema, peguenlo en un editor de texto, guardenlo como ghost.c. Luego lo deben compilar con gcc de la siguiente manera:

$> gcc ghost.c -o ghost (compilan)

$> chmod +x ghost (le dan permisos de ejecucion).

$> ./ghost (ejecutan)


#------------CODIGO-----------#
#include 
#include 
#include 
#include 
#include 

#define CANARY "in_the_coal_mine"

struct {
  char buffer[1024];
  char canary[sizeof(CANARY)];
} temp = { "buffer", CANARY };
 
int main(void) {
  struct hostent resbuf;
  struct hostent *result;
  int herrno;
  int retval;
 
  /*** strlen (name) = size_needed - sizeof (*host_addr) - sizeof (*h_addr_ptrs) - 1; ***/
  size_t len = sizeof(temp.buffer) - 16*sizeof(unsigned char) - 2*sizeof(char *) - 1;
  char name[sizeof(temp.buffer)];
  memset(name, '0', len);
  name[len] = '\0';
 
  retval = gethostbyname_r(name, &resbuf, temp.buffer, sizeof(temp.buffer), &result, &herrno);
 
  if (strcmp(temp.canary, CANARY) != 0) {
    puts("vulnerable");
    exit(EXIT_SUCCESS);
  }
  if (retval == ERANGE) {
    puts("not vulnerable");
    exit(EXIT_SUCCESS);
  }
  puts("should not happen");
  exit(EXIT_FAILURE);
}

#------------FIN DEL CODIGO-----------#

Si es vulnerable, saldria "vulnerable" je je.
Sino, lo contrario.

Para fixear esto desde Debian/Ubuntu vamos a enfocar solamente en actualizar la libc.

$> apt-get update
$> apt-get install --only-upgrade libc6 -y

(reiniciemos, y luego volver a verificar con el PoC si sigue siendo vulnerable).
El resto de distribuciones, favor de verificar y tratar de actualizar el modulo a la ultima version, y no seria mala idea el kernel tambien. 

Mas informacion detallada directo desde Qualys Community:
https://community.qualys.com/blogs/laws-of-vulnerabilities/2015/01/27/the-ghost-vulnerability
http://blog.vpetkov.net/

domingo, 18 de enero de 2015

Instalando VMware Player en Ubuntu 14.04 // Fixeando issues.

Volviendo a jugar con mi Linux y actualizando el ubuntu a la ultima version 14.04, experimente que el VMware Player (6.0.1 build-1379776), en mi caso el que tomo como ejemplo y uso, tenia ciertos inconvenientes y no bastaba con la instalación desde cero para que funcionara. (Idea basada en la de Garrett Skjelstad's)

Al iniciarlo, el VMware Player arrojaba el siguiente cartel:

"Before you can run vmware several modules must be compiled and loaded into the running kernel"

Por lo que vamos a optar a resolverlo de la siguiente manera.
Una vez bajamos el bundle desde la pagina lo instalamos normalmente:

$> chmod +x VMware-Player-6.0.1-1379776.i386.bundle
$> sudo ./VMware-Player-6.0.1-1379776.i386.bundle

Luego que finaliza la instalación satisfactoria, nos damos cuenta de este error, por lo tanto vamos a crear un archivo "patch" para resolver esto, lo copiamos y pegamos en un archivo de texto y lo guardaremos asi: "filter.c.diff":


> #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
206a208,210
> #else
> VNetFilterHookFn(const struct nf_hook_ops *ops,        // IN:
> #endif
255c259,263
<    transmit = (hooknum == VMW_NF_INET_POST_ROUTING);
---
>    #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
>       transmit = (hooknum == VMW_NF_INET_POST_ROUTING);
>    #else
>       transmit = (ops->hooknum == VMW_NF_INET_POST_ROUTING);
>    #endif


En mi caso lo deje en la carpeta temporal /tmp/filter.c.diff.

Vamos a proceder a aplicar dicho parche sobre un archivo que se encuentra comprimido en la carpeta de modulos del vmware. Hacemos lo siguiente en un terminal:

Nos hacemos root:
$> sudo su

Nos dirigimos al modulo comentado:
$> cd /usr/lib/vmware/modules/source/

Realizamos un backup por las dudas del tar que contiene el archivo a modificar:
$> cp vmnet.tar vmnet.tar.backup

Extraemos del archivo comprimido vmnet.tar el archivo filter.c que vamos a fixear con nuestro filter.c.diff:
$> tar xvf vmnet.tar vmnet-only/filter.c

Fixeamos el archivo filter.c con nuestro archivo que habíamos creado en /tmp/filter.c.diff:
$> patch vmnet-only/filter.c < /tmp/filter.c.diff

Por ultimo, volvemos a compactar el archivo ya fixeado:
$> tar -uvf vmnet.tar vmnet-only/filter.c

Limpiamos la carpeta creada..
$>rm -rf vmnet-only/

Volvemos a ejecutar el VMware-Player y deberia estar resuelto el inconveniente.

sábado, 9 de marzo de 2013

How to Exploit: GDB mas a fondo.. -3-

Vamos a retomar con este tercer paper, y analizar lo que hace nuestro humilde programa codeado en C.

Antes que nada, vamos a eliminar nuestro analizaMe compilado anteriormente, y vamos a volverlo a compilar con un parametro nuevo que es la option flag "-g".
Genera mayor informacion de debug para ser utilizada por GDB.
Let's work!.

$> gcc -g analizaMe.c -o analizaMe (compilas con option flag -g)
$> chmod +x analizaMe (le damos permisos de ejecucion)
$> ./analizaMe (ejecutamos el binario para testear que todo haya salido correcto y recordar que hacia)

La variable contar vale: 0
La variable contar vale: 1
La variable contar vale: 2
La variable contar vale: 3
La variable contar vale: 4


Ok, todo funciono bien por fuera, analicemos que hace por dentro, con lo aprendido anteriormente en GDB.

ACLARACION: Puede que las direcciones de memoria de SUS PCS respecto a las mias en estos ejemplos NO SEAN IGUALES. Y seria algo logico..
Asi que no se preocupen, que podran seguir igual los ejemplos...


$> gdb -q ./analizaMe (abrimos el binario creado con nuestro debugger favorito :))

(gdb) b main  (breakpoint en la funcion principal main)
Punto de interrupción 1 at 0x8048415: file analizaMe.c, line 4. (respuesta del gdb).

(gdb) r (corremos el programa con el comando run o r abreviado)
Breakpoint 1, main () at analizaMe.c:4
4      for(contar=0; contar < 5; contar++)


Bien como vemos, para en el punto de interrupcion que nosotros mismos pusimos en main.
Y como vemos nos adjunta '+ informacion' gracias al option flag -g que agregamos.

Bien, vamos a verificar como esta el panorama..

(gdb) i r $eip
eip            0x8048415    0x8048415 <main+9>  (verificamos la informacion del registro $eip y vemos que apunta a esa direccion).

(gdb) x/3i $eip
=> 0x8048415 <main+9>:    mov    DWORD PTR [esp+0x1c],0x0
      0x804841d <main+17>:    jmp    0x8048438 <main+44>
      0x804841f <main+19>:    mov    eax,DWORD PTR [esp+0x1c]



Como anteriormente vimos, la opción 'i' era la de instrucción. Le decimos a GDB que nos muestre solo las próximas 3 instrucciones a ejecutarse para guiarnos de que esta haciendo el programa y que va a hacer.
Si hicieron la tarea y refrescaron un poco assembler, fundamental para explotar cualquier vulnerabilidad... recordamos también cuando explique algunas instrucciones de assembler, como por ejemplo 'mov'.

A simple vista entonces, GDB nos dice que donde ahora mismo esta parado, va a realizar una operacion en la cual 'movera' el valor de la derecha '0x0' hacia la izquierda en donde tenemos como destino una direccion en memoria (esp+0x1c). Nota: Es muy comun ver este tipo de direcciones, porque si recordamos sabemos que EAX, EBX, EDI, ESI, ESP, etc son registros
y es comun leer ESP+4 o EBP-4 y cosas asi, este caso nos dice que lo va a mover a ESP+0x1c.
0x1c en decimal equivale a 28. Por lo que seria $esp+28.

Si recordamos tambien que el programa paro en nuestro breakpoint en main justo cuando comenzaba el for y nos arrojo esta informacion:
"4   for(contar=0; contar < 5; contar++)"
Podríamos deducir que ese valor 0x0 que va a mover, es el que le dimos en el FOR a nuestra variable llamada 'contar'.

Analicemos esa dirección de memoria que valor contiene en este momento con el programa pausado en nuestro breakpoint:

(gdb) i r $esp
esp            0xbffff270  (En el registro ESP encontramos una direccion de memoria 0xbffff270)

Por lo tanto BFFFF270 + 1C  (ESP+28) = BFFFF28C. (tranquilos, todo eso el debugger lo obvia por nosotros y lo sabe, pero para que entendamos, otra aclaracion for dummys, siempre que veamos 0x12345678 esa '0x' del principio nos indica que es una notacion Hexadecimal, la direccion seria 12345678.)

Bien, volviendo a la practica verificamos con GDB, la siguiente linea:
=> 0x8048415 <main+9>:    mov    DWORD PTR [esp+0x1c],0x0

(gdb) x/x $esp+0x1c
0xbffff28c:    0xb7fc1000

Como vemos nos responde lo que anteriormente les aclare, esp contiene una direccion y esa direccion + 28 (1c) es BFFFF28c, y GDB nos dice que esa direccion contiene el siguiente valor: 0xb7fc1000.

Por lo tanto lo que pasaria ahora es que al ejecutar la siguiente instruccion:
"mov    DWORD PTR [esp+0x1c],0x0" ..ese valor dejaria de existir y pasaria a ser 0x0 con la operacion de mov.

Voy a comentarles un nuevo comando el cual nos permite por asi decirlo, crear temporalmente un 'acceso directo' a una determinada direccion, para no tener que escribirla constantemente y verificar si tiene cambios en su contenido:

(gdb) print $esp+0x1c
$1 = (void *) 0xbffff28c

(Le decimos a gdb que nos cree una variable temporal de la direccion de memoria $esp+0x1c, para accederla facilmente cuando querramos, y gdb nos responde diciendo que se creo la variable $1)

Ahora usaremos el comando 'nexti' para ejecutar  la siguiente instruccion, nexti hace que el programa vaya paso a paso, instruccion por instruccion, luego del breakpoint que pusimos.

(gdb) nexti
0x0804841d    4      for(contar=0; contar < 5; contar++)

Ejecutamos nexti. Veamos si la direccion $esp+0x1c (0xbffff28c)    0xb7fc1000 que contenia valores aleatorios.. ha cambiado.

(gdb) x/x $1  
0xbffff28c:    0x00000000

Efectivamente, se cumplio la operacion 'mov' y movio el valor '0x0' a la direccion de esp+0x1c.
Veamos donde esta parado ahora el registro EIP y cuales son sus siguientes operaciones:

(gdb) x/10i $eip  (le decimos a gdb que nos arroje las proximas 10 instrucciones).



Como vemos en la imagen, EIP apunta a una instruccion en donde hay un JMP (JUMP), un salto el cual tiene como destino la direccion 0x8048438. Que es la 7ma linea de las 10 que pedimos que nos muestre. Le damos a nexti.

(gdb) nexti
0x08048438    4      for(contar=0; contar < 5; contar++)

Vemos que seguimos en el FOR.

(gdb) x/3i $eip
=> 0x8048438 <main+44>:    cmp    DWORD PTR [esp+0x1c],0x4
      0x804843d <main+49>:    jle    0x804841f <main+19>
      0x804843f <main+51>:    leave

Ok, confirmamos que salto a la direccion 8048438 como sabiamos.
Y ahora lo que va a hacer es a comparar mediante la instruccion 'cmp'. El valor 0x4 (4) contra el valor que esta guardado en la direccion [esp+0x1c] (nuestra famosa direccion que podemos acceder temporalmente mediante la variable $1 que seteamos anteriormente).
Como sabemos por la ultima vez que vimos la direccion esa contenia el valor '0'. Por lo tanto comparara el valor 4, contra el valor 0. Exactamente en esta parte del FOR estamos: "contar < 5"
Le damos a nexti...

(gdb) nexti
0x0804843d    4      for(contar=0; contar < 5; contar++)

(gdb) x/i $eip
=> 0x804843d <main+49>:    jle    0x804841f <main+19>

Luego de ejecutar 'nexti' nos lleva a la siguiente instruccion, y si la verificamos con examine para ver donde esta parado EIP, nos encontramos con un JLE. Como recordamos, J.. es sinonimo de JUMP, pero en este caso es un salto 'condicional' que significa JUMP LESS EQUAL.
Y quiere decir que SALTA, SI ES MENOR o IGUAL.....

Como evidentemente esto es cierto, ya que 0 es menor que 4.. entonces salta a la direccion 0x804841f.

(gdb) x/i $eip
=> 0x804841f <main+19>:    mov    eax,DWORD PTR [esp+0x1c]

Estábamos en lo correcto, y salto nomas a la direccion previamente dicha.
Si verificamos las siguientes 10 instrucciones:



Observamos que en la 4ta linea de las 10 solicitadas, hay un "CALL 0x80482F0".
Que es el encargado de llamar a la funcion PRINTF. (La que imprime en pantalla el primer mensaje de "La variable contar vale: 0" que observamos al ejecutar el programa).

Para que se entienda, cuando llegamos a una instruccion donde hay un CALL como en este caso el programa se desvia a una subrutina, es como si fuese una porcion de codigo aparte en la cual se realizan otras operaciones y una vez que se concluyen al final de ese codigo de la subrutina hay una instruccion llamada RET (de return/regreso).
Vean la siguiente imagen..















 Por lo tanto, luego de la llamada a esa funcion, el RET deberia dejarnos justito en la siguiente direccion 0x8048433:













 Ok, siguiendo con nuestro analisis, ya estamos por el final, espero no se hayan perdido.

(gdb) x/5i $eip
=> 0x8048433 <main+39>:    add    DWORD PTR [esp+0x1c],0x1
      0x8048438 <main+44>:    cmp    DWORD PTR [esp+0x1c],0x4
      0x804843d <main+49>:    jle    0x804841f <main+19>
      0x804843f <main+51>:    leave
      0x8048440 <main+52>:    ret

EIP apunta a una instruccion conocida llamada 'add' la cual sirve para 'sumar' dos operandos y lo guarda en el lugar destino, en este caso 0x1 en nuestra conocida direccion de memoria ;).

Le damos a 'nexti'.. y luego verificamos despues de esta operacion si el valor de esa direccion de memoria tuvo algun cambio..

(gdb) nexti
0x08048438    4      for(contar=0; contar < 5; contar++)

(gdb) x/x $1
0xbffff28c:    0x00000001

Efectivamente.. ahora contiene el valor de 1.
Si miramos un poco mas las siguientes dos instrucciones:

(gdb) x/2i $eip
=> 0x8048438 <main+44>:    cmp    DWORD PTR [esp+0x1c],0x4
      0x804843d <main+49>:    jle    0x804841f <main+19>

Ya nos resulta conocida, y es que esta nuevamente comparando el valor de 4 con el ahora 1.
Luego viene el ya explicado JLE - va a saltar si es menor o igual que 4.
Como lo és, salta a 0x804841f. Y así seguiría el loop.. hasta que si seguimos analizando el programa paso a paso con nexti y verificando el valor de la direccion en $1.. llegaríamos a:

(gdb) x/x $1
0xbffff28c:    0x00000005

(gdb) x/i $eip
=> 0x8048438 <main+44>:    cmp    DWORD PTR [esp+0x1c],0x4

(gdb) x/5i $eip
=> 0x8048438 <main+44>:    cmp    DWORD PTR [esp+0x1c],0x4
      0x804843d <main+49>:    jle    0x804841f <main+19>
      0x804843f <main+51>:    leave
      0x8048440 <main+52>:    ret


Luego de ir sumándole 1 por cada loop de imprimir en pantalla, nuestra famosa dirección contiene el valor de 5.
Por lo tanto al siguiente 'cmp', de comparar si 5 es menor o igual que 4? y matemáticamente es negativo, NO se cumpliría el JLE condicional por lo que las siguiente dos instrucciones serian:

(gdb) x/2i $eip
=> 0x804843f <main+51>:    leave
      0x8048440 <main+52>:    ret
      0xb7e344d3 <__libc_start_main+243>:    mov    DWORD PTR [esp],eax
      0xb7e344d6 <__libc_start_main+246>:    call   0xb7e4dfb0 <exit>

(gdb) nexti
[Inferior 1 (process 5324) exited with code 034]

De esta manera finaliza el tercer paper.. y uno de los mas largos.
Gracias :).


#c0nfused - allmenage@gmail.com - http://insecuritynotes.blogspot.com


miércoles, 6 de marzo de 2013

#How to exploit: Un poco de Assembler y GNU Debugger. -2-

#How to exploit: Un poco de Assembler y GNU Debugger. 




Retomando con el paper anterior, y nuestro código de ejemplo, vamos a repasar un poco sobre Assembler y GNU Debugger durante esta segunda parte. Veremos por 'encima' el tema de assembler ya que mi interes no es un tutorial de este, sino repasarlo para introducirlo con el Debugger.

Para invocar al GDB
Utilizaremos el crudo y puro gdb desde la linea de comandos con sintaxis INTEL. 
Para configurar GDB con sintaxis INTEL, vamos a hacer lo siguiente:


$> sudo gedit /etc/gdb/gdbint 

Y luego pegamos al final la siguiente linea y guardamos el archivo:

set disassembly-flavor intel

La sintaxis de intel nos mostrara las operaciones de esta manera en gdb:

instrucciones "[destino],[origen]" 
Por ejemplo: "mov ebx, eax"


En este ejemplo el valor del registro 'eax', sera movido al registro 'ebx'. 
Recordar que las operaciones del origen y destino pueden ser un valor, 
una dirección de memoria, o un registro como en este caso.

Operaciones comunes que veremos en assembler para refrescar memoria:

MOV: Mueve contenido
INC: Incrementa de a 1 el valor
DEC: Resta de a 1 el valor
ADD: Suma  
SUB: Resta
CMP: Compara dos registros o un registro y direccion de memoria.
JMP/JNE etc: Todos los que empiecen con J.. son saltos condicionales e inccondicionales. 
Hay mas pero como dije, son los basicos y el paper no esta orientado a un manual de assembler.


 

# GDB

El debugger es una herramienta que nos permite ejecutar programas y analizarlos. Ya sea para localizar errores o entender un poco mas a fondo que es lo que hace una determinada aplicación.

GDB dispone de un comando muy particular y uno de los mas útiles a la hora de verificar la memoria.
Este comando se llama 'examine' y como su nombre indica, nos sirve para examinar la memoria.
GDB puede examinar detenidamente cada aspecto de la ejecución de un programa, ejecutarlo, detenerlo, verificar los registros, direcciones de memoria, lo que se nos ocurra.
(Lo practico de GDB también es que la mayoría de los comandos se pueden 'abreviar', por ejemplo examine se puede acortar a una simple 'x' y este se reconoce como un comando)

El comando examine, tiene varias maneras de arrojar la información que requerimos ver en una determinada direccion de memoria. Podemos especificar el formato en el que se muestra usando alguna de las siguiente abreviaturas:

x = Muestra el resultado en Hexadecimal
u = Muestra el resultado en Decimal.
o = Muestra el resultado en Octal.
t = Muestra el resultado en Binario.


Veamos un ejemplo con nuestro pequeño programa del paper anterior que adjunto nuevamente:

-----------------------------------------------------
#include <stdio.h>
int main() {
  int contar;
  for(contar=0; contar < 5; contar++)
  {
    printf("La variable contar vale: %i \n", contar);
  }
}

-----------------------------------------------------


$> gdb -q ./analizaMe
De esta manera le pasamos a gdb el binario a debugguear.

(gdb) break main
Punto de interrupción 1 at 0x804840f (en mi caso esto nos responde gdb al poner un break)

Le decimos que genere un breakpoint en la funcion principal "main". Un breakpoint no hace otra cosa que poner una barrera una vez que se ejecuta el programa, le dice al gdb que cuando llegue a nuestro breakpoint el programa se parara obligatoriamente ahi en ese break. Podemos poner varios break, de momento solo haremos uno en la funcion main.

(gdb) run
Breakpoint 1, 0x0804840f in main () (esto nos responde el gdb al encontrar el break que seteamos)

Corremos el programa desde el debugger con run o tambien con una simple 'r' y va a parar en el primer breakpoint que seteamos en la funcion "main"

(gdb) info register

eax            0x1    1
ecx            0xbffff344    -1073745084
edx            0xbffff2d4    -1073745196
ebx            0xb7fc1000    -1208217600
esp            0xbffff2a8    0xbffff2a8
ebp            0xbffff2a8    0xbffff2a8
esi            0x0    0
edi            0x0    0
eip            0x804840f    0x804840f <main+3>
eflags         0x246    [ PF ZF IF ]
cs             0x73    115
ss             0x7b    123
ds             0x7b    123
es             0x7b    123
fs             0x0    0
gs             0x33    51


Este comando "info register" nos permite ver el estado actual de los registros.
Como ven obtenemos un status de todos los registros de ese preciso momento.

(gdb) info register eip
eip            0x804840f    0x804840f <main+3> (respuesta del gdb)

Podemos filtrar a algun registro en particular escribiendolo al lado como en el ejemplo 'eip'.
Ademas, como les conte antes podemos 'abreviar' este comando asi: "i r eip"
Vemos como EIP contiene el valor 0x804840f.

(gdb) x/x $eip
0x804840f <main+3>:    0x83f0e483 (ahora examinamos la memoria a la que esta señalando el registro EIP usando la direccion almacenada en EIP). Vemos que donde arriba EIP contenia '0x804840f', examinamos este registro y contiene lo siguiente: 0x83f0e483.

De esa manera usamos el 'examine' abreviado con la primer 'x', luego le decimos que nos arroje la info en hexadecimal con la segunda 'x'. Y el registro 'eip'. Fijense que en este caso hay que poner el registro luego de un $. A diferencia de el info register que no lo anteponiamos.

Tambien se puede anteponer un numero al formato del comando examine, para examinar varias unidades en esas direcciones objetivos que tengamos. Por ejemplo:

(gdb) x/4x $eip
0x804840f <main+3>:    0x83f0e483    0x44c720ec    0x00001c24    0x19eb0000

Las unidades tienen un tamaño predeterminado de 4 bytes. Conocidas como WORD.
De la misma manera que podemos cambiar el formato que nos arroja el resultado con 'examine' ya sea en hexadecimal, octal, binario o decimal, tambien podemos cambiar el tamaño de las unidades que estamos examinando, agregandole una letra de tamaño al final de la de formato y estos son:

b: byte
h: half-word (2 bytes)
w: word (4 bytes)
g: giant o qword (8 bytes)



Veamos un ejemplo practico:

1) (gdb) x/4xb $eip
0x804840f <main+3>:    0x83    0xe4    0xf0    0x83

2) (gdb) x/4xh $eip
0x804840f <main+3>:    0xe483    0x83f0    0x20ec    0x44c7

3) (gdb) x/4xw $eip
0x804840f <main+3>:    0x83f0e483    0x44c720ec    0x00001c24    0x19eb0000

4) (gdb) x/4xg $eip
0x804840f <main+3>:    0x44c720ec83f0e483    0x19eb000000001c24
0x804841f <main+19>:    0x042444891c24448b    0xe8080484e82404c7


1- Como vemos en el ejemplo uno, le decimos a gdb que nos examine el registro $eip, y nos arroje en 4 unidades, en hexadecimal, y en tamaño byte.
2- En el segundo de la misma manera pero ya con 2 bytes.
3- Igual pero con 4 bytes.
4- Por ultimo igual, pero con 8 bytes.

  • Resumen de este paper
  1. Ya sabemos, compilar un codigo fuente, gcc analizaMe.c.
  2. Sabemos invocar el gdb y pasarle un binario para debuggearlo: gdb -q ./analizaMe
  3. Sabemos que para poner un breakpoint y que se detenga el programa invocamos el comando 'break' + nombre de la función, o dirección en memoria donde queremos que pare.
  4. Sabemos que una vez que para en el breakpoint, podemos verificar el status de los registros mediante 'info register' o alguno en particular como en nuestro caso anterior 'info register eip'.
  5. Sabemos que la herramienta 'examine' nos permite verificar todas la memoria, direcciones y valores que se nos ocurra y arrojar el resultado de la manera que mas comoda nos parezca, como en el ejemplo de 'x/x $eip' para ver el valor que contiene el registro EIP en ese momento y que nos arroje el resultado en hexadecimal.
  6. Sabemos como mostrar por unidades como "x/2x"
  7. Sabemos como mostrar examine en tamaño de unidades b,h,w,g (byte, 2bytes,4bytes, 8bytes).

De momento dejamos acá esta segunda parte, y ya pronto escribo la tercera.
c0nfused.