KeyGenME fary - v1.0

Iniciado por fary, 8 Enero 2019, 21:05 PM

0 Miembros y 3 Visitantes están viendo este tema.

karmany

#30
La verdad que esta clase de retos te distrae de la tareas cotidianas, así que he decidido distraerme un poco y hacer un keygen (generador de claves) para todos los seriales SOLO de 6 caracteres. Este keygen no lo he querido programar (sería muy sencillo) y lo voy a hacer escrito para que todo el mundo sin conocimientos de programación pueda usarlo.

Solo he utilizado caracteres imprimibles desde el valor 20hex hasta el 7Fhex, los demás los he obviado.
¿Cómo lo he resuelto? Pues hice directamente en OllyDBG fuerza bruta, me fui a cenar y después de cenar estudié los resultados que el script me dejó en memoria, así que es un keygen post-estudio.

Empecemos.
1º CARÁCTER
El que el usuario quiera. Voy a poner, por ejemplo, la letra v que equivale a 76hex. Los guiones siguientes, aunque puedan valer, en este caso no sirven y los pongo únicamente para mostrar los caracteres pendientes.
v-----

Antes de continuar con los siguientes caracteres, es necesario saber que según el valor hex de este primer caracter, existen 3 zonas.
PRIMERA ZONA. ZONA 4A. Del valor 68h al 7Fh (a.i.)
SEGUNDA ZONA. ZONA 4B. Del valor 1Fh al 7Fh (a.i.)
TERCERA ZONA. ZONA 4C. Del valor 1Fh al 27h (a.i.)

Para que sea sencillo de entender, pongo el ejemplo de la letra v=76h. El valor 76h puede estar:
-En la zona 4A (Del 68h al 7Fh) y
-En la zona 4B (Del 1Fh al 7Fh) pero no puede estar en la zona 4C.

2º y 5º CARACTERES
Estos caracteres son siempre fijos y corresponden a las letras R y X. Por lo tanto, ya tenemos:
vR--X-

3º CARÁCTER
Solo puede ser o los dos puntos : o la letra zeta minúscula (z).
Solo hay una condición:
Si el primer carácter es par, el 3º carácter es la letra zeta minúscula (z), si no : .
Por lo tanto, el primer carácter es la v que equivale a 76hex y es par, así que el 3º carácter es una z. Ya tenemos:
vRz-X-

4º CARÁCTER
El 4º carácter corresponde con la Zona. Así que podemos tener 2 casos para ZONA 4A (J) y ZONA 4B (K).
vRzJX-
vRzKX-

6º Y ÚLTIMO CARÁCTER
Realizamos las operaciones de cifrado del serial hasta el último carácter, así:
PRIMER SERIAL: vRzJX-
v = 76h
R = 52h
z = 7Ah
J = 4Ah
X = 58h

Código (asm) [Seleccionar]
EDI = 0    ; EDI = 00000000h
ADD EDI, 76; EDI = 00000076h
ROR EDI, D ; EDI = 03B00000h
ADD EDI, 52; EDI = 03B00052h
ROR EDI, D ; EDI = 02901D80h
ADD EDI, 7A; EDI = 02901DFAh
ROR EDI, D ; EDI = EFD01480h
ADD EDI, 4A; EDI = EFD014CAh
ROR EDI, D ; EDI = A6577E80h
ADD EDI, 58; EDI = A6577ED8h
ROR EDI, D ; EDI = F6C532BBh


Y ahora tan sencillo como restar la semilla F6C53333 con ese valor:
F6C53333 - F6C532BB = 78hex
6º carácter = 78h (x), por lo tanto, primera contraseña válida:
vRzJXx

SEGUNDO SERIAL: vRzKX-
v = 76h
R = 52h
z = 7Ah
K = 4Bh
X = 58h

Código (asm) [Seleccionar]
EDI = 0    ; EDI = 00000000h
ADD EDI, 76; EDI = 00000076h
ROR EDI, D ; EDI = 03B00000h
ADD EDI, 52; EDI = 03B00052h
ROR EDI, D ; EDI = 02901D80h
ADD EDI, 7A; EDI = 02901DFAh
ROR EDI, D ; EDI = EFD01480h
ADD EDI, 4A; EDI = EFD014CBh
ROR EDI, D ; EDI = A65F7E80h
ADD EDI, 58; EDI = A65F7ED8h
ROR EDI, D ; EDI = F6C532FBh


