sábado, 12 de diciembre de 2009

RootedCon

Seguro que ya lo habéis escuchado pero por si acaso os aviso.

Los días 18 (jueves laborable), 19(viernes festivo) y 20 de Marzo se va a celebrar la RootedCon en Madrid.

¿Qué es la RootedCon? Cito:

Lo primero de todo, el congreso se compondrá de conferencias altamente técnicas. No queremos humo; buscamos fomentar el conocimiento, y por ello no nos contentamos con saber que existen “cosas”: queremos saber cómo son y por qué funcionan así.

Resumiendo: 3 días escuchando a los mejores (sexy pandas incluidos) hablar sobre temas muy interesantes por el ridículo precio de 25€ si eres estudiante y te registrar antes de enero. Realmente increíble. Registro y precios.

Yo asistiré con algún compañero a pasar 3 días a tope.
Por allí nos veremos, ¿no?

viernes, 11 de diciembre de 2009

Curioso deface

No es el típico HACKEY BY -[@Turk15h H4ck3r]-

 
Que pongas el microfiltro en el teléfono so plasta!

El tipo se cargo advance.com.ar seguro que fue cosa de los DNS.

Visto en segu-info.

martes, 1 de diciembre de 2009

Visual Studio Powa!

Problema:
Tengo una mega-lista de 150 valores sacados del HTML de una página:

clip_image002

Y quiero convertirlo en una función de C# que me transforme el texto al valor. Pues nada más fácil que aprovechar la funcionalidad de Visual Studio de reemplazar, con las expresiones regulares y las “Tagged Expresion”:

clip_image004

Y así esto:

clip_image006

Se convierte en esto otro:

clip_image008

Hay que corregir algún fallo, como esos espacios en el case, pero nos hemos ahorrado un buen tiempo, ¿no?

Esto es muy útil cuando deseamos reformatear un texto, por ejemplo extraer los pares de valores entre corchetes, cambiarlos de lugar y añadir unas comas. Seguro que alguna vez os es útil.

Saludos!
Más información sobre el tema.

martes, 3 de noviembre de 2009

Programa para obtener la IP pública

Es un coñazo andar consultando páginas como cualesmiip para saber tu IP pública. Por eso me he creado un sencillo programa para que muestre la dirección IP por consola o la copie al portapapeles .

image

Añado el ejecutable a mi directorio de herramientas básicas, incluido en la variable PATH y a funcionar:

image Falsa IP.

El –c es para que lo copie al portapapeles.

Os lo subo por aquí por si lo queréis tener. Un saludo!

martes, 15 de septiembre de 2009

¿Infectar código fuente?

Supongamos que estaba haciendo un programa en C# con Visual Studio en el que quería poner unos bonitos botones rosas:

gogirls

En realidad es un control personalizado en el que he sobrescrito el método OnPaint, algo así:

image[Offtopic: Molaría poner en el blog algo que colorease el código fuente, pusiera el número de línea, unas scrollbars… ¿se podrá en blogspot?]

Hasta aquí todo mas o menos normal, pero es entonces cuando me fijo que el IDE, Visual Studio, en tiempo de diseño está mostrando el botón exactamente como quedaría una vez compilado y ejecutado el programa.

image

¿Pero como es posible? En tiempo de diseño Visual Studio no puede saber como quedará el botón que yo pinto manualmente, a no ser… que esté ejecutando el método OnPaint para ofrecer al programador una previsualización del formulario tal y como quedará en tiempo de ejecución.

Es decir Visual Studio va a ejecutar lo que halla en el método OnPaint de los controles personalizados que tengamos en el formulario que estemos previsualizando en ese momento.

¿Y si colocásemos en el método OnPaint código malicioso? Un developer que abriese el proyecto y visualizara el diseño del formulario ejecutaría sin saberlo el malvado código malicioso. Esto sería perfecto para infectar a un programador del que sabemos que es muy probable que abra confiadamente el proyecto que le pasemos y trastee felizmente con la interfaz.

Desde aquí podéis bajaos un proyecto de Visual Studio que tras ser abierto y visualizado el form1.cs, se ejecutará la calculadora de Windows sin necesidad de compilar ni ejecutar el proyecto. Nota: Uso el registro “como un mutex” para que solo se ejecute una vez la calculadora.

image

