Cuando un usuario de un ordenador se pregunta como funcionan dichas máquinas en profundidad, enseguida salen a colación términos como el lenguaje ensamblador, el lenguaje máquina y la ingeniería inversa.
Existen auténticos gurús (Steve Wozniak) de este arte que está (por desgracia) muy asociado al término cracker. En absoluto un ingeniero inverso es un cracker, que es un término asociado con el pirata informático que revienta programas y protecciones para su propio beneficio.
Desde RedesZone vamos a proponer este ejemplo (es un programa real tremendamente mal protegido), para todos aquellos que quieran empezar a conocer este mundo y sus aledaños. De entrada, se indica que toda información sensible está ocultada en las capturas. Así mismo, se denota que este artículo tiene como finalidad exclusiva mostrar una mala protección y mejorarla con los consejos que se proporcionarán en el punto correspondiente.
Herramientas
OllyDBG.
Desensamblador y depurador. Tiene dos versiones; siendo la 2.0 la última estable. Yo recomiendo trabajar con las dos, 2.0 y 1.1 puesto que la 2.0 tiene algunas funcionalidades que no me entusiasman no se puede insertar Breakpoint en todos los comandos, por ejemplo, pero es mejor que la 1.1 en muchos otros aspectos.
PeId
Programa que analiza cabeceras PE para determinar ciertos parámetros (unpacker utilizado y otros). Muy útil.
Para poder comprender este artículo, es absolutamente necesario conocer algo de ensamblador, cabeceras PE y funcionamiento de un desensamblador y depurador. El objetivo de este artículo no es enseñar esos términos básicos, de modo que nos centraremos en la explicación y la solución.
Empezando
Lo primero que un ingeniero inverso debe valorar es a qué tipo de programa se enfrenta y como está protegido.
Las protecciones suelen ser varias, pero lo mas eficaz es mezclar muchas de ellas, siempre que esto no resulte contraproducente para la experiencia final de un usuario. Todos hemos visto programas cuyas protecciones «imposibles» de saltar provocan que los usuarios se tiren de los pelos cuando una aplicación que han comprado legalmente deja de funcionar por considerarse pirata. Es esencial que instales programas de forma segura.
La aplicación que tenemos como ejemplo tiene una protección excesivamente básica: busca un archivo y lo comprueba.
Vamos a ver una captura de su ejecución normal:
Se puede comprobar como el programa busca un fichero (ocultado por ser contenido sensible) al que llamaremos Fichero.opl. Si ese fichero no existe, como comentábamos anteriormente, el programa no se ejecuta y provoca ese error. Es una protección bastante burda, puesto que existen multitud de llamadas conocidas para buscar un fichero en el sistema y que pueden ser buscadas con ollyDBG y otros depuradores (el añorado SoftIce, una leyenda). Sin embargo, en este artículo no las usaremos, iremos un poco mas lejos buscándolo «a mano».
Vamos a ejecutar el OllyDbg y a depurar el programa.
Tenemos ésta ventana:
El olly nos indica que este programa está empacado. El empacamiento es una protección frecuente y tremendamente útil: si un cracker no puede leer las instrucciones y seguir el flujo, estará literalmente atado de pies y manos; este tipo de protección es todo un acierto. Sin embargo, existen herramientas que facilitan el trabajo a cualquier usuario, malicioso o no, y que permite conocer detalles sobre las cabeceras PE.
Vamos a abrir el programa con PeId, a ver qué información nos presenta.
Esta ventana nos ofrece una información crucial y además da una idea de la mala protección del sistema: lo primero que vemos es que, efectivamente, el ejecutable está empacado; pero lo está con una protección comercial, UPX, que incluso su utilidad trae un desempacador y por supuesto es muy sencillo de saltar, al ser tan conocido.
Lo ideal hubiera sido proteger el programa con un empacador propio o, al menos, editar las cabeceras para que PeId no pudiera mostrar el empacador utilizado o su versión
Después de ver esta ventana, sabemos que el empacador utilizado es uno que PeId puede desempacar gracias a un plugin que ejecutamos. El resultado de la ejecución es dicho programa desempacado y con sus instrucciones listas para ser leídas por el cracker.
Ejecutamos el programa otra vez con olly y nos encontramos con esta ventana:
Como vemos, la advertencia anterior no aparece, lo que indica que el programa estaba, efectivamente, empacado.
Vamos a depurar con el olly hasta que nos salte la ventana. Es decir, iremos de atrás hacia adelante, buscando el punto exacto en el que el programa se rompe, por decirlo de alguna manera.
Si depuramos un poco con olly, vemos que la ventana aparece. Como sabemos que una ventana se muestra en windows con un registerWindowMessage, buscamos ese comando e insertamos un BP.
Tenemos esto como resultado:
Este comando es el que muestra la ventana. Está claro que si llegamos a ese punto depurando y la ventana no ha salido, es muy posible que esa llamada sea la ventana de error; así que seguimos hacia atrás a ver donde se bifurca, si es que lo hace, el programa para terminar en esa ventana.
Depuramos hacia atrás y nos encontramos con una bifurcación muy simple: un salto que se realiza en función de una comparación. Si cambiamos los flags de las instrucciones, nos encontramos con que el comando de esa ventana se salta y podemos continuar sin mostrarla: parece que hemos avanzado en la dirección correcta. Sin embargo, si seguimos hacia adelante en el flujo nos da este otro error:
Es decir, parece que no sólo valida que exista si no que también verifica su integridad. Esto es completamente lógico y es un buen síntoma de que al menos, no se han estrellado al decidir la protección (lo contrario hubiera sido catastrófico: creas un fichero con el nombre adecuado y el programa funcionaría).
Vamos a ver qué ocurre y observamos que, efectivamente, se llama al mismo comando que antes para mostrar otra ventana. Seguimos hacia arriba y nos encontramos con, exactamente, lo mismo que antes: una bifurcación simple y llana en la que se pasa o no por la ventana de error dependiendo de un flag. Si lo cambiamos (JNZ por JE, idéntico al anterior y seguimos depurando el programa muestra la ventana de inicio de la aplicación; de modo que victoria, hemos logrado parchear el ejecutable y saltar la protección. Ahora, tan sólo restaría guardar los cambios y crear un ejecutable con OllyDbg.
Por supuesto, la ventana principal del programa no se muestra por ser un dato sensible.
CONCLUSIONES
En este caso, observamos que un programa que ha costado mucho esfuerzo y trabajo diseñar ha visto su protección reventada en una hora escasa. Vamos a enumerar los fallos de diseño en la protección:
–Empacador comercial.
Este es el punto mas crítico: al utilizar un empacador comercial, bien conocido por cualquier cracker, la protección resulta nula e muy sencilla de saltar. Este punto debería ser la puerta de entrada mas complicada hacia las instrucciones en ensamblador del programa y se ha saltado utilizando un plugin con dos sencillos clicks. Lo ideal, como se ha comentado mas arriba, es diseñar un algoritmo propio de empacado. Existen muchos buenos libros que analizan los empacadores y dan premisas de diseño para crearlos; Cracking sin secretos es uno muy básico que el lector de este artículo encontrará muy ameno.
-Bifurcación demasiado sencilla
En el programa que nos ocupa, hemos comprobado como la bifurcación de «chico malo» se hacía con un simple salto (JNZ) que ha resultado muy sencillo parchear (JNZ por JE), con lo que el programa no fallaba y el resultado de la ejecución del algoritmo de protección (existencia del fichero y validación de integridad del mismo) es inútil. Lo que se debería haber hecho es ocultar esa bifurcación en flujos mas complicados; es decir: nada obliga a realizar una bifurcación y a continuación mostrar el mensaje de error: se podría realizar el algoritmo y guardar el resultado para que el mensaje de error saliera en cualquier registro o en la pila para leerlo a mitad de cualquier flujo, eso hubiera sido mucho mas complicado de encontrar y parchear.
Desde RedesZone mostramos nuestro desacuerdo con las prácticas de piratería informática que proporcionan cracks de programas comerciales, por lo tanto, insistimos: que el lector no se tome este artículo como una puerta de entrada al cracking, si no a reforzar la seguridad de las aplicaciones que se desarrollen después de su lectura.