F6C53333 - F6C532FB = 38hex = 8
Segundo serial válido: vRzKX8

Otro ejemplo rápido sin tanta explicación:
3-----
solo está en ZONA 4B: 3--K--
2 caracteres fijos: 3R-KX-
impar: 3R:KX-

F6C53333 - F6C532D9 = 5Ah = Z
Serial válido: 3R:KXZ

fary

#31
Cita de: Geovane en 12 Enero 2019, 18:40 PM


ya que hizo en asm, podía escribir isDebuggerPresent() en asm, no api.
mov     eax, large fs:30h
movzx   eax, byte ptr [eax+2]
retn


Si te fijas, compruebo si estoy siendo debugeado dos veces... una llamando a la propia API y otra vez lo compruebo mientras estoy creando los objetos de la ventana :) aunque creo que nadie se tomo cuenta de eso...

Aquí os el código fuente!

Código (asm) [Seleccionar]
format PE GUI 4.0
entry start

include 'win32w.inc'

section '.text' code readable executable
start:
   invoke  GetModuleHandle,0
   mov     [wc.hInstance],eax
   invoke  LoadIcon,0,IDI_APPLICATION
   mov     [wc.hIcon],eax
   invoke  LoadCursor,0,IDC_ARROW
   mov     [wc.hCursor],eax
   invoke  RegisterClass,wc
   test    eax,eax
   jz      error

   invoke IsDebuggerPresent,0    ; ACTIVAR despues de depurar
   cmp eax,0
   jne end_loop

   invoke  CreateWindowEx,0,_class,_title,WS_VISIBLE+WS_DLGFRAME+WS_SYSMENU,128,128,256,100,NULL,NULL,[wc.hInstance],NULL
   test    eax,eax
   jz      error

   msg_loop:
       invoke  GetMessage,msg,NULL,0,0
       cmp     eax,1
       jb      end_loop
       jne     msg_loop
       invoke  TranslateMessage,msg
       invoke  DispatchMessage,msg
       jmp     msg_loop

 error:
       invoke  MessageBox,NULL,_error,NULL,MB_ICONERROR+MB_OK

 end_loop:
       invoke  ExitProcess,[msg.wParam]

proc WindowProc uses ebx esi edi, hwnd,wmsg,wparam,lparam
       cmp     [wmsg],WM_DESTROY
       je      .wmdestroy
       cmp     [wmsg],WM_CREATE
       je      .wmcreate
       cmp     [wmsg],WM_COMMAND
       je      .wmcommand

       jmp .defwndproc

 .wmcommand:
       xor eax, eax
       xor edx, edx

       mov eax, [_buttonregistry]
       mov edx, [lparam]

       cmp eax,edx
       jne .finish

       invoke GetWindowTextA,[_editregistry],password,10

       stdcall checkpass,password ; Comprobamos la contraseña.

       jmp .finish
 .defwndproc:
       invoke  DefWindowProc,[hwnd],[wmsg],[wparam],[lparam]
       jmp     .finish
 .wmcreate:
       invoke CreateWindowExA,WS_EX_APPWINDOW,_labelclass,_labeltext,WS_CHILD+WS_VISIBLE,10,10,150,20,[hwnd],NULL,[wc.hInstance],NULL
       mov edx,dword[fs:0x18]
       push edx
       invoke CreateWindowExA,WS_EX_APPWINDOW,_editclass,0,WS_CHILD+WS_VISIBLE+WS_BORDER,115,10,125,20,[hwnd],NULL,[wc.hInstance],NULL
       mov [_editregistry],eax
       pop edx
       mov edx,dword[edx+0x30]
       push edx
       invoke CreateWindowExA,WS_EX_APPWINDOW,_buttonclass,_buttonname,WS_CHILD+WS_VISIBLE,10,40,230,20,[hwnd],NULL,[wc.hInstance],NULL
       mov [_buttonregistry],eax
       pop edx
       movsx edx,byte[edx+2]
       mov [dbg],edx    ; Si esta debugger presente

       jmp .finish
 .wmdestroy:
       invoke  PostQuitMessage,0
       xor     eax,eax
 .finish:
       ret
