Cracking 101 - Capítulo 1.1
Introducción
Cracking es sobre eliminar restricciones impuestas a un programa cuando no se tiene el código fuente original. Lo anterior puede ser tan simple como una verificación que nos forza a comprar un programa después de X número de días, o tan noble como agregar funcionalidad que necesitamos a un programa del cual no tenemos su código fuente y el autor por alguna razón no está disponible para hacer los cambios. Sea cual sea el motivo, todo se reduce a encontrar esa restricción y eliminarla. Esto nos lleva al tema principal de este capítulo: tipos de restricciones y aproximaciones para eliminarlas.
Si se tiene experiencia en Windows más temprano que tarde te topas con los llamados Shareware, aunque solían ser más populares a mediados de los 90’s. Este tipo de programas te ofrecen una versión de prueba, generalmente con algunas restricciones impuestas. Si el programa te gusta, lo puedes comprar para eliminar las restricciones. Cuando el programa deja por fuera algunas características que si se incluyen en la versión final entonces es un Demo. La diferencia entre Demo y Shareware es que el primero simplemente no incluye la funcionalidad, mientras que el Shareware si incluye la funcionalidad pero es restringida de una u otra forma.
Llave Hardcoded
Presumiblemente el tipo de protección más sencillo de eliminar, causa por la cual es una burla constante hacia los autores que insisten en “proteger” sus programas con una protección de este tipo. Este tipo de protección funciona de la siguiente manera: el programa te pide que introduzcas una clave (llave, serial, key, etc) y si es introducida la clave correcta, el programa elimina todas las restricciones. ¿Cómo sabe el programa que la clave introducida es correcta? ahí está lo interesante y el punto débil de la protección: el programa incluye dentro de su código la clave correcta. Podemos visualizarlo de la siguiente manera (en alto nivel, Java):
-
if(clave.equals(claveCorrecta))
-
return true;
-
return false;
-
}
Al decompilar el programa que queremos crackear (la víctima) generalmente podemos verificar las referencias a cadenas (string references) que no es otra cosa que todas las cadenas utilizadas en el programa. En el caso anterior, la variable claveCorrecta contiene la clave que elimina las restricciones del programa. Esta variable, claveCorrecta, es una cadena y como tal aparece en las referencias a cadenas. Imaginemos por unos momentos que el programador elige una “clave segura”, es decir una combinación de números y letras mayúsculas y minúsculas, símbolos y demás con una longitud de 16 caracteres, del tal manera que la probabilidad de que alguien adivine la clave se vuelve extremadamente baja. Imaginemos pues, que la clave es:
aHa-%67YUI-Mn-34
Cualquier parecido con la realidad es mera coincidencia. En este caso tenemos una clave de 16 caracteres (contando los caracteres guión ‘-’). Al momento de decompilar el programa y verificar las referencias a cadenas vemos la siguiente lista:
MiTiendita 1.0
Tiempo de espera expirado, intente reiniciar
aHa-%67YUI-Mn-34
La ruta de instalación no es válida
Hay actualizaciones disponibles
…
Queda suficientemente claro que al instante que vemos una cadena de ese tipo lo primero que se viene a la mente es “clave válida”. Esto puede no ser el caso (el programador introdujo varias claves no válidas para despistar) pero es seguro que llama la atención. Crackear un programa con este tipo de protección generalmente es tan sencillo como verificar las referencias a cadenas.
¿Cómo crackeamos este tipo de protección? Al iniciar el análisis de un programa que solicita una clave para desbloquearse no se sabe que es del tipo llave hardcoded. Abrimos el programa víctima y nos pide una clave que bien podría ser generada de manera dinámica. Un posible indicador de llave hardcoded podría ser que el programa solo pida una clave, no un nombre de usuario, correo, etc, pero ojo, es solo un indicador y para nada una regla. Si al verificar las referencias a cadenas encontramos alguna cadena sospechosa o con un formato particular, es posible que sea la clave y vale la pena probar. No hay mucho más que decir sobre esta protección.
Vamos a crackear un pequeño programa que se “protege” con llave hardcoded (HardCoded.exe). El crackme lo pueden ver en la imagen de la derecha, es muy sencillo: el programa es un textbox y un botón. Si introducen una clave incorrecta les aparece la ventana de error que se muestra en la imagen. Si introducen la clave correcta… eso vamos a averiguarlo.
Empezamos con una gran ventaja: sabemos que está protegido con llave hardcoded. Lo primero que hay que hacer (y prácticamente lo único) es decompilarlo. Pueden utilizar su decompilador de confianza pero yo recomiendo 2: OllyDBG (que es un debugger) e IDA PRO, el cual no tengo a la mano así que voy a usar Olly. También pueden usar W32Dasm si así lo desean. Abrimos el programa en OllyDBG y verificamos las referencias a cadena. Esto es muy sencillo de hacer, solo click derecho en el área de código, seleccionamos “Search for” y después “All referenced text strings”. Les aparecerá una ventana similar a la de la imagen de abajo:
Vemos algunas cadenas como “Hardcoded Serial”, “Edit”, “Ok”, “Button” y después una muy sospechosa: “AH0-498756JR-RF4″. Introducimos esa en el programa y ¿que pasa? :)
Clave Generada
La protección tipo clave generada es similar a la anterior, solo que con una gran diferencia: ahora la clave no es parte del código (y por lo tanto no tan sencilla de crackear). Existen varias maneras de generar un serial, generalmente se hace que el usuario introduzca su nombre u otra información y a partir de ahí se genera una llave única que desbloquea el programa, con infinitas variaciones a este procedimiento. El punto débil de este tipo de protecciones está en el algoritmo con el que genera la llave única. Si es un algoritmo demasiado sencillo, se puede “reversear” fácil es decir, averiguar cómo funciona por medio del código desensamblado y recrear el algorimo para generar nuestras propias llaves. La otra (menos elegante) es parchar el programa para que acepte cualquier llave.
Y hasta aquí la dejamos, por eso el 1.1 en el nombre del capítulo. En la próxima edición continuamos con otros tipos de protecciones y sus respectivos ejemplos. Pueden HardCoded.exe 100% libre de virus, bacterias o cualquier malware.
Apéndice
Otra manera de crackear el crackme presentado es parcharlo para que siempre muestre el diálogo de éxito. Veamos, lo primero que hay que hacer es saber cómo aproximarnos al punto en el que se verifica que nuestro serial es válido. Sabemos que una ventana de alerta (se llaman message box) nos indica si la clave es válida o no, entonces lo que vamos a hacer es poner un breakpoint en cualquier lugar que el programa haga referencia a la función MessageBox. De nuevo, podemos hacerlo de dos maneras: buscando todas las referencias a la función MessageBox o utilizando la información que el mismo programa nos da. Al introducir un número de serie incorrecto, la ventana nos muestra el mensaje que dice “La clave es incorrecta”. Buscamos esta cadena en la ventana de las referencias a cadenas y efectivamente podemos ver que en la dirección 0040167A se hace referencia a dicha cadena. Damos doble click sobre el renglón en la ventana de referencias a cadena y eso nos lleva a la dirección en cuestión:
Podemos ver claramente que arriba de la referencia a la cadena se encuentra la llamada a MessageBoxA. Nos posicionamos sobre esta instrucción y presionamos F2 para poner un breakpoint. Ejecutamos el programa y ponemos un serial no válido. En vez de seguir ejecutándose, el programa se detiene en la llamada a MessageBoxA por el breakpoint que pusimos. Ahora, en la pila (stack) podemos ver cómo es que primero se empuja el estilo de la ventana, después el título, después el texto y por último la ventana padre (recordando que la pila es FILO o First In Last Out, como en una pila de platos: el primero que ponemos es el último en salir). Algo interesante del órden de los datos en la pila es que, si vieron la documentación de la función MessageBox, es el mismo órden en el que aparecen en el código C de la API de Windows. No es una coincidencia, existe una relación directa entre la manera en la que C declara sus funciones y cómo lo vemos en ensamblador, lo cual es una gran ventaja para nosotros.
Veamos la pila:
Arriba del último dato empujado, hOwner, se encuentra una dirección: HardCode.0040163A. Esa dirección es donde se verifica el resultado de la comparación entre el serial válido y el introducido por el usuario y después brinca si el resultado no es cero (JNZ) lo que verifica la bandera Z. Si ese salto se ejecuta el programa brincará a 00401668 lo que ocasionará que se muestre el mensaje de error. Lo que vamos a hacer es que no brinque y continue con la ejecución del programa, de tal manera que siempre muestre el mensaje correcto. Podemos invertir el salto (convertirlo de JNZ a JZ) pero entonces si se introducie el serial válido marcará el error. Lo que vamos a hacer es simplemente eliminar ese salto con la instrucción NOP (No Operation) que no hace nada (muy útil).
Primero pondremos un breakpoint una instrucción antes de que se ejecute el salto, en la llamada a strcmp. Reiniciamos el análisis Ctrl + F12, llenamos con clave inválida, el programa rompe y posicionamos el marcador de línea sobre el salto, presionamos la barra del espacio, introducimos la instrucción NOP como se muestra en la imagen:
Asegúrense de tener seleccionada la opción de “Fill with NOP” ya que como la instrucción NOP ocupa menos bytes que la que estamos sustituyendo, en efecto tendremos 2 instrucciones NOP seguidas para abarcar el espacio original del salto. En este momento podemos eliminar el breakpoint (posicionamos sobre la linea del breakpoint y presionamos F2) y continuar con la ejecución del programa (F9) ¿Que sucede? Si quieren hacer los cambios permanentes: click derecho, copy to executable, all modifications. Seleccionen la opción de Copy All y se abrirá una ventana de dump, al cerrar esa ventana les pregunta el nombre del nuevo ejecutable y les guardará el programa parchado.
(Gracias a Pablo por el código del crackme en C++. No lo pude compilar bajo MinGW sin modificación ya que se quejaba del operador reinterpret_cast, así que le paso el apuntador original como va. Como vi que funcionaba, así lo dejé. Definitivamente la programación Win32 no es lo mio)





2 Comentarios
Geek & Roll - Blog Archive » De cómo ser un cracker
[...] A los interesados en aprender a crackear, se ha empezado una serie de posts sobre el tema. En vez de dejar su correo y esperar a que los ayuden pueden tomar cartas en el asunto y comenzar a estudiar por su cuenta. Si aún tienen dudas pueden dejar sus preguntas en los comentarios del post respectivo. Liga al capítulo 0 y al capítulo 1.1 [...]
Rafyta
Que machin mi compa, ya esperabamos la secuela.
Espero que mi hamster no se entuma con tantos numeritos…
Haz un comentario:
Es necesario que dejes tu nombre y correo electrónico (no se publicarán).
Si dejas un comentario anónimo, con insultos o ajeno al tema, iremos hasta tu casa y le diremos a tu mamá la cantidad de porno que hay en tu computadora. Si, lo sabemos.