Como obtener un número de serie para el HexDecCharEditor v1.02
Como parchearlo para que acepte cualquier número.
Como hacer un KeyGenerator
By Black Fenix
HexDecChar Editor es un editor hexadecimal y decimal que ocupa relativamente poco y su uso es bastante sencillo. Por lo que si te gusta, recuerda compraló :) .

Bienvenido a mi segundo tutorial sobre cracking, en esta entrega vamos a usar tres metodos diferentes para crackear el programa es cuestión:

El primero y más sencillo se trata de conseguir un numero válido para el nombre que introduzcamos a partir del trazado del programa, sin modificación ninguna de este.
El segundo metodo mas complicado se trata de hacer que el programa acepte cualquier número de serie que le introduzcamos modificando para ello el ejecutable (recuerda esto está prohibido).
El tercero y más complicado se trata crear nuestro propio programa que genere numeros de serie válidospara el nombre que le introduzcamos (esto es lo que hacen los verdaderos crackers).

necesita.gif (15203 bytes)

Images/marcador.gif (1024 bytes)SoftIce para Windows
Images/marcador.gif (1024 bytes) W32Dasm
Images/marcador.gif (1024 bytes) Turbo Pascal (Para el Key Generator)

Nota: Puedes encontrar algunas de estas tools en www.astalavista.box.sk, el HexDecCharEditor lo puedes descargar de www.beyersdorf.com

comenza.gif (16493 bytes)

Images/marcador.gif (1024 bytes) Ejecutamos el HexDecCharEditor y nos aparece un ventana (NAG) en la que nos avisa de que esta versión es de evaluación de 30 días. Vemos que hay un botón que pone Enter Key, hacemos click en el y nos aparece un cuadro de dialogo donde podemos introducir nuestro nombre y el numero de registro. Escribimos nuestro nombre ej: Black Fenix, y la llave pej: 12345. Pulsamos Ok y que tenemos, Un cuadro de dialogo que entre otras cosas dice:

"Sorry, but the name an the key you entered cannot be accepted together."

Bueno ya tenemos algo por donde empezar, le decimos que vale y salimos del programa.

Images/marcador.gif (1024 bytes) Vamos a buscar las posibles referencias a esta cadena dentro del EXE por lo que desensamblamos el EXE con el W32Dasm. Pulsamos en el botón StrnRef y buscamos la cadena en la lista que nos aparece, cuando la encontremos (esta por abajo) hacemos doble click sobre esta y el W32Dasm nos llevará al primer sitio donde hay una posible referencia a esta cadena (aunque hagamos más veces doble click no nos moveremos del sitio ya que no hay más referencias a esta cadena).Ahora podemos ver el código que es algo como esto:

* Referenced by a (U)nconditional or (C)onditional jump at address: |:0043589C
:004358AAB8D05B4300mov eax,00435BD0
:004358AFE8BC9DFFFFcall 0042F670

 

Bueno, tiene toda la pinta de ser lo que buscamos ya que debajo hay una llamada que posiblemente será la que muestre el cuadro de dialogo con la cadena "Sorry.... ". Ya que estamos aquí podemos ver en la linea superior que hay un salto que hace referencia a la dirección 4358AA podemos ver donde esta en la linea donde dice "Referenced by ..."al final muestra una sola dirección que es la 43589C, esta dirección está un poco más arriba por lo que nos moveremos hacia arriba hasta en contrar dicha posición, veremos algo así:

:0043588EEB24jmp 4358b4
* Referenced by a (U)nconditional or (C)onditional jump at address: |:0043585C
:00435890E89F23FDFFcall 00407C34
:0043589583BBD80100007cmp dword ptr [ebx+000001D8],00000007
:0043589C750Cjne 004358AA

 

Hmmm, una comparación y un salto despues de una llamada a una función, parece sospechoso ya que este salto nos envia al cuadro de dialogo directamente, pero también podemos ver que aquí solo se puede entrar desde un salto que se hace en43585C ya que por encima de la llamada hay un jmp (salto incondicional) por lo que es lógico suponer que esta comparación no es exactamente la que buscamos aun que si que tenga algo que ver. Nos vamos a la linea donde se hace el salto (43585C) y contemplamos lo siguiente.

