31 marzo 2014

3.2  ¿Dónde se crea la ventana?

El problema es que no sabemos a dónde queremos que el programa salte. Tenemos la pista del nombre de la ventana “test_app”. También sabemos que seguramente debamos saltar a una función que no sea referenciada por otra (ahí está la gracia del reto). Debemos suponer que primero el binario deberá hacer una llamada para crear la ventana y después otra para pintar el cuadrado (o lo que sea que sea eso).

Otra forma de resolver el reto es ver que hacen cada una de esas tres funciones que he mostrado antes y ver quien las está llamando. Yo opté por una mezcla de esta última opción con la anterior.

Veamos primero la función llamada por IDA sub_4020B0. En un bloque de la función vemos:



¡Vaya! Si tenemos una llamada a la API “CreateWindowExA”. Qué suerte la nuestra que hemos encontrado precisamente lo que buscábamos. Siguiente paso es saber quien está llamando a esta función.

Veamos que trozos del código no son referenciados por el flujo de código que estamos siguiendo simplemente pulsando la letra “x” en IDA al principio de la función. Si nadie referencia a esta función ya sabremos a donde debemos hacer que se produzca el CALL EAX:



Vemos que la dirección 402012(402000+12) está haciendo un CALL a la función que crea la ventana donde más tarde se debe pintar el susodicho cuadrado. Vayamos allí a ver que vemos:



¡Perfecto! Parece que está llamando a nuestra función create_window (así la he llamado yo pero es la antigua sub_4020B0) y en caso de que la respuesta de la misma sea 0 (error) nos mostrará un mensaje con el texto “error”.
Veamos ahora si alguna parte del código está llamando a la dirección 402000.



¡Ya tenemos nuestra dirección deseada del CALL para crear la ventana!

Otra forma de encontrar la función “huérfana” a la que debemos saltar es abrir la vista de IDA que pinta el “CALL flow” del programa (Ctrl+F12):



Como podemos ver todas las funciones son referenciadas excepto dos de ellas: sub_4022E0 y sub_402000. Si recordamos del punto 3.1, el programa cogía los 4 primeros bytes del fichero “key.txt” y los sumaba al valor 7A40B660.

Por tanto: X+7A40B660=402000 => X=402000-7A40B660. Usamos la misma calculadora de Windows para calcular nuestra X y obtenemos: 85FF69A0. Estos deberán ser los primeros 4 bytes del fichero “key.txt”. Recordemos que estamos bajo una arquitectura Little Endian por lo que el orden de los bytes es de derecha a izquierda (inverso a la escritura occidental) y por tanto los cuatro primeros bytes serán: A069FF85.

Debugueamos la aplicación con IDA y vemos como el CALL EAX se produce con el valor de EAX=402000 y podemos observar como se ha creado una nueva ventana con el nombre “test_app”. ¡Perfecto!


3.3  Pintar el cuadrado

Ahora solo nos falta que se pinte el cuadrado en la ventana creada. Para ello deberemos de saltar en algún momento a alguna parte del código que se encargue de pintar dicho cuadrado. Intentemos identificar las opciones que tenemos para saltar a una zona que nosotros queramos como hicimos anteriormente:



Como vemos solo tenemos dos opciones que a priori no parecen muy prometedoras:
  • CALL [EBP+4]: En ningún momento llegamos a controlar EBP por lo que no podemos contar con ello para dirigir el flujo de ejecución a donde queramos.
  • JMP loc_402360: En principio parece que la dirección a la que salta es estática y no depende de ningún registro (y lo es), sin embargo si nos fijamos en las instrucciones desde el CALL EAX hasta el PUSH previo al siguiente CALL podemos observar lo siguiente:



Vemos que tenemos el control de EDI y que en EDI se escriben ciertos bytes de los cuales también tenemos nosotros el control. Por tanto, lo que podemos hacer es modificar a donde debe el JMP pegar el salto para hacer que ese salto sea al trozo de código que se encargue de pintar el cuadrado y solucionar el reto. Por tantoEntonces deberemos hacer que se modifiquen los bytes de la dirección del JMP (4010BD).

Del byte 4 al byte 8 (Teniendo en cuenta que el primer byte es el 0) de nuestro “key.txt” es sumado a “0D1BE0114C” y almacenado en EDI. Luego el byte 8 del fichero es almacenado en BL. Por último del byte 9 al 13 del fichero se mueven a EAX.

Los siguientes dos MOV modificarán la zona de memoria a donde apunta EDI (y que nosotros controlamos):
  •  El primer MOV mueve a donde apunte EDI el byte octavo de nuestro “key.txt”.
  • El segundo MOV mueve EAX (los bytes de “key.txt” de la posición 9 a la 13) a donde apunte EDI+1.

Como queremos modificar la zona de memoria del JMP (4010BD) tendremos que hacer que esta sea igual a la suma de “0D1BE014C” (harcodeado por el programador) con los bytes del 4º al 8º de nuestro “key.txt. Por tanto:
0D1BE014C + X = 4110BD => X = 2E830F71 (710F831E en Little Endian).

3.4  Dónde saltar para pintar el cuadrado


¡Perfecto! Ahora que podemos modificar a donde salta el JMP solo nos queda saber a qué dirección queremos que dé el salto. Debemos hacer que salte a alguna zona de código que se encargue de pintar el cuadrado en la ventana que ya hemos creado.

Para encontrar dicha zona echemos un vistazo a las otras dos funciones que nos enseñaba IDA (sub_402040 y sub_4023A0):
  • sub_402040: Parece que lo que hace es eliminar la ventana creada por lo que no debe ser la encargada de pintar el cuadrado.


Además si vemos que partes de código la llaman nos encontramos con que se llama justo antes de mostrar un mensaje con el string “error”. 



Por esta información podemos decir que esta llamada es el destructor de la ventana.
  • sub_4023A0: Solamente viendo las APIs que está utilizando podemos darnos cuenta de que está función se encarga de crear una figura geométrica a la cual le establece ciertos colores:



Veamos quien llama a esta función:



Vemos que la dirección 402324 está llamando a dicha función. Si miramos por encima la estructura del código anterior y posterior veremos que es un bucle:



Podemos ver (resaltado en naranja) como se almacena en EDI, EBP y EBX las direcciones de tres funciones (“PeekMessageA”, “DispatchMessageA” y “SwapBuffers”) que más tarde son usadas en el bucle y también la típica estructura de prólogo de una función reservando 28 bytes (1Ch) de espacio en la pila: SUB ESP,1Ch.

Yo cree una función en la dirección 4022FC en IDA presionando la letra “P” para poder verlo gráficamente más fácilmente:



Como podemos ver ninguna parte del código accede a este bucle (que pinta el dichoso cuadrado en la ventana) y por tanto, debemos hacer que nuestro flujo de instrucciones salte a la dirección 4022E0.


Ya tenemos donde queremos saltar para pintar el cuadrado. 


Artículo cortesía de: Alberto García Illera

1 comments :

Security By Default dijo...

Disculpad la errata, ¡gracias por la aclaración Nacho!