Warning: This challenge is still active and therefore should not be resolved using this information. Aviso: Este reto sigue en activo y por lo tanto no se debería resolver utilizando esta información.
Intro
This crackme is for the crack challenge 6 of canyouhack.it.
In this crackme the goal is to turn on all the lights. Note that a light off to the next, so if we interrupt this, we win.
Tools
Exeinfo (For crackme info)
Delphi Decompiler (For decompile)
OllyDbg (For debug)
Decompiling
With Delphi Decompiler we can found easy the buttons and his offsets.
Go to the offset 401A64 in OllyDbg and analyze the code.
We view two jumps, one turn ON the light and the other Turn OFF the next light. Patching the call from offset 401A8B we get the serial.
Warning: This challenge is still active and therefore should not be resolved using this information. Aviso: Este reto sigue en activo y por lo tanto no se debería resolver utilizando esta información.
Realistic Challenge 4: There is a site offering protection against hackers to website owners, the service is far too overpriced and the people running the service don’t know anything about security. Look around their site, and see how protected it is.
Hay un sitio que ofrece protección contra los hackers. El servicio tiene un precio abusivo, echa un vistazo a la web y evalúa su pretección.
Analizando a la víctima
Vemos un escueto menú pero con cosas interesantes.
Pinchamos sobre «Testimonials» y a continuación en «Customer 1»
Vemos que hay solo 3 «customers», vamos a introducir manualmente un 5 haber que pasa.
Ok, nos genera el siguiente error.
Probamos ahora con un enlace interno que nos genera el siguiente error.
Tenemos un directorio interesante «secure«, si entramos en el nos salta un Login típico protegido con «.htaccess«. Lo lógico a continuación es hacernos con el archivo «.htpasswd«
Una vez obtenido el contenido del archivo «.htpasswd» lo siguiente es crackear el password con John the Ripper. Nos logueamos en la carpeta secure y reto superado.
Rebuscando entre todo el caos que puede llegar a ser mi disco duro, he encontrado una serie de programas que utilizaba antiguamente cuando empezó a interesarme el Cracking. Ya sabéis que no soy partidario de crackear programas comerciales pero hoy voy a hacer una excepción ya que la versión del programa es muy vieja (1997) e incluso podría considerarse abandonware.
Este ejercicio es ideal para los que están empezando ya que es fácil localizar donde está el algoritmo y éste es sumamente sencillo.
Address Hex dump Command Comments
00402213 E8 78170000 CALL HEdit.00403990
........
004039C0 8BC1 MOV EAX,ECX
004039C2 99 CDQ
004039C3 33C2 XOR EAX,EDX
004039C5 2BC2 SUB EAX,EDX
004039C7 83E0 03 AND EAX,00000003
004039CA 33C2 XOR EAX,EDX
004039CC 2BC2 SUB EAX,EDX
004039CE 8A540C 04 MOV DL,BYTE PTR SS:[ECX+ESP+4] ;Coge el dígito i*3
004039D2 8A5C04 04 MOV BL,BYTE PTR SS:[EAX+ESP+4] ;Coge el dígito i
004039D6 8D4404 04 LEA EAX,[EAX+ESP+4] ;Guarda en memoria 12EE90
004039DA 32DA XOR BL,DL
004039DC 41 INC ECX ; i +=1
004039DD 81F9 00010000 CMP ECX,100 ;El bucle se repite 256 veces (0x100)
004039E3 8818 MOV BYTE PTR DS:[EAX],BL
004039E5 ^ 7C D9 JL SHORT HEdit.004039C0
004039E7 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4]
004039EB 85C0 TEST EAX,EAX ;Comprueba que el serial no sea 0
004039ED 7D 02 JGE SHORT HEdit.004039F1 ;Si es 0 se acabó
004039EF F7D8 NEG EAX
004039F1 3B8424 0C010000 CMP EAX,DWORD PTR SS:[ESP+10C] ;Comprobación de serial válido
004039F8 75 13 JNE SHORT HEdit.00403A0D ;Si no es igual bad boy
004039FA 85C0 TEST EAX,EAX ;Comprueba que el serial no sea 0
004039FC 74 0F JE SHORT HEdit.00403A0D ;Si es 0 se acabó
004039FE B8 01000000 MOV EAX,1
00403A03 5B POP EBX
00403A04 81C4 00010000 ADD ESP,100
00403A0A C2 0800 RETN 8
En resumen hace esto:
- Nombre introducido: deurus
- Convierte el nombre a mayúsculas
D E U R U S
44 45 55 52 55 53 (En Hexadecimal)
1) 55 xor 44 = 11
2) 53 xor 45 = 16
3) 00 xor 55 = 55
4) 00 xor 52 = 52
--------------- solo vale hasta aquí EAX(32 bits)
5) 00 xor 55 = 55
6) 00 xor 53 = 53
7) 00 xor 00 = 00
8) ...
HEX DEC
Serial = 52551611 = 1381307921
Como veis, realiza un bucle 256 veces pero como al final utiliza el registro EAX para hacer la comparación, solamente nos sirven las cuatro primeras operaciones. De hecho, no comprueba ni la longitud del nombre por lo que si introducimos un solo dígito como nombre, el serial será el valor ascii de ese dígito en decimal. La única comprobación que realiza es que el serial no sea 0.
var nombre = "deurus";
nombre = nombre.toUpperCase();
var serial = "";
serial = serial + nombre.charCodeAt(3).toString(16) + nombre.charCodeAt(2).toString(16);
serial = serial + (nombre.charCodeAt(5) ^ nombre.charCodeAt(1)).toString(16);
serial = serial + (nombre.charCodeAt(2) ^ nombre.charCodeAt(0)).toString(16);
serial = "Nº Serie: " + parseInt(serial,16);
document.write(serial);
Siguiendo con los crackmes que contienen RSA, esta vez tenemos un Keygenme del grupo PGC (Pirates Gone Crazy) que incluso servía para ser admitido en el grupo si mandabas la solución. Como veremos usa RSA32 + MD5 y en la parte de RSA ni siquiera usa el descifrado por lo que es de los sencillitos.
Resumen RSA
Parámetros
p = Primer número primo
q = Segundo número primo
e = Exponente público que cumpla MCD(e,(p-1)*(q-1))==1
n = Módulo público siendo n=p*q
d = Exponente privado que cumpla d=e^(-1) mod ((p-1)*(q-1))
De este modo e y n son la parte pública de la clave y d y n la parte privada. Los número primos p y q se utilizan solo para generar los parámetros y de ahí en adelante se pueden desechar.
Funciones de Cifrado/Descifrado
cifrado = descifrado ^ e mod n
descifrado = cifrado ^ d mod n
Debug
En las referencias de texto se ven a simple vista el exponente públicoe (10001) y el módulo n (8e701a4c793eb8b739166bb23b49e421)
Text strings referenced in RSA32+MD:.text
Address Disassembly Text string
00401848 PUSH RSA32+MD.00404104 ASCII "%.8x%.8x%.8x%.8x"
00401A72 PUSH RSA32+MD.0040429C ASCII "[PGCTRiAL/2oo2]"
00401AEE PUSH RSA32+MD.00404275 ASCII "10001"
00401AFE PUSH RSA32+MD.0040427B ASCII "8e701a4c793eb8b739166bb23b49e421"
00401B43 PUSH RSA32+MD.00404404 ASCII "Name Must Be >= 1 Character."
00401B57 PUSH RSA32+MD.00404421 ASCII "Key Must Be >= 1 Character."
00401B6D PUSH RSA32+MD.0040443D ASCII "Congratulations!"
00401B72 PUSH RSA32+MD.0040444E ASCII " You've done it!
Please send your keygen along with
source code to pgc@dangerous-minds.com
if you would like to be considered as
a new member of PGC."
00401BE7 PUSH 0 (Initial CPU selection)
00401C47 MOV [DWORD SS:EBP-24],RSA32+MD.00404119 ASCII "PGCWinClass"
00401C7C MOV [DWORD SS:EBP-24],RSA32+MD.0040424E ASCII "STATIC"
00401CDB PUSH RSA32+MD.00404115 ASCII "PGC"
00401CE0 PUSH RSA32+MD.00404119 ASCII "PGCWinClass"
00401D13 PUSH RSA32+MD.00404125 ASCII "EDIT"
00401D46 PUSH RSA32+MD.00404125 ASCII "EDIT"
00401DFB PUSH RSA32+MD.00404115 ASCII "PGC"
00401E00 PUSH RSA32+MD.0040424E ASCII "STATIC"
Como vemos comprueba que tanto el nombre como el número de serie tengan al menos un dígito y a continuación comienza el chequeo del serial. El chequeo es muy sencillo ya que ni siquiera tenemos que buscar los números primos p y q y a continuación n, simplemente podemos obtener el número de serie con la parte pública de la clave (par de número e y n). Lo resumimos a continuación:
Concatena nuestro nombre con la cadena «[PGCTRiAL/2oo2]»
Crea el hash MD5 de la cadena concatenada.
Cifra el hash usando el par de números e y n obtenidos en las referencias de texto.
//
// md5(deurus[PGCTRiAL/2oo2]) = dc8a39282da8539d11b8a6aec000c45a
//
var c = BigInt("0xdc8a39282da8539d11b8a6aec000c45a");
var e = BigInt("0x10001");
var n = BigInt("0x8e701a4c793eb8b739166bb23b49e421");
//
var serial = BigInt(0);
serial = powmod(c, e, n);
document.write(serial.toString(16));
//
//POWMOD
//
function powmod(base, exp, modulus) {
var accum = BigInt("1");
var i = BigInt("0");
var basepow2 = BigInt(base);
while ((BigInt(exp) >> BigInt(i) > BigInt(0))) {
if (((BigInt(exp) >> BigInt(i)) & BigInt(1)) == BigInt(1)) {
accum = (BigInt(accum) * BigInt(basepow2)) % BigInt(modulus);
}
basepow2 = (BigInt(basepow2) * BigInt(basepow2)) % BigInt(modulus);
i++;
}
return BigInt(accum);
}