Como he puesto que se ejecute la calculadora de Windows podía haber puesto que se ejecute un binario incluido en el proyecto o que lo descargue y ejecute o … algo mas interesante.

El código malicioso podría buscar todos los proyectos de Visual Studio e insertar en ellos un botón personalizado de 0x0 con un método OnPaint que haga exactamente lo mismo (buscar todos los proyectos e infectarlos, etc…). Y así infectaría todos los proyectos de VS de ese ordenador. Esto en un desarrollador que comparta sus códigos mediante SVN, SourceSafe o CodePlex, SourceSafe podría causar estragos. Sería como un virus en el código fuente.

Y esto me recuerda al virus W32/Induc comentado por aquí, por acá, por allá y por mas allá. Este virus infecta el compilador de Delphi, modifica una dependencia incluida en todos los ejecutables, de modo que cada ejecutable compilado con ese ordenador queda infectado y trata de infectar el compilador de Delphi de los usuarios que lo ejecuten.

¿Sería mas peligroso esto del código fuente? Le faltaría ya de paso no solo infectar el código fuente sino también los ejecutables generados como hace Induc y de paso una vez infectado el equipo eliminar del código fuente las rutinas maliciosas.

Por último quiero destacar que el hecho de que seamos capaces de ejecutar código sin compilar el proyecto tampoco es un gran logro, al fin y al cabo seguramente se conseguiría el mismo efecto insertando la rutina normalmente como parte del programa y esperando a que el programador lo compile y ejecute.

PD: No me gustan los botones rosas con bordes negros solo era un suponer ;)

jueves, 11 de junio de 2009

Solución reto Pwtent Pwnables 100 Defcon 17 Quals

Que nombres mas raros Dios Santo. El pasado finde 6,7 de Junio se realizó una clasificación para asistir a la competición CTF, Capture The Flag, de la Defcon 17, en Las Vegas. Consiste en un montón de retos/pruebas/desafíos informáticos que hay que superar en equipo y así los 10 primeros van a Las Vegas para ver quien es el mejor del mundo. El nivel , altísimo. Suena guay, ¿verdad?

Mi querido Pedro Laguna nos invito a que nos apuntásemos con él a ver que se movía por ahí. Así que ahí estábamos el sábado 6 de madrugada Pedro, Manu (un compañero) y yo cagándonos en lo mal que funcionaba ese applet que era el panel de puntuación.

DefconFinal

Las pruebas eran muy raras y no se daban demasiadas indicaciones sobre como superarlas, es parte del juego ;)

Yo me tope con una especie de ejecutable que pedía un serial, ummm eso sonaba bien, al menos podía abrirlo con OllyDbg e intentar hallar un serial. Aquí os lo cuelgo A continuación os cuento como lo resolví.

Nada mas abrirlo veo una consola que no hace nada, mas que dejar un puerto a la escucha:

TCP 0.0.0.0:5832 0.0.0.0:0 LISTENING 1976

Me conecto con netcat y me pide un serial ¿?

image

Perfecto, lo abro con el OllyDbg, busco las cadenas referenciadas en el código:

image

Ahí está la cadena “Well done!” la cual en teoría tiene que aparecer cuando introduzca el serial bueno. Perfecto: Follow in Disassembler:

image

Mira justo un par de instrucciones antes de mostrar ese mensaje se hace una comparación de cadenas, strcmp, guay, pongo un breakpoint allí, veo lo que se está comparando y reto solucionado.

Pero no funciona…algo raro pasa, pongo otro breakpoint cuando directamente me muestra el mensaje de serial erróneo y tampoco se detiene.

Así que voy ejecutándolo desde el principio poco a poco para ver si tiene alguna protección o que… Veo una llamada a accept, me conecto con netcat y entonces me encuentro que llega a esta función:

image

Aja! Está creando un nuevo proceso por cada petición, es ese proceso el encargado de verificar si nuestro serial es correcto o no. Así que necesito abrir con OllyDbg el nuevo proceso, el proceso hijo, no este.

Resumen: al ejecutar el exe este se queda a la escucha en el puerto 5832 y por cada nueva conexión crea un proceso hijo que se encarga de recibir y verificar el serial que introducimos. Así que era normal que cuando ponía breakpoints en el proceso inicial no se detuvieran ahí nunca.