endp

proc checkpass,pass
   mov esi, [pass]

   compute_hash:
       xor     edi, edi     ;EDI = 0
       xor     eax, eax   ;EAX = 0
       cld
   compute_hash_again:
       lodsb                ;AL = BYTE[ESI] , ESI = ESI + 1
       test    al, al
      jz       compute_hash_finished
       ror     edi, 0xD
       add     edi, eax
      jmp      compute_hash_again
   compute_hash_finished:

   ;EDI = El Hash de la cadena
   cmp edi,0xF6C53333
   jne salircheck
   mov eax, [dbg]
   cmp eax,1
   je salircheck

   invoke MessageBoxA,0,_goodpass,_goodtitle,MB_OK+MB_ICONINFORMATION

   salircheck:
   ret
endp

section '.data' data readable writeable

 _class        TCHAR 'KeyGenMe Fary',0
 _title        TCHAR 'Fary KeyGenME - 1.0',0
 _error        TCHAR 'Startup failed.',0
 _goodpass     db    'Enhorabuena, superaste el reto!ahora el keygen ;)',0
 _goodtitle    db    'Good Boy',0

 _buttonregistry       dd ?
 _buttonclass          db 'BUTTON',0
 _buttonname           db 'Registrar',0

 _editregistry         dd ?
 _editclass            db 'EDIT',0

 _labelclass           db 'STATIC',0
 _labeltext            db 'Fary Password: ',0

  password             rb 11
  dbg                  dd 0

 wc WNDCLASS 0,WindowProc,0,0,NULL,NULL,NULL,COLOR_BTNFACE+1,NULL,_class

 msg MSG

section '.idata' import data readable writeable

 library kernel32,'KERNEL32.DLL',\
         user32,'USER32.DLL'

 include 'api\kernel32.inc'
 include 'api\user32.inc'


También quiero aclarar que el código que crear los hashes no es mio! pero me parecio interesante  >:D >:D >:D

https://foro.elhacker.net/programacion_visual_basic/asmvb6invoke_llamas_apis_sin_declararlas_kinvokebas-t290072.0.html

Aunque claro, veté tu a saber quién sea el autor porque por aquí también aparece el mismo hash  :xD

https://github.com/debasishm89/x86-Assembly/blob/master/speaking%20shell%20code.asm

Entre otras páginas...
Un byte a la izquierda.

Geovane

#32
Fary , usted tiene razón, hay segunda verificación, en la confirmación de la contraseña
felicitaciones.

karmany , "Este keygen no lo he querido programar (sería muy sencillo)"
eso es un poco divertido
Si es simple muestre la lógica de creación de una contraseña!
Lo que mostró, basta mirar en el EDI, en el debugger!

Saludos


Para servicios, envíe un mensaje privado, sólo para servicios en curso hasta fecha de 10/06/2019

karmany

#33
Bueno, he creado este simple generador de claves para 6 caracteres, usando solo la zona 4B. Unicamente el usuario debe escribir el primer carácter de (20hex hasta 7Fhex) y el resto lo calcula el programa.
Para no usar registros EDI ni nada por el estilo, he escrito la fórmula en un Excel. Os lo pongo en descarga.


Descarga del Excel:
https://mega.nz/#!i5YwSYLI!koy5ybfMZG1Op0v7-Ui8c3NdNIsvjU5R2tQW_4pOfuQ

Un saludo.
No puedo dedicar nada más de tiempo a este keygen. Espero el keygen de Geovane, que es muy interesante lo que explicó.

Geovane

#34
Gracias karmany por compartir, realmente tiempo es un problema, cuando el desafío exige mucho tiempo de nosotros

Aquí esta Keygen
Parece que "reinventó la rueda", con las funciones ....

El propósito y analizar lo más profundo posible en la lógica
Pero tiene como mejorar mucho el código.
Agradecimientos especiales a todos los que participaron en este desafío.
Aprendí mucho, con todos.

¿Quién puede mejorar el código, favor dice

Código (delphi) [Seleccionar]
function HexToBin(Hex: String): String;
var
  Bin: String;
  k: Byte;
