Tutorial. Solución Reto Panda Security (P1)

Página 1 de 1
Avatar de Usuario
ethiel
Registrado: 05/11/2005
Mensajes: 2737
Seguridad informática ADSLzone
Seguridad informática ADSLzone
Mar 07 Abr, 12:29
Tutorial. Solución Reto Panda Security. Prueba 1


INTRODUCCIÓN.


He aquí la solución a la primera prueba del reto de Panda. Voy a explicar en qué consiste por si alguien no lo sabe. Panda Software ha llevado a cabo una campaña de publicidad, con el objetivo de captar nuevos talentos ;) (o mejorar su programas ... [opinión personal]), que consiste en descifrar el código de un archivo .exe para sacar una contraseña. Esto es, sencillamente, aplicarle ingeniería inversa a un ejecutable. La persona que primero realice la hazaña, tendrá como premio una PSP, un Ipod Touch y como último premio, un portátil.

Si alguien desconoce lo que es ingeniería inversa:
http://es.wikipedia.org/wiki/Ingenier%C3%ADa_inversa

DESTREZAS QUE SE SUPONEN.

Es necesario tener un mínimo de conocimiento de ASM para entender este manual, así como saber algo sobre FPU para poder lograrlo con éxito.

MATERIALES.

OllyDbg.

Como desemsamblador, OllyDbg, en su versión 1.0. Actualmente está en desarrollo la 2.0, pero aún no es estable. Este programa es gratuito, con muchísimos plugins que facilitan la tarea del ingeniero inverso. Existen otros, pero personalmente siempre recomiendo el uso de esta potente herramienta.

URL de descarga del programa: http://www.ollydbg.de/ o también en la zona de programas de este foro
URL de descarga de los plugins: http://www.openrce.org/downloads/browse/OllyDbg_Plugins

Existen actualmente mas páginas de descarga de plugins de ollyDbg, yo he puesto esa porque me parece muy completa.


Un cerebro.

El ingeniero inverso ha de estar, de entrada, predispuesto a pensar. De nada sirve tener un arsenal de depuradores, desemsambladores, desempacadores, reactores de fisión atómica o similares, si no se piensa antes lo que se va a realizar, con calma.

Programa Text.exe


Es el programa suministrado por Panda en su web para la prueba 1. Pulsa aquí para bajarlo


OBJETIVOS

El objetivo de este manual es aprender unos fundamentos para poder mejorar la seguridad de tus programas, viendo los fallos de seguridad de otros.
Por supuesto, en este caso, el del reto de panda, hay un premio más jugoso: la psp, el Ipod Touch, o el portátil. No obstante, puede que nosotros no seamos los más rápidos en enviar la contraseña (objetivo final del reto), pero no debe preocuparnos. Si logramos comprender el manual, habremos cultivado el espíritu (Ramón y Cajal era un experto en esa materia, leed "los tónicos de la voluntad") y nos habremos preparado para futuros retos. No se quién dijo esta frase, pero me gusta, como colofón:

“Vive como si fueras a morir mañana, aprende como si fueras a vivir para siempre.”


SOLUCIÓN

Este manual no pretende ser un documento de ayuda para el uso del ollyDbg (se deja para otro manual, por supuesto), explicaré de pasada, sin centrarme en profundidad, el uso del programa.

Éste es el aspecto de un programa desensamblado con ollyDbg:

Imagen

Como podeis observar, tiene la parte de código en ensamblador, la parte de registros, la parte de pila, etc...
El olly es muy completo y puede mostrar otras muchas características. Os invito a que investiguéis las posibilidades de este magnífico programa.

Destripando el objetivo: test.exe


Abrimos el programa test.exe y ponemos cualquier clave.
Vemos que el resultado es bad!.

Imagen

Esto nos da una fenomenal pista a los ingenieros inversos, y es una muy mala práctica en los programadores: jamás se debe insertar texto plano indicando una frase de error en un programa.
Abrimos el programa test.exe con el ollyDbg. A los pocos segundos, podremos ver el programa desensamblado. Como todo ingeniero inverso debe hacer, buscamos por strings dentro del programa. Este es el resultado:

Imagen