Tuve algunos problema iniciales para hacer Attach con OllyDbg sobre el proceso hijo, pero tras pensarlo un rato (dormir), me doy cuenta de que es de lo mas fácil, no hay que hacer nada :) Simplemente ejecutar el programa inicial, conectarnos por netcat y entonces hacer Attach sobre el proceso hijo.

image

En estos momentos el programa está esperando a que introduzcamos texto desde el netcat, así que pongo un breakpoint en recv, escribo algo en la consola donde tengo el netcat a la espera y llego a esta zona de código:

image

Podemos ver dos bucles donde se reciben bytes hasta encontrar el salto de linea, \n, y entonces se comparan ambos.

image

Así que en realidad se reciben dos líneas, claro! Ya decía yo que eso de dar dos veces al enter no era muy normal :) Estas dos líneas se comparan sin mas ¿? Aquí hay truco…vamos a a probar:

image

Uy que raro…es entonces cuando recapacito, ¿pero en serio que nos piden un serial? Pues no, lo que nos piden es que les petemos, si es que hay que leer el enunciado detenidamente antes de lanzarse a abrir el OllyDbg en cuanto vemos un exe…

image

Efectivamente peta, ¿será un Stack Buffer Overflow? Vemos donde está guardando el contenido de la primera línea introducida:

image

Guarda el contenido de la primera línea en 22FDC0 (fijaos que esta es la segunda vez que pasa por bucle, en la primera yo no estaba ni “Attacheado” al proceso).

Ahora mirad en el contenido de la pila:

image

Uhhh bonito Stack Buffer Overflow. Escribiendo 64 bytes sobrescribimos la dirección de retorno de la función actual haciendo que cuando termine salte a donde queramos, esto pinta bien. Ahora solo falta un sitio donde meter las instrucciones que queremos que se ejecuten, la shellcode.

El primer bucle tiene una limitación:

image

No deja escribir mas de 64 bytes, que casualidad ¿no? Pero teníamos dos bucles, el de la primera y el de la segunda línea.

El segundo bucle se guarda en la dirección 004099F8:

image

Y permite escribir todos los bytes que queramos hasta encontrar el salto de línea, así que nos sirve perfectamente para meter ahí la shellcode. Pero hay que tener cuidado, fijaos de nuevo en la situación de la pila en el primer bucle cuando íbamos a sobrescribir el valor de retorno, la dirección 0022FDEC (local.3) contiene el valor 004099F8:

image

Si nuestro primer buffer sobrescribe ese valor el segundo bucle intentara escribir donde le hallamos dicho. A nosotros no nos interesa modificar ese valor, queremos dejarle como está, sobrescribir la dirección de retorno y escribir en el segundo buffer la shellcode.

Voy probando diferentes valores hasta dar con la primera línea a introducir:

image

64 bytes que dejan intacta la variable utilizada por el segundo buffer y que sobrescriben la dirección de retorno para que al finalizar la función el programa salte al segundo buffer donde meteremos directamente la shellcode.

Para la shellcode use la página de metasploit, que poco h4x0r soy, ¿no?:

image

Solo hay que tener cuidado con que la shellcode no haga uso del carácter de salto de línea, 0x0A ya que nuestra función busca ese carácter para buscar el fin de las distintas líneas.

Desde la página de retos se suministraba esta dirección para ser atacada:

pwn2.ddtek.biz

Probé con varias shellcodes, hasta probar una para FreeBSD que me funcionó perfectamente.

nc pwn2.ddtek.biz 5832 <>

Argumento pasado:

image

La shellcode utilizada era una bind shell, vamos que deja un puerto a la escucha en el puerto 6969, pruebo y...eureka:

nc pwn2.ddtek.biz 6969 adsfadsf adsfadsf: not found pwd /usr/home/cabernet ls cabernet.exe key start_server.sh cat key Hacker Joe Where Are You?

Esta última cadena era la necesaria para superar el reto, 100 puntos. Al finalizar el maratón 800 puntos logró alcanzar mi equipo, McLoving, que buen nombre :D

Los Sexy pandas, un gran equipo español, terminaron terceros. Que genios. Suerte en Las Vegas fieras!

Si queréis aprender mas sobre el tema: Smashing The Stack For Fun And Profit

martes, 21 de abril de 2009

La gorda FOCA

