jueves, 26 de julio de 2012

FRP6: Reto Hacking de Julio – ¡Killo! ¡onde ectá mi clave!

Un nuevo reto de Flu Project, tiempo libre en Alemania... vamos ya!!
Tras descargar el fichero procedo a ejecutarlo. Lo suyo sería ejecutarlo en una máquina virtual preparada y eso, y más viniendo de Flu! xD Pero como la conexión que tengo en este momento va como el naclas, no me he podido descargar VMWare o Vbox y me he tenido que fiar de los chicos de Flu.
Se ve que es el típico "Crack me", como el ordenador en el que estoy trabajando está nuevecito, pues pongo a descargar el Immunity debugger para ver que puedo sacar del fichero. Mientras se descarga mi pequeña vena de consultor y mi impaciencia saltan y dicen: "Psss! Tú!! Chato!! S, ese que está con el jaquin ese del demonio... pero tú no has aprendido nada en los CTFs? Es que no tienes una metodología definida para tratar los binarios?!?! CLARO!!! ES QUE NO LEES LA DOCUMENTACIÓN!!!". Coño! Es verdad!! Siempre que estoy con un binario en un CTF trato de seguir unos pasos que pueden ahorrarme mucho tiempo, y a veces hasta darme la solución.
1.- file -> Para comprobar que de verdad es un binario y no es algún truquillo del que ha puesto el reto y no este tratando de debuggear un jpg.
2.- strings -> A veces la respuesta está entre las cadenas que se muestran (sólo en algunos niveles básicos).
3.- strace, etc -> Para hacerme una idea de qué hace el programa antes de pegarme con el código.
4.- magia -> autoexplicativo.
5.- gdb, immunity, etc.
Pero claro... esto es un ejecutable de Windows... así que tocaba buscar las herramientas que hacen esto en Windows, la primera que encontré fue Strings, de Mr. Russinovich por supuesto lo descargué y me soltó, entre mucha basura:

Espera, que igual hay mucha basura y no lo ves:
Fluprojectmola... fluprojectmola... hmmmm sospechoso!! Osea, que es verdad, Flu Project mola, y mucho, pero eso no puede estar ahí por casualidad así que, a probar... y...
Bingo!!
 key: fluprojectmola
Muy facilillo, y por lo menos me ha tenido entretenido un ratillo en Alemania que nunca viene mal por las tardes. Conclusiones: - Hay que pensar fácil antes de echarse la manta a la cabeza y ponerse con el reversing.
 xgusix@PHT

lunes, 5 de marzo de 2012

Write-up Nuit du hack 2011 Prequals - forensic100


Para no perder comba, y antes de publicar definitivamente los write-up de la última Rooted Arena 2012, pongo la solución a este sencillo reto de la fase de clasificación del CTF de Nuit du hack de 2011.

Forensic100