Como se puede observar, la cadena “bad” y la cadena “password” aparecen. Además, utilizando F2 hemos insertado un breakpoint dentro del programa. ¿Qué es un breakpoint?. Un punto en el que el olly te devuelve el control. O sea: el programa se está ejecutando; cuando llega a un BP, el programa se detiene y te devuelve el control a ti. Hay de tipos distintos, de memoria, de hardware, en escritura, en acceso, en byte, en word...
Nosotros utilizaremos un BP normal, pulsando F2 encima de la cadena.

A continuación, pulsamos Enter y el programa nos desplaza a este punto:

Imagen


Se observa claramente cual es el curso de acción del programa:
Se ejecuta, carga la cadena ASCII bad y luego pregunta el password.

Tenemos dos conclusiones, entonces:
1)La cadena bad se carga siempre, no podemos hacer nada para eso.
2)Tendremos que cambiar esa cadena, una vez insertado el password, pero NO antes, como consecuencia de lo anterior.

En este punto, es donde la experiencia del ingeniero puede entrar en juego. Hasta el momento, todo ha sido mecánico.
Debemos saber que cadena es la que sale cuando el password es correcto. Una manera de hacer eso, es con programas que te devuelven absolutamente todas las cadenas que existen en el programa, entre otras cosas (siempre y cuando no se cargan dinámicamente en memoria). Uno de ellos es DIS, que también viene incluido en el rar.
Nosotros haremos esto merced a una característica de Olly.
Buscamos en el DUMP por el valor inmediato, o sea:

Imagen

Abajo a la izquierda, rodeados en rojo, podéis ver las cadenas que están próximas en bytes a bad: yes y password. Como ya el avispado lector habrá adivinado, la palabra cuando insertas la contraseña correcta es YES. ¡He aquí nuestro punto de partida!.
¿Como se te ocurre buscar por follow in Dump?. Sencillamente, lo da la experiencia, tanto programando como desensamblando programas. Si el programa estuviera correctamente codificado, hablando en términos de seguridad, esa cadena debería estar lejos de la cadena bad, con lo cual hubiera sido un poco mas complicado dar con ella.

¿Como podemos obtener la cadena yes?. Observemos la parte ampliada de la imagen:

Imagen

Yes está separada de bad, 4 bytes.
Con ese dato, ya podemos suponer una cosa: al resultado que pone la cadena bad en pila, hay que sumarle 4. Si logramos eso, la cadena que se pone en pila es yes.

Recapitulemos:


Tenemos dos datos: que la cadena de “chico bueno” es yes y que dista 4 bytes de de la cadena bad.
Sigamos ejecutando el programa a ver como funciona.....
Seguimos ejecutando el programa y vemos como se para en el momento en que la ventana de CMD se abre para que insertemos una contraseña, eso en ensamblador se traduce en las siguientes líneas de olly:

Imagen

Alto. Pensemos ahora por un momento que nos dicen esas líneas con BP insertado.
1º. El formato de la contraseña debe ser %d-%f-%f-%c.
2º. Son 4 caracteres.

Recapitulemos de nuevo: cadena yes, separada de Bad 4 bytes.

Formato de la contraseña: entero-punto flotante-punto flotante-carácter.

Tenemos ya varias pistas para seguir con el proceso de recuperación de la contraseña.
Vamos a insertar cualquier password, sabiendo que la línea sombreada de la imagen precedente, indica el final del proceso de escritura. O sea: cuando escribes la contraseña y pulsas enter, la siguiente línea que se ejecuta es add esp,20.

Vamos avanzando por instrucciones. Observamos que la contraseña que hemos escrito se carga en los registros y luego pasa a un call. Detrás de ese call, una vez ejecutadas otra serie de instrucciones, saldrá como resultado en pantalla o bien la cadena bad o bien la cadena yes. Lo anteriormente dicho equivale a estas líneas de olly:

Imagen

El call en el cual está situado el BP, es el call “mágico”. A continuación de ese call, se empiezan a devolver valores para realizar las comparaciones. Debemos asegurarnos que el valor que se devuelve de esa función la del call, es 4. ¿Por qué 4?. Por lo que dijimos antes, la cadena yes dista de bad 4 bytes, justo esos 4 que se suman a la dirección de bad.
Previamente, hemos insertado el BP, y vamos a probar con un serial cualquiera: 1-2.0-3.0-4