Todo empezó cuando me liaron con una aplicación destinada a extraer y eliminar los metadatos de documentos OpenOffice, OOMetaExtractor.

“La cosa” se fue descontrolando, al poco tiempo ya trataba documentos de Office desde la versión 97 a la 2007 y mas tarde PDFs. Pero la cosa nostra, no quedó ahí. Pensamos que sería cómodo que buscara y descargara documentos usado los buscadores Google y LiveSearch. Y así se hizo.

Una vez que la bola de nieve empieza a rodar…no hay quien la pare. El programa pintaba bien, así que requería una buena interfaz, iconos para todo, menús con todo tipo de opciones, colores y sabores.

pdfMirad cuantos colorines !!!

¿Y qué es de un programa sin un buen nombre? Como todo buen nombre primero se eligen las siglas, que sean impactantes, por ejemplo FOCA, un nombre fácil de recordar aunque no demasiado descriptivo... El significado de las siglas vino, creo recordar, acompañado de un buen vino , Fingerprinting Organizations with Collected Archives.

Aun quedaban mejoras por hacer. Pensamos que sería cómodo bajarse todos los documentos de una web, por ejemplo la casa blanca, sacar todos los usuarios de los metadatos, ponerlos todos juntos para guardarlos en un fichero y usarlos por ejemplo para hacer fuerza bruta o guardar los emails para “anunciar” nuestra potenciada viagra > Mas código, mas menús, mas ventanas.

Durante todo el proceso, Chema Alonso y Enrique Rando probaron insaciablemente todas las opciones y examinaron los metadatos extraídos proponiendo muchas mejoras y metadatos extra. Así que se fueron incorporando las versiones antiguas, el historial de edición y la información EXIF de las imágenes incrustadas > Mas código, mas menús , mas ventanas.

doc2La cosa apunto de explotar

Ya por último decidimos que sería interesante coger todos los documentos editados por un mismo usuario y juntar los metadatos considerándolos del mismo equipo, así poder interpretar mas fácilmente toda la maraña de metadatos obtenidos. Así surgió la opción Analize Metadata > Mas y mas código.

La cosa llego muy lejos, hace unos días Chema Alonso y Enrique Rando hablaron en la BlackHat Europe sobre la herramienta y los metadatos. Y con motivo de tan especial ocasión la FOCA fue liberada: Descarga, necesitáis .NET Framework 3.5, preferiblemente en Windows Vista o Windows Server 2008 .

Manual de usuario (en construcción) (las imágenes fueron robadas de él): FOCA, manual de usuario I de IV FOCA, manual de usuario II de IV FOCA, manual de usuario III de IV FOCA, manual de usuario IV de IV

Mas información relacionada

Tened cuidado, suele morder a los desconocidos.

jueves, 16 de abril de 2009

¿Fallo de programación en mod_evasive?

mod_evasive es un módulo de apache que sirve para “esquivar” ataques de denegación de servicio. Detecta cuando un cliente está realizando excesivas peticiones y bloquea temporalmente su acceso o realiza otra acción configurable.

Hay muchos “manuales” para instalar y configurar mod_evasive. Lo mas importante son los valores configurables en httpd.conf para definir su comportamiento, por defecto viene configurado así:

DOSHashTableSize 3097 DOSPageCount 2 DOSSiteCount 50 DOSPageInterval 1 DOSSiteInterval 1 DOSBlockingPeriod 10

Significando de DOSPageCount y DOSPageInterval, sacado de emezeta.com:

  • DOSPageCount / DOSPageInterval: Máximo (umbral) que se debe alcanzar para ser incluído en la lista de bloqueados. En este caso el objetivo será una página concreta. (Entiendase como «Máximo de DOSPageCount páginas en DOSPageInterval segundos»).

    Por defecto el máximo está establecido a 2 páginas por segundo.

Genial, es muy útil, aunque no es raro que un cliente legítimo realice en un momento puntual 2 peticiones a una misma página en menos de un segundo, abriendo pestañas, algún script de recarga, o un php de acceso a imágenes…

Me parece mucho mas adecuado que bloquee una IP cuando ese índice de peticiones por segundo se perpetua en el tiempo. Por ejemplo 20 peticiones en 10 segundos, 2 peticiones por segundo durante 10 segundos (si, aprendí a multiplicar recientemente).