Begin
  Bin:='';
  For k:=1 to Length(Hex) do
     if      Hex[k]='0' then Bin:=Bin+'0000'
     else if Hex[k]='1' then Bin:=Bin+'0001'
     else if Hex[k]='2' then Bin:=Bin+'0010'
     else if Hex[k]='3' then Bin:=Bin+'0011'
     else if Hex[k]='4' then Bin:=Bin+'0100'
     else if Hex[k]='5' then Bin:=Bin+'0101'
     else if Hex[k]='6' then Bin:=Bin+'0110'
     else if Hex[k]='7' then Bin:=Bin+'0111'
     else if Hex[k]='8' then Bin:=Bin+'1000'
     else if Hex[k]='9' then Bin:=Bin+'1001'
     else if Hex[k]='A' then Bin:=Bin+'1010'
     else if Hex[k]='B' then Bin:=Bin+'1011'
     else if Hex[k]='C' then Bin:=Bin+'1100'
     else if Hex[k]='D' then Bin:=Bin+'1101'
     else if Hex[k]='E' then Bin:=Bin+'1110'
     else if Hex[k]='F' then Bin:=Bin+'1111';
  HexToBin:=Bin;
End;

function BinToHex(Bin: String): String;

var
  k: Byte;
  s: String;
  Hex: String;
Begin
  Hex:='';
  While Length(Bin) mod 4<>0 do Bin:='0'+Bin;
  For k:=0 to Length(Bin) div 4 -1 do
  Begin
     s:=Copy(Bin,k*4+1,4);
     if      s='0000' then s:='0'
     else if s='0001' then s:='1'
     else if s='0010' then s:='2'
     else if s='0011' then s:='3'
     else if s='0100' then s:='4'
     else if s='0101' then s:='5'
     else if s='0110' then s:='6'
     else if s='0111' then s:='7'
     else if s='1000' then s:='8'
     else if s='1001' then s:='9'
     else if s='1010' then s:='A'
     else if s='1011' then s:='B'
     else if s='1100' then s:='C'
     else if s='1101' then s:='D'
     else if s='1110' then s:='E'
     else if s='1111' then s:='F';
     Hex:=Hex+s;
  End;
  BinToHex:=Hex;
End;

function StrToHex(Str: String): Integer;
var
  Hex:Integer;
Begin

  if (str.Length=7) Then
  Begin
       str:='0' + str;
  end;

  if (str.Length=6) Then
  Begin
       str:='00' + str;
  end;

  Hex:=       (strToInt(copy(Str,1,1))*128);
  Hex:= Hex + (strToInt(copy(Str,2,1))*64);
  Hex:= Hex + (strToInt(copy(Str,3,1))*32);
  Hex:= Hex + (strToInt(copy(Str,4,1))*16);
  Hex:= Hex + (strToInt(copy(Str,5,1))*8);
  Hex:= Hex + (strToInt(copy(Str,6,1))*4);
  Hex:= Hex + (strToInt(copy(Str,7,1))*2);
  Hex:= Hex + (strToInt(copy(Str,8,1))*1);
  StrToHex:=Hex;
end;

function shLeft(Str:String;N:integer): String;
var
  s:String;
Begin
        s:=copy(Str,N+1,32-N)+copy(Str,1,N);
        shLeft:=s;
  end;

procedure TForm1.Button1Click(Sender: TObject);
     var
        A,B:String;
        C:Integer;
Label
rotacionar,ciclo;
                     //F6C53333    Caractere >=32 <=126  $20 $7E
begin
     A:= 'F6C53333';
     B:= HexToBin(A);

     ciclo:
     // 8 bits
     C:= strToHex(copy(B,25,8));
     IF (C>31) and (C<127) Then
     Begin
       Edit1.text:= (intTohex(C,2)) + Edit1.text ;
       B:= (Copy(B,1,24)) + '00000000';
       GOTO rotacionar;
     end;  // fin 8 bits


     //7 bits
     C:= strToHex(copy(B,26,7));
     IF (C>31) and (C<127) Then
     Begin
       Edit1.text:= (intTohex(C,2)) + Edit1.text;
       B:= (Copy(B,1,25)) + '0000000';
       GOTO rotacionar;
     end;   //fin 7 bits


     //6 bits  (Con 6 bits positivos no passa valor $7E  No precisa testar con 5)
     C:= strToHex(copy(B,27,6));
     IF (C>31) and (C<127) Then
     Begin
       Edit1.text:=  (intTohex(C,2)) + Edit1.text;
       B:= (Copy(B,1,26)) + '000000';
       GOTO rotacionar;
     end;    //fin 6 bits


     rotacionar:
     IF ((Copy(B,1,32)) <> '00000000000000000000000000000000') Then
     begin
       B:=shLeft(B,13);
       goto ciclo;
      //Showmessage(B);
     end;