:00435855 E8EEC2FFFF call 00431B48
:0043585A 84C0 test al,al
:0043585C 7432 je 00435890
:0043585E ........... mov byte ptr [00456520],1
:00435865 ........... mov dword ptr [ebx+128],1
:0043586F ........... cmp dword ptr [ebx+1D8],7
:00435876 ........... jne 00435884

Bueno, esta si que tiene toda la pinta ya que la llamada y la comprobacion deALson mucho más sospechosas que la anterior, ademas si nos fijamos en el resto del código podremos ver que hay cadenas escritas en alemán ya que este programa permite seleccionar el idioma inglés o el alemán. Por lo que es posible que utilice una variable global para indicarlo y asi saber si debe mostrar los mensajes en uno u otro idioma, Examinando los saltos que hay por esta zona vemos que hay una comparación bastante usada y es: cmp dword ptr [ebx+000001D8],00000007, si nos fijamos los saltos que vienen después de esta comparación nos envian a partes de código que hacen referencia a cadenas escritas en alemán, por lo que ya sabemos que estos saltos los podemos descartar (por eso el primer salto lo he descartado). Bueno ahora ya sabemos casi con toda seguridad donde se realiza la comprobación del número de registro, por lo que apuntaremos la dirección que está al lado del call 00431B48en este caso es 435855.

La primera aproximación...

Images/marcador.gif (1024 bytes) Cerramos el W32Dasm y nos vamos al SI, antes ejecutaremos el HexDecCharEditor y iremos hasta el cuadro de dialogo de registro, introduciremos un nombre y una clave ej:

Name : Black Fenix
Key : 12345

Antes de pulsar en Ok activamos el SI (Ctrl+D). De lo que se trata ahora es interrumpir la ejecución del programa en la dirección 435855, si intentamos establecer un BPX con bpx 435855 sin haber entrado con el SI en la zona de memoria donde está situado el programa, el SI nos dirá "invalid address" por lo que debemos interrumpir el programa de alguna otra manera para poder entrar en su zona de memoria.
Esto es fácil ya que
podemos poner un BPX en HMEMCPY(usada por Windows para copiar cadenas ) y despues ir trazando con F12 hasta llegar a la zona donde esta nuestro programa. Pues venga un bpx en hmemcpy salimos del SI (Ctrl+D) y pulsamos en OK.

Boom!, de nuevo en el SI y antes de que aparezca ningun cuadro de dialogo. Ahora estamos en KERNEL32.DLL vamos a salir de aquí pulsando F12 hasta que podamos ver que nos encontramos en el código fuente de nuestro programa (debera poner
HEXDECCHAREDITOR!CODE+XXXXXXXX). Ok estamos en la zona que buscamos ahora podemos borrar el BPX al HMEMCPY y establecer uno nuevo en la dirección 435855 con BPX 435855. Pulsamos g+Enter para seguir con la ejecución normal del programa y Boom! ya estamos donde queriamos, ahora vamos a examinar la llamada. Pulsamos F8 y estaremos dentro, a primera vista parece una rutina bastante compleja ya que podemos ver un gran numero de llamadas a otras partes del programa pero vamos a pensar a lo facil y buscaremos (para navegar por la ventana de codigo usaremos el mouse o Ctrl+Cursor adecuado) la primera comparación que encontremos después de una llamada. vamos trazando con F10 poco a poco hasta encontrar:

CALL 00405AC8
CMP ESI,EAX
JNZ 0431D17

Hmmm, podria ser esta?, comprobemos los valores de ESI y EAX tecleando:

? esi Enter
? eax Enter

ESI= 6345Fh -> 406623 -> Adininas ?
EAX= 3039h -> 12345 -> Vaya es IGUAL que nuestro numero de registro :)

Bueno creo que lo hemos encontrado, esta comparando nuestro numero de registro (en mi caso 12345) con otro numero (posiblemente el bueno). Comprobemoslo, salimos del SI, y el programa nos dara el mensaje de que no sirve nuestro numero , ahora ponemos el numero con el cual era comparado el nuestro y !!SORPRESA!!El programa está registrado.