Así que establecí los siguientes valores en la configuración de mod_evasive:

DOSPageCount 20 DOSPageInterval 10

apache reload y a gozar.

Al rato vi como se estaban bloqueando IPs que en principio no deberían ser bloqueadas. Verifiqué el access_log de apache y efectivamente, estaban realizando como mucho 5 peticiones cada 10 segundos. Un valor 4 veces menor(incluso sé dividir), muy lejano al máximo de 20 peticiones cada 10 segundos que hemos configurado. Lo verifiqué manualmente y en efecto, realizando una petición cada 5 segundos a las 20-21ava petición mod_evasive me bloqueaba.

Probé con diferentes valores, rango mas amplios, reiniciar apache, reinstalar y nada, esa cosa no funcionaba como decía. Maldita sea !

Estaba claro, yo no estaba entendiendo bien que significaban esos valores, porque sería muymuy raro que un módulo tan usado fallase en algo tan básico, ¿no? Así que me dispuse a leer la documentación oficial, el mítico README, que decía mas o menos lo mismo que lo que pegue arriba. Así que se me ocurrió la locura de echar un ojo al código fuente: “quizás ahí este explicado o vea una formula que explique su funcionamiento”.

El código, localizado en mod_evasive20.c, se puede entender, al menos la parte donde hace la verificación de si una IP está atacando o no.

image

Resumen de los valores de las variables al realizar la comprobación:

  • t: Tiempo actual en segundos. Inicializado como: time_t t = time(NULL);
  • n->timestamp: n es una tabla que se usa para relacionar URL-Numero de peticiones-Timestamp. timestamp es una “marca de tiempo” que se establece en la primera petición y es actualizada cada DOSPageInterval segundos, en nuestro caso cada 10 segundos.
  • page_interval: Tiene el valor establecido en httpd.conf, DOSPageInterval. Intervalo en segundos durante el cual se medirá si se ha alcanzado el límite de peticiones. Como acabamos de decir, 10 segundos en nuestro caso.
  • n->count: Número de peticiones realizadas a una misma página web, el valor se resetea cada DOSPageInterval segundos, en nuestro caso cada 10 segundos.
  • page_count: Tiene el valor configurado en httpd.conf, DOSPageCount. Máximo número de peticiones que se puede realizar a una misma página web. En nuestro caso 20.

Así podemos ver como la primera parte de la condición mira si desde el timestamp hasta el momento actual han transcurrido menos de 10 segundos, si esto ocurre pasa a la segunda parte de la condición que verifica si el número de peticiones realizadas es mayor que el máximo numero de peticiones permitidas.

Todo perfecto en teoría, pero a mi me funcionaba mal, así que hice un debug chapucero usando el macro LOG que añade un mensaje al log del sistema /var/log/syslog.

image

Recompilamos ./apxs -cia mod_evasive20.c Recargamos la configuración de apache /etc/init.d/apache reload

Y empezamos a hacer una petición cada 5 segundos mientras miramos el syslog tailf –f /var/log/syslog | grep mod_evasive

image *Paint art

Como esperábamos cada 5 segundos se realiza una petición, hasta alcanzar las 6 peticiones de un máximo de 20. Pero esto sigue hasta que…

image

Pero como es posible, está ****** nos banea con 20 peticiones en 200 segundos !!! El error parece estar en que nunca resetea el n->count y en teoría cada 20 segundos debería resetearlo. Veamos en el código en que parte lo resetea…

image

Cuando el tiempo actual en segundos, t, menos la marca de tiempo inicial, n->timestamp, es mayor que el intervalo de tiempo, 10, se resetea n->count. Es decir, una vez pasados los 10 primeros segundos debería resetear el contador n->count, pero en los “logs” vemos que hay un problema, n->timestamp se actualiza constantemente con el valor de la anterior petición (Señalado en azul).

La idea es que este timestamp se actualice solo cuando el contador se pone a 0

image *Paint genius

Recompilamos, reiniciamos y vemos el log

image

Esto ya tiene mejor pinta, el contador n->count se resetea cada 10 segundos y el valor n->timestamp también. De modo que ahora si, solo bloqueará a aquellas IPs que hagan mas de 20 peticiones en 10 segundos.

Este mismo cambio hay que realizarle otra vez en la comprobación de páginas del sitio visitadas, situado unas pocas lineas mas abajo.