El archivo README nos cuenta:
$ cat README
On a dumpe la RAM d'une machine sur laquelle tournait un serveur VNC.
Le but est de recupere le mot de passe de ce serveur.
* * *
We have dumped the RAM of a Machine on which was running a VNC server.
The goal is to get the password of that VNC server.
Sabiendo esto, nos ponemos manos a la obra. Una buena herramienta de análisis de volcados de RAM es volatility.
Descargamos y, ayudándonos de la referencia de comandos, vamos sacando información:
$ python vol.py -f forensic100/Desktop/dump.raw imageinfo
Volatile Systems Volatility Framework 2.0
Suggested Profile(s) : WinXPSP3x86, WinXPSP2x86 (Instantiated with WinXPSP2x86)
AS Layer1 : JKIA32PagedMemoryPae (Kernel AS)
AS Layer2 : FileAddressSpace (/home/loopback1984/Descargas/forensic100/Desktop/dump.raw)
PAE type : PAE
DTB : 0xae2000
KDBG : 0x80544ce0L
KPCR : 0xffdff000L
KUSER_SHARED_DATA : 0xffdf0000L
Image date and time : 2011-03-10 13:28:56
Image local date and time : 2011-03-10 13:28:56
Number of Processors : 1
Image Type : Service Pack 2
Con esto sabríamos que estamos frente a un volcado de memoria de Windows XP SP2.
$ python vol.py -f forensic100/Desktop/dump.raw psscan
Volatile Systems Volatility Framework 2.0
Offset Name PID PPID PDB Time created Time exited
---------- ---------------- ------ ------ ---------- ------------------------ ------------------------
0x01fb0020 ctfmon.exe 1664 1580 0x06f10140 2011-03-10 13:02:35
0x01fce938 lsass.exe 696 632 0x06f100a0 2011-03-10 13:02:30
0x01fd1500 svchost.exe 928 684 0x06f100e0 2011-03-10 13:02:31
0x01fe8020 wscntfy.exe 532 1020 0x06f10200 2011-03-10 13:02:59
0x01ff4020 svchost.exe 1020 684 0x06f10100 2011-03-10 13:02:31
0x0201d7e8 spoolsv.exe 1472 684 0x06f10180 2011-03-10 13:02:34
0x02192020 alg.exe 500 684 0x06f101e0 2011-03-10 13:02:58
0x021ea980 winvnc4.exe 1696 684 0x06f10240 2011-03-10 13:09:47
0x021eb558 wmiprvse.exe 1460 860 0x06f10280 2011-03-10 13:28:33
0x022123c0 svchost.exe 1064 684 0x06f10120 2011-03-10 13:02:31
0x022216e8 csrss.exe 608 544 0x06f10040 2011-03-10 13:02:29
0x022356d8 smss.exe 544 4 0x06f10020 2011-03-10 13:02:27
0x02394da0 mmc.exe 1512 1580 0x06f101a0 2011-03-10 13:28:14
0x023cf620 explorer.exe 1580 1564 0x06f101c0 2011-03-10 13:02:34
0x02429720 svchost.exe 860 684 0x06f100c0 2011-03-10 13:02:31
0x024ac9c0 winlogon.exe 632 544 0x06f10060 2011-03-10 13:02:29
0x024df548 svchost.exe 1300 684 0x06f10160 2011-03-10 13:02:33
0x025365b0 services.exe 684 632 0x06f10080 2011-03-10 13:02:30
0x025c8830 System 4 0 0x00ae2000
Aquí vemos el ejecutable y sabemos que se trata de la versión 4.
$ python vol.py -f forensic100/Desktop/dump.raw hivelist
Volatile Systems Volatility Framework 2.0
Virtual Physical Name
0x8066e904 0x0066e904 [no name]
0xe1809008 0x08bfd008 \Device\HarddiskVolume1\Documents and Settings\eleve\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe1986008 0x09f7e008 \Device\HarddiskVolume1\Documents and Settings\eleve\NTUSER.DAT
0xe17a9768 0x08a48768 \Device\HarddiskVolume1\Documents and Settings\LocalService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe179b758 0x08a40758 \Device\HarddiskVolume1\Documents and Settings\LocalService\NTUSER.DAT
0xe1770008 0x085d6008 \Device\HarddiskVolume1\Documents and Settings\NetworkService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe175fb60 0x08410b60 \Device\HarddiskVolume1\Documents and Settings\NetworkService\NTUSER.DAT
0xe13ffb60 0x02f2bb60 \Device\HarddiskVolume1\WINDOWS\system32\config\software
0xe14ab008 0x07023008 \Device\HarddiskVolume1\WINDOWS\system32\config\default
0xe14abb60 0x07023b60 \Device\HarddiskVolume1\WINDOWS\system32\config\SAM
0xe14e4758 0x0369d758 \Device\HarddiskVolume1\WINDOWS\system32\config\SECURITY
0xe12e8288 0x02d65288 [no name]
0xe1035b60 0x02aafb60 \Device\HarddiskVolume1\WINDOWS\system32\config\system
0xe102e008 0x02ab1008 [no name]
En esta última consulta descubrimos los “hives” [2] del registro que están presentes en el volcado, los cuales nos serán útiles para el siguiente paso.
Sabiendo el fallo [3] que esta versión de RealVNC tiene (almacena en el registro las contraseñas con un hash bastante débil), buscamos la clave adecuada en nuestro volcado [4]:

$ python vol.py -f forensic100/Desktop/dump.raw printkey -K "RealVNC\WinVNC4"
Volatile Systems Volatility Framework 2.0
Legend: (S) = Stable (V) = Volatile
----------------------------
Registry: \Device\HarddiskVolume1\WINDOWS\system32\config\software
Key name: WinVNC4 (S)
Last updated: 2011-03-10 13:10:51
Subkeys:
Values:
REG_BINARY Password : (S)
0000 DA 6E 31 84 95 77 AD 6B .n1..w.k
REG_SZ SecurityTypes : (S) VncAuth
REG_SZ ReverseSecurityTypes : (S) None
REG_DWORD QueryConnect : (S) 0
REG_DWORD QueryOnlyIfLoggedOn : (S) 0
Una vez localizada la contraseña almacenada en memoria, procedemos a tratar de descifrarla. Para ello, el paso siguiente más lógico es identificar el tipo de hash. Gracias a Hash ID [5], podemos ver una aproximación:
$ python ../Hash_ID_v1.1.py
######################################################################### # __ __ __ ______ _____ # # /\ \/\ \ /\ \ /\__ _\ /\ _ `\ # # \ \ \_\ \ __ ____ \ \ \___ \/_/\ \/ \ \ \/\ \ # # \ \ _ \ /'__`\ / ,__\ \ \ _ `\ \ \ \ \ \ \ \ \ # # \ \ \ \ \/\ \_\ \_/\__, `\ \ \ \ \ \ \_\ \__ \ \ \_\ \ # # \ \_\ \_\ \___ \_\/\____/ \ \_\ \_\ /\_____\ \ \____/ # # \/_/\/_/\/__/\/_/\/___/ \/_/\/_/ \/_____/ \/___/ v1.1 # # By Zion3R # # www.Blackploit.com # # Root@Blackploit.com # #########################################################################
       -------------------------------------------------------------------------