La segunda aproximación...

Si lo que quieres es que el programa acepte cualquier numero habra que eliminar la llamada previa al CMP ESI,EAX y hacer un XOR de EAX y otro de ESI para ponerlos a 0 antes de la comparación más un NOP para que quede todo correcto (el call ocupa 5 bytes los XOR cada uno 2 bytes y el NOP 1 byte sumando un total de 5). Posteriormente deberas hacer los cambios en el ejecutable con un editor Hexadecimal que puede ser el mismo que hemos crackeado jejejejeje :)

La tercera aproximación, lo que un verdadero cracker debe saber hacer ...

Para los más avanzados que quieran hacer un generador de numeros pueden encontrar como lo hace el programa a partir de la dirección 431AC4 en adelante.
Aquí podeis ver un volcado de la rutina que se encarga de esto:
El estado de los registros utilizados al llegar a este punto es el siguiente:

eax,esi = Longitud del nombre introducido en caracteres
edx = Puntero al nombre introducido
edi = 1
ebp-4 = Puntero al nombre introducido
ebp-8 = Puntero a un dword que será donde se almacene el numero de serie válido.

:00431AC4 mov ebx, 00000001 -> carga contador principal de caracteres

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00431B01(C)

|

:00431AC9 mov ecx, ebx -> copia contador principal al secundario
:00431ACB dec ecx -> decrementa en 1 contador secundario
:00431ACC and ecx, 8000000F -> comprueba si el numero es negativo
:00431AD2 jns 00431AD9 -> salta si no lo es a 431AD9
:00431AD4 dec ecx -> creo que esto no llega a ejecutarse
:00431AD5 or ecx, FFFFFFF0 -> nunca
:00431AD8 inc ecx -> si la longitud de la cadena es -> mayor que 1 (siempre hay caracteres ) -> por lo que no puede ser negativo.

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00431AD2(C)

:00431AD9 lea eax, dword ptr [ebx+edi] -> suma al contador de caracteres principal 1 y -> pone el resultado en eax
:00431ADC push ecx -> guarda contador secundario
:00431ADD mov ecx, 00000112 -> prepara ecx con 112h=274 para multiplicar
:00431AE2 cdq -> extiende el signo de eax a eax:edx -> para multiplicar con signo
:00431AE3 idiv ecx -> multiplica (contador de caracteres+1)*112h
:00431AE5 pop ecx -> restaura contador secundario de caracteres
:00431AE6 mov al, byte ptr [edx+0045480C] -> usa la parte alta como indice a una tabla -> de valores preconstruida-> y guarda este valor en AL
:00431AEC mov edx, dword ptr [ebp-04] -> Carga puntero al nombre introducido
:00431AEF mov dl, byte ptr [edx+ebx-01] -> lee siguiente caracter de la cadena -> recordar que EBX es el contador principal -> de caracteres
:00431AF3 xor al, dl -> Hace un XOR sobre el valor de la tabla pre-> construida con el valor del caracter -> de la cadena
:00431AF5 and eax, 000000FF -> realiza un AND sobre EAX para que este -> quede sólo con el valor de AL
:00431AFA shl eax, cl -> por último desplaza a la izquierda -> en un numero igual al contador -> secundario de caracteres
:00431AFC add dword ptr [ebp-08], eax -> suma el resultado al codigo final -> que está en ebp-8. Nota: en el primer -> paso ebp-8 valdrá 0 ya que es inicializado -> por el programa antes de llamar -> a la rutina que cálcula el número
:00431AFF inc ebx -> incrementa contador principal de caracteres
:00431B00 dec esi -> decrementa el numero de caractereas procesados
:00431B01 jne 00431AC9 -> salta , si hay más ( esi <> 0 )

