Hace unos años cuando empecé a trastear con Android y animado por mi afición a la Ingeniería Inversa, decidí realizar una serie de crackmes. Los dos primeros pasaron algo desapercibidos, pero el Crackme nº3 tuvo una gran repercusión en el mundillo y, aunque no fue el primer crackme para Android ni mucho menos, si que fue uno de los más estudiados. Todos ellos fueron publicados a través de crackmes.de y el nº3 en cuestión el 6 de Noviembre de 2010. Os dejo una lista de unas cuantas webs donde aparece analizado para que veáis la repercusión que a mi parecer tuvo.
Este es un crackme de la web de Karpoff programado por Sotanez y realizado en Delphi. Como máximo nos deja meter nombres de 10 dígitos.
El algoritmo
Es un algoritmo muy sencillo pero veremos que nos tendremos que fijar en el DUMP de Olly para saber que demonios hace. Como de costumbre abrimos Olly y en las «Referenced Strings» localizamos la palabra «Registrado«, pinchamos en ella y localizamos la porción de código que nos interesa. Vamos a analizarla.
Vemos 3 bucles, el primero pone la memoria (Dump) a cero, el segundo guarda nuestro nombre (errata en la imagen) en el Dump y el tercero realiza la suma de los valores ascii del nombre. Hasta aquí todo bien, pero vamos a hacer una prueba para el nombre deurus.
Nombre: deurus
Serial: 64+65+75+72+75+73 = 298 (664 en decimal)
Probamos el serial en el programa y nos da error, vale, vamos a analizar más a fondo los bucles.
El primer bucle hemos dicho que pone la memoria a 0, en concreto desde «45BC60» y de 4 en 4 (fíjate en el Add 4), es decir, pone a 0 los offsets 45BC60, 45BC64, 45BC68, 45BC6C, 45BC70, 45BC74, 45BC78, 45BC7C, 45BC80, 45BC84, ya que el bucle se repite 10 veces. En la imágen queda claro.
El segundo bucle se repite 11 veces y lo que hace es guardar en el dump el valor ascii de las letras de nuestro nombre. En la imagen lo vemos.
A primera vista ya vemos un valor extraño en la posición 45BC80, y es que cuando debiera haber un 0, hay un 12. Vamos a ver como afecta esto al serial final.
El tercer bucle se repite 10 veces y lo que hace es sumar los valores que haya en el DUMP en las posiciones anteriormente citadas.
En concreto suma 64+65+75+72+75+73+0+0+12+0 = 2AA (682 en decimal). Probamos 682 como serial y funciona. Realizando más pruebas vemos que para nombres con un tamaño inferior a 5 letras se ocupan las posiciones 45BC70 y 45BC80 con valores extraños, el resto de posiciones se mantienen a 0. En las imágenes inferiores se pueden apreciar más claramente los valores extraños.
Nombre de tamaño < 5.
Nombre de tamaño >5 y <9
Nombre de tamaño = 10
En resumen:
Nombre de tamaño < 5 –> Ascii SUM + 14h Nombre de tamaño >5 y <9 –> Ascii SUM + 12h Nombre de tamaño =10 –> Ascii SUM
Con esto ya tenemos todo lo que necesitamos para nuestro keygen.
char Nombre[11];
GetWindowText(hwndEdit1, Nombre, 11);
char Serial[20];
int len = strlen(Nombre);
int suma = 0;
for(int i = 0; i <= len; i = i + 1)
{
suma += Nombre[i];
}
if(len < 5){
suma +=0x14;
}
if(len > 5 && len < 9){
suma +=0x12;
}
wsprintf(Serial,"%d",suma);
SetWindowText(hwndEdit2, TEXT(Serial));
Este BTM va otra vez sobre IPs. Si amigos del séptimo arte, viendo un capítulo de mi querida «The Sinner» me han vuelto a chirriar los dientes. La verdad que viendo el capítulo no te da tiempo a apreciarlo, únicamente me quedo con que aparece una URL y lo reviso a posteriori (esto lo digo para los curiosos que me preguntáis).
En esta ocasión me tiene un poco inquieto ya que es una serie que cuida enormemente los detalles y el fallo que os voy a mostrar parece intencionado. La imagen en cuestión es esta:
Fotograma del capítulo 2×06
Aparece un buscador con una URL más o menos creíble si no fuera porque la IP que aparece es IMPOSIBLE. La máxima IPv4 es 255.255.255.255, es decir, no han dado ni una, y eso es lo que me tiene mosca. Si hubieran utilizado 82.47.25.29 hubiera quedado bien y estaríamos hablando de un problema de geolocalización de IPs, ya que el rango 82.47.xx.xx le pertenece a UK y deberíamos discernir si el servidor está en EEUU o no…
En definitiva, puede ser un fallo a propósito, un guiño o tener un significado. No se que deciros, bueno si, ¡lo investigaré!
Alerta de Spoiler: El reto está en activo a fecha de publicación.
Spoiler alert: The challenge is still alive.
Este tipo de retos son de lo más variopinto pero una de las primeras cosas que se suele hacer es ver el código fuente y fijarse en los enlaces para hacernos una idea del tipo de vulnerabilidades a explotar. Empezamos por explorar el código fuente.
A simple vista no hay nada sospechoso pero me llama la atención el enlace de la imagen del gatito «source/cat.gif«. Si fisgamos dentro de la carpeta «source» podemos ver que nos muestra el contenido de la carpeta como se puede apreciar en la imagen a continuación.
Contenido de la carpeta source
La carpeta «app» suena interesante. Hacemos clic y vemos lo siguiente.
Notice: Undefined index: commit in C:/xampp/htdocs/challenge-land/Realistic/shop/source/app/index.php on line 2
Vemos que el error mostrado muestra más información de la debida y la aprovecharemos en beneficio propio. Aquí la clave está en el fichero index.php y en el parámetro commit. Haremos una prueba para ver que vamos por el buen camino.
Hay varias respuestas sugerentes pero quizá la más relevante es la 8. Ahora bien, solo falta encontrar donde introducir el usuario y la clave.
Si volvemos a la página principal vemos en el enlace algo interesante, me refiero a index.php?page=index. Tras probar varias cosas la que funciona es la típica, admin.
Al entrar vemos que nos redirige al index de nuevo tras pocos segundos. Aquí hay dos opciones, desactivar javascript para evitar la redirección o entrar directamente a la página admin.php. Optamos por el camino fácil entrando directamente en admin.php:
Aquí tenemos un crackme clásico realizado en Visual C++. La única particularidad que tiene es que no muestra MessageBox al introducir bien o mal el serial, simplemente cambia una imagen de un emoticono. Si observamos el comportamiento del crackme notaremos que inicialmente el emoticono está neutral y al fallar se pone triste y por lo tanto es de suponer que al acertar se pondrá contento.
El BreakPoint
Intermodular Calls
Al mirar en las Intermodular Calls de OllyDbg vemos que LoadIconA es un buen candidato para ubicar la comprobación del serial. Si nos fijamos hay tres llamadas, ponemos un breakpoint en las tres y enseguida llegamos a la zona de comprobación del serial.
La comprobación es muy sencilla, en resumen hace esto con todas las letras del nombre excepto la última:
1º Caracter
(1ºname + 1ºserial - 2 = X)
(X / 2)
(X + 1)
(2ºname - 2 = Y)
¿Y = X?
2º Caracter
(2ºname + 2ºserial - 2 = X)
(X / 2)
(X + 1)
(3ºname - 2 = Y)
¿Y = X?
...
Con el último caracter del nombre hace lo siguiente:
(6ºname + 6ºserial - 2 = X)
(X / 2)
(X + 1)
(2ºname - 2 = Y)
¿Y = X?
---------
Para revertir la primera parte de la comprobación para el nombre deurus quedaría:
X1 = (((2ºname-2-1)*2)+2)-1ºname
X2 = (((3ºname-2-1)*2)+2)-2ºname
X3 = (((4ºname-2-1)*2)+2)-3ºname
X4 = (((5ºname-2-1)*2)+2)-4ºname
X5 = (((6ºname-2-1)*2)+2)-5ºname
X6 = (((2ºname-2-1)*2)+2)-6ºname
Keygen
var nombre = "deurus";
nombre = nombre.toUpperCase();
var serial = "";
var tmp = "";
var i;
for (i = 0; i < nombre.length-1 ; i++) {
tmp = ((nombre.charCodeAt(i+1)-2-1)*2+2)-nombre.charCodeAt(i);
serial += String.fromCharCode(tmp);
}
tmp = ((nombre.charCodeAt(1)-2-1)*2+2)-nombre.charCodeAt(nombre.length-1);
serial += String.fromCharCode(tmp);
document.write(serial);