HASH: DA6E31849577AD6B
Possible Hashs:
[+] MySQL
[+] MD5(Middle)
Least Possible Hashs:
[+] MD5(Half)
-------------------------------------------------------------------------
Tras investigar un poco, descrubrimos que ya hay una herramienta para estos menesteres,  vncpwdump [6]:
$ wine vncpwdump -k DA6E31849577AD6B
VNCPwdump v.1.0.6 by patrik@cqure.net
-------------------------------------
Password: secretpq

Referencias

Un blog interesante sobre el tema: http://gleeda.blogspot.com/

viernes, 14 de octubre de 2011

Instalando, usando y parcheando nemesis

Nemesis es una aplicación de creación de paquetes de red. Nos permite crear a nuestro gusto (dentro de unos límites) paquetes de red e inyectarlos a la red. Actualmente su desarrollo está parado pero sigue siendo una herramienta muy buena para curiosear con las redes y el tráfico, se puede conseguir aquí.

Está construida sobre la libnet, la biblioteca básica de inyección de tráfico (aunque a mi no me llega a convencer del todo, prefiero PF_PACKET).

Ayer quería jugar un poco con nemesis, así que me baje el código fuente y, como especifica la web, busqué por internet el código de la libnet-1.0.2a, que es la que usa nemesis. Libnet, a la hora de escribir estas líneas va por la version 1.1.4 si no me equivoco, y no tiene compatibilidad hacia atrás.

Para instalar la libnet lo propio, ./configure, make, sudo make install. El problema vino al instalar nemesis, ./configure decía que no encontraba la libnet. Probé a jugar con los argumentos --with-libnet-include y --with-libnet-libraries pero no logré que la detectara. Al cabo de un rato me di cuenta que era porque ya tenía instalada la última versión (en los repos de Debian libnet1-dev) y la versión anterior no sobreescribió, ni tampoco soltó ningún mensaje. Esto lo descubrí analizando la salida del sudo make install de la libnet.

Después de cargarme la libnet que tenía y reinstalar la 1.0.2a logré que nemesis se instalara sin problemas y empecé a jugar con él (o sea, a leer manual).

Llegué a un punto en que me encontraba un fallo y no tenía muy claro si era mio o de nemesis. La situación era la siguiente, yo quería crear una pregunta DNS e inyectarla a la red, para ello ejecutaba nemesis de la siguiente manera (preguntando por ulpgc.es):


$ perl -e 'print "\x05ulpgc\x02es\x00\x00\x01\x00\x01"' > query.raw; sudo nemesis dns -dlo -g256 -q1 -P query.raw

Como contrapartida tengo que decir que DNS no está completamente soportado por nemesis y que hay que usar un fichero de payload que contenga parte del paquete DNS bien construido, una pena. Además lo que sí está soportado no lo está correctamente, por ejemplo nemesis-dns tiene el parámetro "-g" para poner el valor de flags que queramos, sin embargo en DNS no existe ningún campo "flags", el RFC 1035 especifíca el flag QR, el campo Opcode, los flags AA, TC, RD, RA, y los campos Z y el RCODE concretamente en lo que nemesis entiende "flags". Los que han trabajado conmigo saben que soy muy estricto con estas cosas... y más con DNS (no Héctor? ;).

Cuando hayamos inyectado el paquete en la red y lo analicemos con wireshark veremos esto:

Si analizamos byte a byte todo el mensaje DNS (RFC en mano) veremos que está bien construido y sin embargo wireshark nos dice "Malformed packet". Mirando la cabecera UDP veremos que el campo Length vale 8, el RFC 768 especifica que el campo Length debe ser el tamaño en bytes de la cabecera UDP más el payload que lleva, en nuestro caso el mensaje DNS. Así pues nemesis o libnet (linux lo descarto) están creando mal el paquete.

Después de un ratillo mirando el código de nemesis llegué al sitio del problema, fichero nemesis-proto_dns.c:

92     if (state == 0)
93     {
94         libnet_build_udp(udp->uh_sport, udp->uh_dport, NULL,0
95                 pkt + link_offset + LIBNET_IP_H);
96     }

Es aquí donde nemesis le pide a la libnet que cree la cabecera UDP, sin embargo siempre le dice que no hay payload (NULL, 0) aunque no sea así. Más tarde nemesis si que pone el payload pero ya el campo Length de UDP estará mal generado. La solución es cambiar estas líneas por:

92     if (state == 0)
93     {
94         libnet_build_udp(udp->uh_sport, udp->uh_dport, NULL, LIBNET_DNS_H + pd->file_s,
95                 pkt + link_offset + LIBNET_IP_H);
96     }

Recompilamos y ya nemesis generará paquetes DNS sin el bug antes mencionado. He escrito un mail al autor (Jeff Nathan) con el parche, lo que no estoy seguro de si lo verá ya que como comentaba al principio, nemesis lleva bastantes años parados, una pena, es una buena herramienta.