end;                        


Esto se basa en la lógica que ya he posteado

F6C53333      11110110110001010011001100110011
                                                                         110011 33---3
                     11110110110001010011001100000000
                     10100110011000000001111011011000 58---X
                                                               
                     10100110011000000001111010000000
                     00000011110100000001010011001100 4C---L
                                                                 
                     00000011110100000001010010000000
                     00000010100100000000000001111010 7A---z
                                                     
                     00000010100100000000000000000000
                                                           0000001010010 52---R  

RzLX3


En texto, función, después al final .......

Código (delphi) [Seleccionar]
Function HexToStr(s: String): String;
Var i: Integer;
Begin
 Result:=''; i:=1;
 While i<Length(s) Do Begin
   Result:=Result+Chr(StrToIntDef('$'+Copy(s,i,2),0));
   Inc(i,2);
 End;
End;


Código (delphi) [Seleccionar]
Showmessage(hexTostr(Edit1.text));

Fary ¡Muy bueno su codigo, excelente desafío !!!!!

Actualización 1

Usted puede intentar con otro valor.
Pero el valor necesita estar correctamente construido, mediante función inversa!


Para evitar este error, antes rotacionar:
¿Por qué con 6 bits no encontró valor válido !!!!



Código (delphi) [Seleccionar]

    Showmessage('¡Hummmm, valor incorrecto !!!!!');
    rotacionar:
     IF ((Copy(B,1,32)) <> '00000000000000000000000000000000') Then
     begin
       B:=shLeft(B,13);
       goto ciclo;
      //Showmessage(B);
     end;




Gracias, Saludos
Para servicios, envíe un mensaje privado, sólo para servicios en curso hasta fecha de 10/06/2019

karmany

#35
¡¡Excelente trabajo Geovane!!
Tu punto de vista ha sido muy instructivo e interesante.

Gracias a tu idea se me ha ocurrido lo siguiente que no se si se podrá generalizar para otros caracteres o tamaños de serial.

Partimos del último carácter que me invento: 8 que es 38hex
Inicio: F6C53333

Código (cpp) [Seleccionar]
F6C53333 - 38   = F6C532FB; //38hex es el carácter 8
ROL F6C532FB, D = A65F7ED8

Y ahora voy restanto 7/8 bits como tu mencionas:
A65F7ED8 - 58   = A65F7E80; //58hex es el caracter X
ROL A65F7E80, D = EFD014CB
EFD014CB - 4B   = EFD01480; //4Bhex es el caracter K
ROL EFD01480, D = 02901DFA
02901DFA - 7A   = 02901D80; //7Ahex es el caracter z
ROL 02901D80, D = 03B00052
03B00052 - 52   = 03B00000; // 52hex es el caracter R
ROL 00000076, D = 00000076
00000076 - 76   = 00000000; //76hex es el caracter v


Por lo tanto, el serial válido es vRzKX8

Un saludo
Good work!

MCKSys Argentina

Y así es como, de un reto "simple", se puede aprender mucho...

Felicitaciones y agradecimientos para todos los involucrados.

Saludos!
MCKSys Argentina

"Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."


Geovane

Hello friends

Hasta ahora tenemos un keygen que busca el primer serial válido.
Tenemos uno que busca mediante fuerza bruta


¿Dónde está lo que busca la contraseña correcta?

Recuerda a los amigos (ver los bits !!!)


Tengo la solución, voy a publicar si nadie encuentra.

Saludos.

Para servicios, envíe un mensaje privado, sólo para servicios en curso hasta fecha de 10/06/2019

apuromafo CLS

Cita de: fary en 11 Enero 2019, 23:10 PM
Ya que esta esto resuelto, diré que la contraseña maestra es: f4RyKeY    :laugh:
;-)