1. Abrimos el simple_KGM y buscamos las apis en el olly , umm GetDlgItemInt y dos GetDlgItemText , bueno pongamos los breakpoints.
2. Coge nuestro ID, y mira si eax es 0 (eax en ese momento es el largo del nombre) , si es 0 va al chico malo,si nó, le resta 0D4h y lo guarda en la memoria [404674]
3. Coge nuestro serial y mira si eax es 0(eax en ese momento es el largo del serial),si es 0 va al chico malo, si nó, lo guarda en [404678]
4. Coge nuestro nombre y mira si eax es 4, si es mas bajo , chico malo, si nó, mira si eax es 20, si es más grande chico malo... De aquí deducimos que nuestro nombre debe tener entre 4 y 20 carácteres , ni más ni menos.Una vez hecho esto va cogiendo cada byte de nuestro nombre y le hace estas operaciones:
Código
El call que hay ahí en medio:
MOV EDI,EAX XOR EDX,EDX XOR ESI,ESI MOV ECX,1 LOOP: INC EDX MOVZX EAX,BYTE PTR DS:[EDX+4042D3] CMP EDX,EDI XOR EDX,EDX ADD EAX,ESI SHL EAX,4 ADD EAX,10001 PUSH EAX ; /Arg1 CALL 00401283 ; \Simple_KGM_2.00401283 ADD ESI,EAX INC ECX CMP ECX,20 JNE LOOP
Código
Después del loop , compara el resultado de todas las operaciones con [404674] , adivinad quien había en la posición de memoria, el valor de nuestro ID -04Dh ,con lo que si hacemos un keygen para eso tendriamos que pedir el nombre , hacer las rutinas de calculo para el ID , y sumarle 04Dh , ya que cuando lo metemos en el programa se lo resta.
PUSH EBP ; Simple_KGM_2.00401283(guessed Arg1) MOV EBP,ESP PUSH ECX MOV EAX,DWORD PTR SS:[ARG.1] MOV ECX,666 CICLO: ADD EAX,68656865 ROR EAX,8 SUB EAX,65686568 ROL EAX,16 MOV EBX,EAX NOT EAX SUB EBX,EAX ADC EAX,EBX ROR EAX,6 LOOP CICLO ADD EAX,61733376 XOR EAX,76337361 NOP NOP NOP NOP NOP NOP NOP AND EAX,0000FFFF SHL EAX,10 MOV AX,0DEAD SUB EAX,D00EA00D POP ECX LEAVE RETN 4
Hasta ahí bien , he hecho mitad del keygen para eso, nos pide el nombre y el te calcula el ID:
Código
Despues , lo que hace es con wsprintf , pasa lo que hay en eax , o sea nuestro ID , a una cadena en notación hexadecimal, y seguidamente , hay una rutina en la que hacen operaciones con un valor que no es constante !!! , cambia , y ese valor lo cogen con lo que retorna la api , VirtualAlloc pasandole estos parámetros, pero es que siempre da un valor diferente , y para hacer un keygen como sé cual es ese valor?
.386 ; Hace el código compatible con el procesador 386 .MODEL flat,stdcall INCLUDE user32.inc INCLUDE kernel32.inc INCLUDE msvcrt.inc INCLUDELIB user32.lib INCLUDELIB kernel32.lib INCLUDELIB msvcrt.lib ;PARA TENER LOS BUFFERS __p__iob PROTO C _iobuf STRUCT _ptr DWORD ? _cnt DWORD ? _base DWORD ? _flag DWORD ? _file DWORD ? _charbuf DWORD ? _bufsiz DWORD ? _tmpfname DWORD ? _iobuf ENDS FILE TYPEDEF _iobuf ;PROTOTIPOS DE FUNCIONES EN C EXTRN printf:NEAR EXTRN fgets:NEAR EXTRN sscanf:NEAR EXTRN getchar:NEAR EXTRN strlen:NEAR ;PROTOTIPOS DE FUNCIONES EN ASM .data ;Datos del programa INGRESA_NOMBRE BYTE "Ingresa tu nombre: ",0 TU_ID_ES BYTE "Tu ID es: %u",0Ah,0Dh,0 PULSE_TECLA BYTE "Pulse intro para terminar . . .",0 ;ESPECIFICADORES DE FORMATO ESPI BYTE "%d",0 ESPS BYTE "%s",0 ESPIU BYTE "%u",0 .data? NOMBRE BYTE 20 DUP (0) ID DWORD ? BUFFER_FGETS BYTE 20 DUP(0) stdin DWORD ? stdout DWORD ? stderr DWORD ? .code rutinaSerial PROC PUSH EBP MOV EBP,ESP PUSH ECX MOV EAX,[EBP+8] MOV ECX,666h CICLO: ADD EAX,68656865h ROR EAX,8h SUB EAX,65686568h ROL EAX,16h MOV EBX,EAX NOT EAX SUB EBX,EAX ADC EAX,EBX ROR EAX,6h LOOP CICLO ADD EAX,61733376h XOR EAX,76337361h AND EAX,0000FFFFh SHL EAX,10h MOV AX,0DEADh SUB EAX,0D00EA00Dh POP ECX leave ret rutinaSerial endp .code ;Código del programa main PROC ;Buffers call __p__iob mov stdin,eax ; #define stdin (&__iob_func()[0]) add eax,SIZEOF(FILE) mov stdout,eax ; #define stdout (&__iob_func()[1]) add eax,SIZEOF(FILE) mov stderr,eax ; #define stderr (&__iob_func()[2]) ;Inicio código. push OFFSET INGRESA_NOMBRE push OFFSET ESPS call printf push stdin push 20 push OFFSET BUFFER_FGETS call fgets push OFFSET NOMBRE push OFFSET ESPS push OFFSET BUFFER_FGETS call sscanf push OFFSET NOMBRE call strlen MOV EDI,EAX XOR EDX,EDX XOR ESI,ESI MOV ECX,1 L1: INC EDX MOVZX EAX,NOMBRE[EDX-1] CMP EDX,EDI JNE L2 XOR EDX,EDX L2: ADD EAX,ESI SHL EAX,4h ADD EAX,10001h PUSH EAX CALL rutinaSerial ADD ESI,EAX INC ECX CMP ECX,20h JNE L1 add eax,0D4h mov ID,EAX push ID push OFFSET TU_ID_ES call printf push OFFSET PULSE_TECLA push OFFSET ESPS call printf call getchar invoke ExitProcess,0 ret main endp END main
Pongo las rutinas que decía:
Código
CPU Disasm Address Hex dump Command Comments 004011AA |. 50 PUSH EAX ; /<%08X> 004011AB |. 68 16404000 PUSH OFFSET 00404016 ; |Format = "%08X" 004011B0 |. 68 F4454000 PUSH OFFSET 004045F4 ; |Buf 004011B5 |. E8 1A010000 CALL <JMP.&user32.wsprintfA> ; \USER32.wsprintfA 004011BA |. 83C4 0C ADD ESP,0C 004011BD |. FF35 3E404000 PUSH DWORD PTR DS:[40403E] ; /Arg3 = 290000 004011C3 |. 6A 10 PUSH 10 ; |Arg2 = 10 004011C5 |. 68 F4424000 PUSH OFFSET 004042F4 ; |Arg1 = ASCII "12345" 004011CA |. E8 F4020000 CALL 004014C3 ; \Simple_KGM_2.004014C3
Y los parametros que se le pasan a la api:
Código
Bueno no hay problema , la cogeré con virtualprotect o algo de eso.
Address Hex dump Command Comments 00401326 |. 6A 04 PUSH 4 ; /Protect = PAGE_READWRITE 00401328 |. 68 00100000 PUSH 1000 ; |AllocType = MEM_COMMIT 0040132D |. 6A 54 PUSH 54 ; |Size = 84. 0040132F |. 6A 00 PUSH 0 ; |Address = NULL 00401331 |. E8 30110000 CALL <JMP.&kernel32.VirtualAlloc> ; \KERNEL32.VirtualAlloc