He intentado contactar con el autor de este modulo, para que me verificase que era un fallo y no una mala interpretación mía. Pero el modulo es de hace 4 años así que posiblemente el autor haya cambiado de correo.

mod_evasive es muy conocido y usado, es increíble que nadie haya notado que no funciona como debe o que no se hayan mirado el código fuente, de ahí mis dudas sobre si no estaré equivocado yo. Aunque por otra parte en la configuración por defecto se usa un valor de DOSPageInterval de 1 y entonces la continua actualización de n->timestamp no entorpece el resto de comprobaciones, ya que solo se actualizará cada segundo (no tiene precisión de milisegundos) y si se realizan X peticiones por cada segundo serán detectadas correctamente.

Editado a 02/02/2011 A continuación pongo el parche que ha dejado Antonio en los comentarios:

El parche es este: --- mod_evasive20.c.orig 2005-10-08 21:01:18.000000000 +0200 +++ mod_evasive20.c 2011-02-02 18:00:25.000000000 +0100 @@ -168,9 +168,9 @@ /* Reset our hit count list as necessary */ if (t-n->timestamp>=page_interval) { n->count=0; + n->timestamp = t; } } - n->timestamp = t; n->count++; } else { ntt_insert(hit_list, hash_key, t); @@ -190,9 +190,9 @@ /* Reset our hit count list as necessary */ if (t-n->timestamp>=site_interval) { n->count=0; + n->timestamp = t; } } - n->timestamp = t; n->count++; } else { ntt_insert(hit_list, hash_key, t); lo copiamos y pegamos en un fichero, por ejemplo mod_evasive.patch, dentro del directorio mod_evasive, aplicamos el parche con: patch -p0 < ../mod_evasive.patch

miércoles, 15 de abril de 2009

Usar debug para generar ficheros ejecutables

Supongamos que hemos conseguido explotar satisfactoriamente un fallo remoto en un sistema operativo Windows y tenemos acceso mediante una shell a dicho sistema. O Dicho de otro modo, hemos usado Metasploit para petar el ordenador del vecino y ahora tenemos un cmd de su sistema :|

El siguiente paso será ejecutar una herramienta de administración remota para “asegurarnos” la permanencia en su sistema. Pero bueno solo tenemos una shell, tendremos que descargarnos el RAT, ¿no?

Para ello se podría usar ftp.exe, si pero no siempre es posible, quizás el sistema no nos deje (permisos) o el firewall no nos permita acceder a ningún FTP.

A primera vista se nos puede ocurrir usar el comando echo para escribir valores hexadecimales sobre un fichero de salida, pero el comando no soporta valores hexadecimales como entrada, que raro, ¿no?

Lo que se puede usar es el comando echo para generar un fichero que pueda interpretar correctamente el comando debug y así generar el archivo que queramos. Con estos dos comandos podemos crear cualquier fichero en el sistema. Perfecto para generar un troyano o mejor un mini-downloader que baje el troyano.

Aquí se explica detalladamente como conseguirlo, con imágenes explicativas !

image

Resumiendo, hay un par de programas que una vez seleccionado un fichero te crean un bat con todos los echos y comandos necesarios para generar dicho fichero en un sistema remoto. Después, ya solo sería cuestión de tener paciencia e ir ejecutando cada línea de dicho bat en el sistema remoto.

Programas:

miércoles, 8 de abril de 2009

Solución al reto 1 de Panda (III parte, las dos comprobaciones)

-------------------------------------------------------------------- Solución al reto 1 de Panda (I parte, fracaso absoluto) Solución al reto 1 de Panda (II parte, FPqué!?) Solución al reto 1 de Panda (III parte, las dos comprobaciones) -------------------------------------------------------------------- En anteriores episodios, localizamos dos zonas vitales para que nuestro serial fuera tomado como valido. Primero una comprobación, un salto que nos lleva a la zona de password incorrecto, “bad!” y una variable que tiene que tener un determinado valor, 4, para mostrar el mensaje correcto, “yes!”.

Empecemos por la primera comparación.

image

Empezamos desde el salto condicional JNZ resaltado en amarillo hacia atrás. JNZ, realiza el salto cuando el flag Zero no está activado, vale 0. En nuestro caso esto es así.

image Por esta razón el salto es tomado y llegamos a la zona de printf “bad!” :(. Podríamos cambiar el flag manualmente a 1 o invertir el salto y seguir la ejecución, pero nuestro objetivo es conseguir un password correcto no forzar a que muestre el mensaje correcto.

Así que manos a la obra, hay que analizar las instrucciones anteriores al JNZ.

La instrucción inmediatamente anterior al JNZ es XOR AH, 40 Queremos que el flag zero se active, así que esa instrucción tiene que dar como resultado 0, por ello AH debe valer 40 en ese punto.

Vamos a ir analizando mas rápidamente el resto las instrucciones, tened en cuenta que se hace en orden inverso, primero las que se ejecutarán últimas:

  • AND AH, 45: Quedamos en que AH tenía que valer 40 tras esta operación, si se le va a aplicar un “AND 45”, AH tiene que tener el bit 6 activado (correspondiente al segundo 4) y los bits 2 y 0 desactivados (correspondientes al primer 5). Puede resultar confuso, si, mirad esta representación para aclaraos:image
    En los bits marcados con x da igual el valor que tengan ya que el AND cuando se le aplica un 0 siempre devuelve un 0 independientemente del otro bit.
  • FSTSW AX: Esta instrucción guarda en AX el valor de los bits de condición de la FPU, mas info. ¿Qué diablos son esos bits? Pues los que indican el resultado de una comparación de dos floats. Puede verse en los registros.
    image
    El valor de FST se guarda en AX. Recordad que antes las operaciones se han hecho sobre AH (la parte alta del registro AX), que descartamos la parte baja AL, 8 bits. Así que queremos que el bit 6+8, 14, del FST valga 1 y que los bits 2+8,10 y 0+8,8 valgan 0. Ollydbg puede confundir con su descomposición del registro FST. El contenido desglosado de FST es el siguiente.
    imageComo vemos el bit 14 corresponde a el bit C3(Z) de los Condition Code. El bit 10 al C2(C) y el bit 8 al C0(S). imageCuando estos bits se activan justo como requiere el programa significa que la FPU ha comparado dos número que eran iguales. Seguimos con las instrucciones previas, omitiendo aquellas que no hagan nada interesante:
  • FUCOMPP: Compara los números de la FPU ST(0) y ST(1)
    imageAsí que esos dos números tendrían que ser iguales, ¿no?
  • FXCH ST(1): Intercambia los registros ST(0) y ST(1)
  • FILD WORD PTR SS:[ESP]: Carga en ST(0), el tope de la pila de la FPU, el valor apuntado por la cima de la pila, y si hubiese algo en ST(0) lo desplaza a ST(1).
  • PUSH EAX: El valor que acababa de cargar en la FPU es EAX, que lo mete en la pila previamente.
  • CBW: Convierte un byte, AL, en palabra, AX, rellenando con ceros…pues fale.
  • MOV AL,BYTE PTR SS:[EBP-21]: Mueve a AL el carácter introducido, ¿que cómo sabemos que en EBP-21 estaba el carácter? Acudiendo a nuestro scanf inicial. image
  • FMULP ST(1),ST: Se multiplican ST(0) y ST(1)
  • FLD [LOCAL.8]: Carga en la pila de la FPU el %f2
  • FILD DWORD PTR SS:[ESP]: Carga en la FPU el valor de la cima de la pila
  • PUSH EAX: Pone en la pila EAX
  • MOV EAX,[LOCAL.12]: Pone en EAX la variable LOCAL.12, que aun no sabemos que es…
  • FISTP [LOCAL.12]: Guarda en LOCAL.12 el valor ST(0)
  • FLD [LOCAL.7]: Pone en ST(0) %f1

Recapitulemos:

  • Se carga en la FPU %f1
  • Lo saca y lo vuelve a meter, así me gusta nena, pero sigue estando %f1 en la FPU, ST(0)
  • Se carga en la FPU %f2 en ST(0), ahora %f1 está en ST(1) Para %f1 = 1 y %f2 = 97 image
  • Se multiplican estos dos valores
  • Mete en la FPU el valor ASCII del carácter %c
  • Compara los dos números

De modo que un password como esté: “1-1-97-a” debería superar la primera condición. 1*97 == ASCII(‘a’)

Probémoslo, ponemos un breakpoint antes del maldito JNZ, introducimos el posible password vemos que camino toma el salto.

image

JNZ no salta (la flecha esta de color gris), por lo que llega al JMP que le aleja de el printf que nos dice que el password era incorrecto. Perfecto !!

Uff, esto de analizarlo al revés es una locura. Pero nos ahorra analizar algunas instrucciones aunque ahora no nos ha servidor de mucho después nos ahorraremos un buen cacho de análisis.

Pasamos al segundo requisito para que un password sea correcto. que el desplazamiento visto en el capítulo anterior, almacenado en LOCAL.4, valga 4. Recordamos…

image

Buscamos donde se asigna una valor a LOCAL.4, se encuentra casi al principio, cerca del scanf.

image

Se le asigna el valor de EAX, justo después de de esa función. Esto es típico, cuando una función devuelve un valor, realmente se almacena en EAX. Hay que fijarse que la función solo se le pasan %f1 (argumento 3) y %d (argumento 1) así que en principio no usará el resto de números introducidos.

Entramos en la función, la seleccionamos y pulsamos intro. Una vez dentro de la función vamos al final de está. Tracearemos desde el final al principio buscando que hace falta para que EAX valga 4.

image

EAX vale lo que contenga LOCAL.18. A esta instrucción de puede llegar desde tres lugares. Desde la instrucción justamente anterior, MOV [LOCAL.17], EDX. Y desde dos saltos. Para localizarlos seguimos la línea roja de la muerte.

image

Desde cualquiera de los dos saltos LOCAL.18 vale 0 y por lo tanto EAX también. Esto no puede ocurrir ! Ponemos un breakpoint en los dos saltos, con el fin de determinar si alguno de los dos es tomado. Ejecutamos el programa e introducimos “1-1-97-a”. Vemos que en el primer salto ni se para, una comparación anterior hace que no se llegue hasta ahí. En el segundo alto si se para y…salta, por lo que LOCAL.18 valdrá 0, EAX 0 y … “bad!”.

image

Bueno está claro que la culpa es del JE(Jump if Equal) anterior si hubiese sido “Equal” hubiese ignorado este JMP maldito.

Analizamos las instrucciones anteriores al JE.

image

A destacar que EAX y LOCAL.16 tienen que valer lo mismo. EAX resulta de la suma de EAX y EBX. Ponemos un breakpoint en ADD EAX, EBX para observar que valores toma con diferentes passwords.

image

Sea cual sea el password introducido, EAX siempre vale 1 y EBX 3. Así que EAX terminará conteniendo el valor 4 (EAX += EBX).

Recordamos que antes hemos quedado en que EAX y LOCAL.16 tenían que valer lo mismo, y EAX sabemos que siempre vale 4. Así que buscamos cual es la última asignación realizada a LOCAL.16.

image

La encontramos ahí, tras analizar las instrucciones vemos como LOCAL.16 es cargada a partir de LOCAL.7 la cual es cargada a partir de ARG.3, que como hemos visto al entrar a esta función es %f1.

Ahora con todas las piezas disponibles, montamos el puzzle. EAX y LOCAL.16 tenían que valer lo mismo, EAX siempre valía 4, así que LOCAL.16 tiene que valer 4 y LOCAL.16 coge el valor de %f1. Así que %f1 tiene que valer 4.

Pero no olvidemos que %f1*%f2 = %c 4*%f2 = %c Si %f2 vale 25 por ejemplo 100 = %c = ‘d’

Pues ahí lo tenemos. El primer número, %d, no se ha usado para nada, así que le damos un valor aleatorio. %f1 tiene que valer 4. %f2 le damos el valor de 25. %c tiene que ser igual al valor ASCII de %f1*%f2, 100, ‘d’.

Y colorín colorado, un password correcto es: 1-4-25-d

image

Eureka ! Tarde unas 6 horas en sacarlo, soy un cracker de pacotilla. Envíe la solución 14 horas después del inicio del reto así que me quedaré sin camiseta, solo los 5 primeros la reciben.

Shaddy, un amigo que lo resolvió antes que yo, ha publicado también una solución que seguramente esté mejor explicada que esto. Solución en Megaupload Solución en GoogleGroups

Si queréis aprender sobre ingeniería inversa, este curso de Ricardo Narvaja es un buen comienzo, y la lista de google de crackslatinos un buen camino.