COMO CRAKEAR POR ESTADO+PORCINO |
CAPÍTULO
IV. Haciendo de Cerrajeros -Generadores de Llaves (KeyGen)- Revival 2.1 |
Mayo 1998
Indice |
INTRODUCCIÓN
Generadores de Llaves ┐Es posible crear un Generador de Llaves? ┐Pos mu bien, pero que necesito pa hacer un Generador de Llaves? ┐Merece la pena hacer un Generador? Generador de Llaves para REVIVAL 2.1: Notas para los lectores |
INTRODUCCIÓN íSaludos Familia! Aprovechando las vacas estivales me he decidido por escribir un bonito Generador de Llaves (en inglΘs KeyGen) para un ·til programa de reparaci≤n de discos duros y disquetes. Como siempre un poco de Teorφa para que podamos entendernos. |
Generadores de Llaves. La primera pregunta que responder es ┐quΘ carajo es un Generador de Llaves? Suponed por un instante que sois unos de esos programadores perezosos y cegados por el dinero que ha construido un programa protegido con un n·mero de serie. Si alguien desea registrarse debemos pagar una cifra de dinero (peque±a o no) que harß engrosar nuestra cuenta. A cambio debemos de enviarle un n·mero de serie que desbloquee el programa. ┐Hasta ahora todo correcto, verdad?. ┐Pero como demonios se genera un n·mero de serie diferente para cada usuario? . La respuesta es: con un Generador de Llaves.Existen dos tipos de Generadores de Llaves: A- Dependientes de los datos del cliente. B- Independientes de los datos del cliente. El tipo A es el mßs extendido, el n·mero de serie se genera a partir del nombre del cliente y el de su direcci≤n de correo (por ejemplo). Asφ dos usuarios tendrßn n·meros de serie diferentes, por que en principio sus datos personales son diferentes. El tipo B estß un poco en desuso, pero se siguen viendo por que son fßciles de programar (recordad que los programadores son por naturaleza vagos y sin imaginaci≤n). El mismo n·mero de serie es vßlido para cualquier cliente. En estos casos, el programador da un n·mero diferente a los clientes pardillos que compran su producto y reza para que no se lo den a nadie. |
┐Es posible crear un Generador de Llaves? El programa Generador de Llaves estß normalmente en el ordenata del programador, entonces, ┐c≤mo demonios puede un cracker construir un Generador ?. La respuesta es sencilla pero difφcil (en general) de realizar. El programa debe verificar que el n·mero de serie que introducimos es vßlido y Θsto s≤lo puede hacerlo verificando ciertas propiedades que debe cumplir el n·mero de serie y que fueron establecidas por el Generador. ┐Un poco lioso verdad?, dicho de otra forma, el Generador es un codificador de n·meros de serie y en el programa s≤lo existe un decodificador que descifra el n·mero de serie introducido. Vemos un sencillo ejemplo, suponed que nuestro Generador es el siguiente: N·meroSerie=(89934*4)*(nombre(5)) Donde nombre(5) es la quinta letra del nombre del usuario. EL n·mero 89934 es el llamado n·mero mßgico, un n·mero que es de agrado del programador (quizßs el n·mero de veces que le ha su jefe le ha jodido) y que realmente es el coraz≤n del Generador En el programa, para ver que el n·mero de serie es correcto se debe de verificar: (N·meroSerie/(4 /nombre(5)) = 89934 Como podΘis apreciar, lo que hay en el programa es la inversa del Generador, por tanto si invertimos la inversa podemos obtener el Generador de Partida. No os enga±Θis, este es un Generador sencillo, lo normal es que estΘ ultra enrevesao , lleno de n·meros mßgicos y operaciones aritmΘticas ex≤ticas. Normalmente, las rutinas de verificaci≤n realizan ciertas comprobaciones sobre la password de entrada. Generalmente pasan a may·sculas y buscan ciertos caracteres en ciertas posiciones. En caso de no encontrarlos la password no es vßlida. Esto da pie a un truco mu ·til pa localizar di una forma directa la rutina. Pero esto lo veremos mßs adelante. |
┐Pos mu bien, pero que necesito pa hacer un Generador de Llaves? 1.- Lo primero es aislar el c≤digo del programa que verifica el n·mero de serie.Ademßs del c≤digo que las funciones que son llamadas desde la rutina de verificaci≤n (pa Saber que narices hacen). Normalmente las rutinas de verificaci≤n hacen uso de peque±as rutinas: convertir a may·sculas,convertir letras en n·meros... 2.- Un conocimiento exhaustivo, repito, exhaustivo del la rutina de verificaci≤n. Debemos saber TODO lo que hace y porquΘ lo hace. Recordad que tenemos que invertir su funcionamineto y esto no lo podemos hacer si no sabemos como funciona. Este es el punto mßs delicado y el que consume mßs tiempo. Dependiendo de las paranoias del programador podΘis tardar horas o semanas. Se necesitan conocimientos de ensamblador y de operaciones aritmΘticas binarias 3.- Invertir el funcionamineto del Generador y crear con un compilador, por ejemplo de C nuestro propio Generador. |
┐Merece la pena hacer un Generador? La respuesta es depende. Hacer un Generador no es nada sencillo, consume mucho tiempo y habilidades. Es mucho mßs fßcil parchear la rutina de verificaci≤n para que acepte cualquier cosa.Pero las ventajas de crear un Generador son muy importantes, primera y ante todo es que realmente se estß cumpliendo con la filosofφa crack (ingenierφa inversa) al comprender y transformar el programa para que adapte a nuestras necesidades. Seg·nda ventaja son los conocimientos que se captan sobre todo a nivel ensamblador y de operaciones aritmΘricas con bits. Tercera y no mßs importante la satisfacci≤n del trabajo artesano, bien hecho. Esa satisfacci≤n que nos hace seguir adelante. La cuarta ventaja tiene que ver con la historia del Software. Puedes "coleccionar" las protecciones de tu programa favorito y ver la evoluci≤n de su software. Y como quinta un fin prßctico, al final del proceso se obtiene un n·mero de serie vßlido, lo que te convierte en un usuario "legal" y problamente no tengas que crakear la pr≤xima versi≤n. |
Generador de Llaves para REVIVAL 2.1
Objetivo: REVIVAL 2.1
Este es un interesante programa que te permite recuperar ficheros borrados de discos
duros y disquetes que soporta FAT32 y NTFS. Tiene una tφpica ventana de registro a partir de
la cual podemos acceder directamente a la rutina de verificaci≤n de la pass. Esta rutina es
extremadamente sencilla e independiente de los datos del usuario, por eso ha sido la
elegida como demostraci≤n. 0040AA6C call sub_40CD10 ; RUTINA DE VERIFICACI╙N 0040AA71 add esp, 4 0040AA74 test eax, eax 0040AA76 jz short loc_40AABA; SALTA SI ERES UN MAL CRACKER. 0040AA78 mov dword ptr [esi+5Ch], 1 0040AA7F mov eax, [esi+64h] 0040AA82 push eax 0040AA83 push offset aName;NOMBRE. 0040AA88 call sub_40AD70 0040AA8D add esp, 8 0040AA90 mov eax, [esi+60h] 0040AA93 push eax 0040AA94 push offset aCompany;COMPA╤═A. 0040AA99 call sub_40AD70 0040AA9E add esp, 8 0040AAA1 mov eax, [edi] 0040AAA3 push eax 0040AAA4 push offset aSerial;N┌MERO DE SERIE. 0040AAA9 call sub_40AD70 0040AAAE add esp, 8 0040AAB1 mov ecx, esi 0040AAB3 call sub_42550E 0040AAB8 jmp short loc_40AACF 0040AABA ; ─────────────────────────────────────────────────────────────────────────── 0040AABA 0040AABA loc_40AABA: ; CODE XREF: sub_40AA20+56_j 0040AABA push 0FFFFFFFFh 0040AABC push 30h 0040AABE push 0EF1Fh ; DIRECCION DEL MENSAJE DE ERROR 0040AAC3 call sub_431413 ; VENTANA DE MESAJE DE ERROR 0040AAC8 mov ecx, esi 0040AACA call sub_425527 0040AACF 0040AACF loc_40AACF: ; CODE XREF: sub_40AA20+98_j 0040AACF push 0FFFFFFFFh 0040AAD1 mov ecx, edi 0040AAD3 call sub_429A33 0040AAD8 pop edi 0040AAD9 pop esi 0040AADA retn 0040AADB ; ─────────────────────────────────────────────────────────────────────────── 0040AADB 0040AADB loc_40AADB: ; CODE XREF: sub_40AA20+25_j 0040AADB ; sub_40AA20+40_j 0040AADB push 0FFFFFFFFh 0040AADD push 30h 0040AADF push 0EF1Eh 0040AAE4 call sub_431413 0040AAE9 pop edi 0040AAEA pop esi 0040AAEB retn 0040AAEB sub_40AA20 endp Fijaos en el salto en :40AA76. Si saltamos caemos en la ventana de mensaje y evitamos acceder a NOMBRE,COMPA╤═A y N┌MERO DE SERIE. El salto estß controlado por :40AA6C call sub_40CD10 .Que interesante, una rutina que controla la ventana de mensaje de error, ┐a quΘ nos suena Θsto?. BINGO, estamos ante la rutina de verificaci≤n. ╔chem≤sle un vistazo y comentΘmosla. ;Desensamblado con el IDA ;p(0) indica el carßcter 0 de la password. Recordad, empiezo a contar los caracteres desde 0. 0040CD10 sub_40CD10 proc near ; CODE XREF: sub_404600+98_p 0040CD10 ; sub_40AA20+4C_p 0040CD10 0040CD10 var_24 = byte ptr -24h ; 1 variable local. 0040CD10 var_20 = word ptr -20h ; 2 variable local. 0040CD10 var_1E = byte ptr -1Eh ; 3 variable local. 0040CD10 var_1B = byte ptr -1Bh ; 4 variable local. 0040CD10 arg_0 = dword ptr 4 ; Argumento de la funci≤n que no es mßs que la direcci≤n de nuestra password. 0040CD10 0040CD10 sub esp, 24h; Ajusta la pila para reservar espacio para las varibles locales. 0040CD13 push ebx; Guarda algunos registros. 0040CD14 push esi 0040CD15 mov esi, [esp+2Ch+arg_0] ; esi= direcci≤n de nuestra password. 0040CD19 push edi 0040CD1A movsx eax, byte ptr [esi] ; eax=p(0) 0040CD1D push eax 0040CD1E call _toupper ; Pasamos a may·sculas p(0). 0040CD23 add esp, 4 0040CD26 cmp eax, 52h ; ┐ES P(0) = R? 0040CD29 jnz loc_40CE7F ; Salta a flag de error si p(0) no es R. 0040CD2F movsx eax, byte ptr [esi+1] ; eax=p(1) 0040CD33 push eax 0040CD34 call _toupper ; Pasamos a may·sculas p(1). 0040CD39 add esp, 4 0040CD3C cmp eax, 56h ; ┐ES P(1) = V? 0040CD3F jnz loc_40CE7F ; Salta a flag de error si p(1) no es V. 0040CD45 cmp byte ptr [esi+7], 2Dh ; ┐ES P(7) = '-'? 0040CD49 jnz loc_40CE7F ; Salta a flag de error si p(7) no es '-'. 0040CD4F push esi 0040CD50 call ds:lstrlenA ; Calcula el tama±o de la password. 0040CD56 cmp eax, 0Fh ; ┐Es el tama±o 15? 0040CD59 jnz loc_40CE7F ; Salta a flag de error si el tama±o no es 15 0040CD5F mov edi, 2 ; Segundo carßcter. 0040CD64 0040CD64 loc_40CD64: ; CODE XREF: sub_40CD10+6D_j ;Bucle para comprobar que son n·meros p(2)...p(6) 0040CD64 movsx eax, byte ptr [edi+esi]; eax=p(2) 0040CD68 push eax 0040CD69 call _isdigit ; ┐es un n·mero p(2)? 0040CD6E add esp, 4 0040CD71 test eax, eax 0040CD73 jz loc_40CE64 ; Salta con flag de error si p(2) no es n·mero. 0040CD79 inc edi ; Apuntamos al siguiente carßcter. 0040CD7A cmp edi, 7 ; ┐Hemos llegado a p(7)? 0040CD7D jl short loc_40CD64 ; Salta si no hemos llegado a p(7). 0040CD7F mov edi, 8 ; Octavo carßcter. ;Bucle para comprobar que son n·meros p(8)...p(14) 0040CD84 0040CD84 loc_40CD84: ; CODE XREF: sub_40CD10+8D_j 0040CD84 movsx eax, byte ptr [edi+esi];; eax=p(8) 0040CD88 push eax 0040CD89 call _isdigit ;┐es un n·mero p(8)? 0040CD8E add esp, 4 0040CD91 test eax, eax 0040CD93 jz loc_40CE6D ; Salta con flag de error si p(8) no es n·mero. 0040CD99 inc edi ; Apuntamos al siguiente carßcter. 0040CD9A cmp edi, 0Fh ; ┐Hemos llegado a p(15)? 0040CD9D jl short loc_40CD84; Salta si no hemos llegado a p(15). 0040CD9F mov ax, [esi+2] ; ax=p(2)p(3) 0040CDA3 mov [esp+30h+var_20], ax 0040CDA8 lea eax, [esp+30h+var_20] 0040CDAC mov [esp+30h+var_1E], 0 0040CDB1 push eax 0040CDB2 call _atoi ;Pasa p(2)p(3) a n·mero. 0040CDB7 mov cx, [esi+5] ;cx=p(5)p(6) 0040CDBB add esp, 4 0040CDBE mov [esp+30h+var_20], cx 0040CDC3 sub al, 13h ; al=p(2)p(3)-19 0040CDC5 lea ecx, [esp+30h+var_20] 0040CDC9 mov [esp+30h+var_24], al 0040CDCD mov [esp+30h+var_1E], 0 0040CDD2 push ecx 0040CDD3 call _atoi ;Pasa p(5)p(6) a n·mero. 0040CDD8 lea edx, [esp+34h+var_20]; 0040CDDC add esp, 4 0040CDDF lea ebx, [eax-25h] ;ebx=p(5)p(6)-37 0040CDE2 lea ecx, [esi+0Ah] ;ecx=direcci≤n de p(10) 0040CDE5 push edx 0040CDE6 mov eax, [ecx] ;ebx=p(10)p(11)p(12)p(13) 0040CDE8 mov [edx], eax 0040CDEA mov cl, [ecx+4] ;cl=p(14) 0040CDED mov [edx+4], cl 0040CDF0 mov [esp+34h+var_1B], 0 0040CDF5 call _atoi ;Pasa p(10)p(11)p(12)p(13)p(14) a n·mero. 0040CDFA add esp, 4 0040CDFD mov edi, eax 0040CDFF xor di, 5468h ;di=p(10)p(11)p(12)p(13)p(14) XOR 21508 0040CE04 mov ax, [esi+8] ;ax=p(8)p(9) 0040CE08 mov [esp+30h+var_20], ax 0040CE0D lea eax, [esp+30h+var_20] 0040CE11 mov [esp+30h+var_1E], 0 0040CE16 movzx edi, di 0040CE19 push eax 0040CE1A call _atoi ;Pasa p(8)p(9) a n·mero. 0040CE1F mov byte ptr [esp+34h+var_20], al 0040CE23 add esp, 4 0040CE26 xor eax, eax 0040CE28 mov ecx, 64h 0040CE2D mov al, bl ;al=p(5)p(6)-37 0040CE2F mov ebx, 0Ah 0040CE34 lea eax, [eax+edi+3]; eax'=(p(5)p(6)-37)+(p(10)p(11)p(12)p(13)p(14) XOR 21508) + 3 0040CE38 cdq 0040CE39 idiv ecx ;Divide eax'/100 0040CE3B mov cl, dl ;cl=resto(eax'/100) 0040CE3D xor eax, eax 0040CE3F mov al, [esp+30h+var_24] 0040CE43 lea eax, [eax+edi+3]; eax=(p(2)p(3)-19)+(p(10)p(11)p(12)p(13)p(14) XOR 21508) + 3 0040CE47 cdq 0040CE48 idiv ebx ;Divide eax/10 0040CE4A sub dl, [esi+4] ;dl=resto(eax/10)-p(4) 0040CE4D cmp dl, 0D0h ;┐Es resto(eax/10) = p(4)? 0040CE50 jnz short loc_40CE76;Salta a flag de error si resto(eax/10) no es p(4) 0040CE52 cmp byte ptr [esp+30h+var_20], cl;┐Es resto(eax'/100) = p(8)p(9)? 0040CE56 jnz short loc_40CE76;Salta a flag de error si resto(eax'/100) no es p(4) 0040CE58 mov eax, 1 ; Ok todo correcto. Flag de Θxito activado. 0040CE5D pop edi 0040CE5E pop esi 0040CE5F pop ebx 0040CE60 add esp, 24h 0040CE63 retn 0040CE64 ; ─────────────────────────────────────────────────────────────────────────── 0040CE64 0040CE64 loc_40CE64: ; CODE XREF: sub_40CD10+63_j 0040CE64 xor eax, eax ; Eres un mal chico.Flag de error activado. 0040CE66 pop edi 0040CE67 pop esi 0040CE68 pop ebx 0040CE69 add esp, 24h 0040CE6C retn 0040CE6D ; ─────────────────────────────────────────────────────────────────────────── 0040CE6D 0040CE6D loc_40CE6D: ; CODE XREF: sub_40CD10+83_j 0040CE6D xor eax, eax ; Eres un mal chico.Flag de error activado. 0040CE6F pop edi 0040CE70 pop esi 0040CE71 pop ebx 0040CE72 add esp, 24h 0040CE75 retn 0040CE76 ; ─────────────────────────────────────────────────────────────────────────── Antes de seguir adelante, centremonos en un par de puntos: - ┐HabΘis descubierto los n·meros mßgicos?, sip los hay son 5468h, 0Ah y 64h. - Como es tradici≤n la rutina checkea en este caso la presencia del carßcter '-'. Luego con un poco de paciencia, nuestra b·squeda inicial hubiera tenido sus frutos. - HabΘis notado la pΘsima calidad del c≤digo. Uso innecesario de variables, instrucciones in·tiles, tama±o del c≤digo exagerado. Todo esto es debido a que se program≤ en alto nivel, seguramente en C. ┐C≤mo quieren los programadores proteger su software si es de pΘsima calidad?. Estßn directamente vendidos (salvo honrosas excepciones, por supuesto.) - Si andais un poco pegaos de operacones aritmΘticas y de ensamblador, buscad alguno de los fabulosos cursos de ensamblador que hay en la Web. Resumamos los momentos mßs interesantes de la rutina de verificaci≤n: A)0040CD26 cmp eax, 52h ; ┐ES P(0) = R? B)0040CD3C cmp eax, 56h ; ┐ES P(1) = V? C)0040CD45 cmp byte ptr [esi+7], 2Dh ; ┐ES P(7) = '-'? D)0040CD56 cmp eax, 0Fh ; ┐Es el tama±o 15? E)0040CD64 ;Bucle para comprobar que son n·meros p(2)...p(6) F)0040CD84 ;Bucle para comprobar que son n·meros p(8)...p(14) G)0040CDC3 sub al, 13h ; al=p(2)p(3)-19 H)0040CDDF lea ebx, [eax-25h] ; ebx=p(5)p(6)-37 I)0040CE34 lea eax, [eax+edi+3] ; eax'=(p(5)p(6)-37)+(p(10)p(11)p(12)p(13)p(14) XOR 21508) + 3 J)0040CE3B mov cl, dl ; cl=resto(eax'/100) K)0040CE43 lea eax, [eax+edi+3] ; eax=(p(2)p(3)-19)+(p(10)p(11)p(12)p(13)p(14) XOR 21508) + 3 L)0040CE4D cmp dl, 0D0h ;┐Es resto(eax/10) = p(4)? M)0040CE52 cmp byte ptr [esp+30h+var_20], cl;┐Es resto(eax'/100) = p(8)p(9)?. Por A),B),C),D),E) y F) sabemos que la password debe de tener este aspecto: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 R V x x x x x - x x x x x x x x Donde x es un n·mero del 0 al 9. Despues hay dos bonitas ecuaciones: Por H),I),J) y M) I) p(8)p(9)=resto( (p(5)p(6)-0x25)+(p(10)p(11)p(12)p(13)p(14) XOR 21508) + 3) / 0x64) Por G),K),L) II) p(4)=resto((p(2)p(3)-0x13)+(p(10)p(11)p(12)p(13)p(14) XOR 21508) + 3) / 0x0A)Pos ya estß. Estas son las ecuaciones de la rutina de verificaci≤n, ya se puede implementar nuestro propio Generador de Llaves, que no serß mßs que implementar estas dos ecuaciones. Estas dos ecuaciones comprueban que la parte derecha sea igual a la parte izquierda (p(8)p(9) y p(4)). Nuestro Generador calculara la parte derecha y construirß la parte izquierda de forma adecuada. Se podrφan simplificar un poco, pero no lo harΘ pa no complicar el asunto. Un posible Generador en C serφa algo asφ como: |
Utilizo n·meros aleatorios (random) para generar un n·mero de serie diferente cada vez que se ejecute e programa. Una ·ltima curiosidad, donde creereis que guarda nuestra pass el programa. Si lanzais el La utilidad regmon (analiza todos los accesos al Registro dels Sistema) con el programa, podrΘis apreciar que se accede a "HKEY_LOCAL_MACHINE\SOFTWARE\Revival\Revival\2.0\Serial" Poco imaginativo, ┐verdad?. PodΘis modificar este n·mero para evitar registraos y probad Con nuevas pass. |
Notas para los lectores. 1.- Los mensajes del tipo "Hazme el crack para ....", "Dime como de crackea....", "Dime donde puedo encontrar..." son automßticamente ignorados. El objetivo de estos artφculos es ense±ar a crackear no ense±ar a ser unos llorones ineptos que s≤lo saben mendigar.2.- S≤lo responderΘ a preguntas te≤ricas sobre cracks, indicando algunas pistas que faciliten la labor. 3.- Narices, escribid artφculos sobre los programas que crackeeis. De nada sirve lo que aprendΘis si no lo repartφs, se os pudre en el cabeza, palabra. 4.- Lamento no haber contestado a ciertos mails interesantes. Desde aquφ mis excusas. 5.- Si os ha servido para algo mis artφculos, no seßis vagos y mandad un mail indicßndomelo. Mr.PinK & WKT ( WHISKEY KON TEKILA ) Esperamos vuestras opiniones, sugerencias y ensayos en estadoporcino@hotmail.com En breve analizaremos tipos de protecciones mucho más interesantes. Recordad bebed de la fuente, buscad a +ORC en la red. |
[ Entrada | Documentoz GenΘricoz | WKT TEAM Main Site ] |
[ Todo el ECD | x Tipo de Protecci≤n | x Fecha de Publicaci≤n | x orden AlfabΘtico ] |