Pulsamos Enter y nos vamos al call, pulsamos F8 y pasamos a la siguiente instrucción.
Veamos una captura de pantalla para comprender mejor lo que sucede.

Imagen

He insertado BP's en todas las instrucciones. Vosotros debéis hacerlo también, con objeto de que comprobéis paso a paso lo que viene en los comentarios.

Hay que prestar atención a dos puntos:
la instrucción: FILD WORD PTR SS:[ESP]
FUCOMPP.

La primera nos dice, que pasa el carácter introducido a FLOAT.
La segunda, es una instrucción que deja un valor por el que se compara después.
Precisamente, ese valor es el resultado de multiplicar F1XF2, o sea:
Float1 X Float2 ==(Caracter pasado a Float).
Con lo cual, ya tenemos una parte del serial solucionada. Podéis comprobarlo vosotros mismos:insertad el serial: 1-34.0-2.0-D. El valor D pasado a numérico es 68, igual que el resultado de la multiplicación de 34.0 y 2.0, con lo que el valor de la bandera Z cambiará y el salto en la instrucción JNZ SHORT de la dirección: 004015AE no se tomará, pasando a la comprobación de la segunda parte del serial.

Como recordareis, la comprobación de la segunda parte, tenía que ver con que la función del call debía retornar 4. Ese será nuestro objetivo.

Vamos a volver a ejecutar el programa, poniendo un BP en la dirección del call, la 00401561.
El programa se parará, una vez insertado nuestro serial y pulsado Enter, en el call. Pulsamos F7 para meternos dentro del susodicho call y nos encontramos con una maraña de instrucciones, 4 funciones internas y mucho dolor de cabeza, pero que nadie se asuste. Paja, muchísima paja.

Vamos a ver lo que se hace en estos casos.
Sabemos, por todo lo anterior, que el resultado del call debe devolver EAX igual a 4. Nos vamos al resultado de la función, donde se devuelve EAX y nos topamos con esto:

Imagen

EAX, antes de terminar la función, se actualiza con el valor de Local.18. Sin embargo, nosotros sabemos que el valor de EAX ha de ser 4. Como se observa en el comentario, si el salto de la instrucción en 00401408 no se cumple: a LOCAL.18 se le inserta un cero, con lo cual, EAX toma el valor cero.

Ya sabemos qué no debe ocurrir: el salto debe cumplirse. Sigamos observando un poco mas hacia arriba:

Imagen

El resultado del salto depende del OR EAX,ECX. Obliga a que tanto EAX como ECX valgan cero y por lo tanto, el resultado del XOR anterior tiene que ser cero.

Con el BP insertado ahí, ejecutamos y observamos lo que ocurre. Voilá, se hace un XOR del FLOAT1 con 0x4. O sea; para que salga cero, debemos hacer que FLOAT1 sea justamente 4.0.


EL FINAL.

Ya tenemos las dos comprobaciones: FLOAT1XFLOAT2=(CARACTER PASADO A FLOAT) y FLOAT1=4.0

Por lo tanto, cualquier serial que cumpla esas dos comprobaciones será correcto. Vamos a comprobar (el primer número sencillamente no vale para nada).
23-4.0-22.0-X

Imagen

Saludos. Ethiel.

Con mi agradecimiento al FOS TEAM.
Última edición por ethiel el Mié 08 Abr, 18:27, editado 2 veces en total
Shaddy
Shaddy
Registrado: 08/05/2009
Mensajes: 2
ZoNeR@
ZoNeR@
Vie 08 May, 20:33
Hola ethiel, tengo una pequeña duda respecto al tutorial.

He insertado BP's en todas las instrucciones. Vosotros debéis hacerlo también, con objeto de que comprobéis paso a paso lo que viene en los comentarios.


¿Porqué tienes que meter un BreakPoint e todas las instrucciones? Se puede tracear sin ningún problema con F7 o F8, el primero para ir trazando entrando en los call y el segundo para saltarlos. Felicidades por resolver el reto :).

Shaddy.
"Si buscas resultados diferentes, no hagas siempre lo mismo" (Albert Einstein)

http://abssha.blogspot.com
Página 1 de 1

Volver a Seguridad informática