Basicamente la rutina es bastante sencilla, utiliza un contador de caracteres con el cual realiza un calculo usando un valor constante (112h) y usa una parte del resultado como indice a una tabla de caracteres precalculadosde la cual obtiene un valor, este valor lo hace servir para realizar otra serie de calculos con el valor ASCII del caracter que se esta procesando y así obtener un resultado que suma al codigo definitivo.
El
problema reside en la tabla de numeros precalculada que esta almacenada a partir de la dirección 45480C. Yo me pregunto si tiene algun limite en la longitud del nombre que se le puede introducir ya que de este depende el índice con el que se accede a la tabla, pero por las pruebas que he hecho parece una tabla muy grande por lo menos de 1024 valores, En principio creo que el programa no hace ningún calculo sobre la longitud máxima del nombre.
En que nos afecta esto a nosotros ? Pues bien,
debemos copiar dicha tablapara poder crear el programa que genere numeros válidos, pero, ¿Como sabemos cuantos valores copiar? Este es el problema, no vamos a matarnos en copiar todos los valores, además no sabemos que longitud puede tener esta tabla , pero parece muy larga, por lo que yo he optado por copiar una cantidad suficiente de esta (unos 90 valores).

keygen.gif (14559 bytes)

Aquí teneis el programilla final en Pascal con un poquitin de assembler. Podeis encontrar el ejecutable compilado junto con este documento se llama HexDeck.exe

Program HexDecChar_KeyGenerator;

Uses Crt;
Const Table:array [0..92] of byte= ($34,$a0,$d5,0,$f7,$24,$5d,$5c,$0a,$8c,$10,$d6,$9e,$b5,$9c,$66,0

,$24,$6f,$20,$44,$4d,$a2,$f0,$10,$27,$55,$20,$E7,$F7,$E8,$A3,$47,

$F9,$14,$AC,$E8,$44,$98,$2C,$53,$58,$EB,$FE,$25,$B0,$FC,$4E,$77,

$CC,$66,$49,$DA,$7C,$C6,$8E,$D1,$5C,$22,$D9,$C5,$C8,$90,$E4,$BF,

$B4,$79,$87,$7E,$3E,$3D,$76,$A3,$D6,$08,$43,$1A,$52,$20,$6B,$EC,

$5E,$FE,$A9,$23,$05,$F5,$C8,$77,$54,$3F,$AC,$DB);

Var

Count2,TabIndex:integer;

i:word;

CharTab,CharName:byte;

Codigo,ResChar:Longint;

Name:string[90];

Begin

Writeln;
textcolor(7);
Writeln('HexDecChar Editor v1.02 Key Generator by Black Fenix.');
Writeln('-----------------------------------------------------');
Write('Enter your name (max 90 chars):');
readln(Name);
Codigo:=0;


For i:=1 to length(Name) do
Begin

Count2:=i;
Dec(Count2);
Count2:=Count2 and $8000000F;

if Count2<0 then
Begin

dec(Count2);
Count2:=Count2 or -10;
inc(Count2);

End;

{ Nota: los codigos de operación de 386 no estan permitidos en el Turbo Pascal 7.0 por lo que debemos usar la directiva db para introducir el código de operación de }
{ la instrucción deseada, ¿ Si no sabes algo de assembler que coño haces leyendo esto ?}

asm

db $66 { esto expande la instrucción siguiente a xor eax,eax }
xor ax,ax
mov ax,i
db $66 { esto expande la instrucción siguiente a inc eax }
inc ax
db $66 { esto expande la instrucción siguiente a xor ecx,ecx }
xor cx,cx
mov cx,$112
db $66,$99 { esto añade la instrucción CDQ }
db $66 { esto expande la instrucción siguiente a idiv ecx }
idiv cx
mov TabIndex,dx { coge el resultado para usarlo como indice }

end;

CharTab:=Table[TabIndex];
CharName:=ord(Name[i]);
ResChar:=(CharTab XOR CharName) and $ff;
ResChar:=ResChar shl Count2;
Codigo:=Codigo+ResChar;

End;

Write('Your registration number is:');
textcolor(15);
Write(codigo);
textcolor(7);

End.


You are inside Reversed Minds pages.

por Mr. Silver / WKT!
La información aquí vertida es exclusivamente para uso educacional, no puedo hacerme responsable del uso que se haga de esta, por lo que atiendo a la honradez de cada uno :), recuerda que debes comprar el software que utilices :)