domingo, 1 de julio de 2012

[Tutorial] Keygen CrackMe Mr.Blood

Lo tenía pendiente desde hace algún tiempo...


 
Revisión


Lo primero es obtener el crackme, pueden descargarlo desde Aquí.

Lo primero que hice fué dar una revisión rápida al crackme y al fichero data. No muestra más que un código de 8 bytes.


 
Análisis

Decidido arranco el Crackme, y veo:
 
00401290  /$  55            PUSH EBP
00401291  |.  89E5          MOV EBP,ESP
00401293  |.  53            PUSH EBX
00401294  |.  81EC 84000000 SUB ESP,84
0040129A  |.  83E4 F0       AND ESP,FFFFFFF0
0040129D  |.  B8 00000000   MOV EAX,0
004012A2  |.  83C0 0F       ADD EAX,0F
004012A5  |.  83C0 0F       ADD EAX,0F
004012A8  |.  C1E8 04       SHR EAX,4
004012AB  |.  C1E0 04       SHL EAX,4
004012AE  |.  8945 A4       MOV [LOCAL.23],EAX
004012B1  |.  8B45 A4       MOV EAX,[LOCAL.23]
004012B4  |.  E8 87060000   CALL Crackme.00401940
004012B9  |.  E8 22030000   CALL Crackme.004015E0
004012BE  |.  C645 EF 00    MOV BYTE PTR SS:[EBP-11],0               ; |
004012C2  |.  C74424 04 003>MOV DWORD PTR SS:[ESP+4],Crackme.0040300>; |
004012CA  |.  C70424 023040>MOV DWORD PTR SS:[ESP],Crackme.00403002  ; |ASCII "data"
004012D1  |.  E8 AA070000   CALL                  ; \fopen
004012D6  |.  8945 B4       MOV [LOCAL.19],EAX
004012D9  |.  C745 E8 00000>MOV [LOCAL.6],0
004012E0  |>  837D E8 01    /CMP [LOCAL.6],1
004012E4  |.  7F 39         |JG SHORT Crackme.0040131F
004012E6  |.  C745 E4 00000>|MOV [LOCAL.7],0
004012ED  |>  837D E4 03    |/CMP [LOCAL.7],3                        ; |
004012F1  |.  7F 25         ||JG SHORT Crackme.00401318              ; |
004012F3  |.  8B45 E8       ||MOV EAX,[LOCAL.6]                      ; |
004012F6  |.  C1E0 02       ||SHL EAX,2                              ; |
004012F9  |.  0345 E4       ||ADD EAX,[LOCAL.7]                      ; |
004012FC  |.  8D55 F8       ||LEA EDX,[LOCAL.2]                      ; |
004012FF  |.  01D0          ||ADD EAX,EDX                            ; |
00401301  |.  8D58 F8       ||LEA EBX,DWORD PTR DS:[EAX-8]           ; |
00401304  |.  8B45 B4       ||MOV EAX,[LOCAL.19]                     ; |
00401307  |.  890424        ||MOV DWORD PTR SS:[ESP],EAX             ; |
0040130A  |.  E8 61070000   ||CALL                 ; \getc
0040130F  |.  8803          ||MOV BYTE PTR DS:[EBX],AL
00401311  |.  8D45 E4       ||LEA EAX,[LOCAL.7]
00401314  |.  FF00          ||INC DWORD PTR DS:[EAX]
00401316  |.^ EB D5         |\JMP SHORT Crackme.004012ED
00401318  |>  8D45 E8       |LEA EAX,[LOCAL.6]
0040131B  |.  FF00          |INC DWORD PTR DS:[EAX]
0040131D  |.^ EB C1         \JMP SHORT Crackme.004012E0
0040131F  |>  8B45 B4       MOV EAX,[LOCAL.19]                       ; |
00401322  |.  890424        MOV DWORD PTR SS:[ESP],EAX               ; |#Dirección de stack donde almacena la recogida
00401325  |.  E8 36070000   CALL                 ; \fclose

En mi caso, es almacenado en 0022FF38.


 
Profundizando


Si continuo traceando...

0040132A  |.  C745 E4 00000>MOV [LOCAL.7],0
00401331  |>  837D E4 03    /CMP [LOCAL.7],3
00401335  |.  7F 2A         |JG SHORT Crackme.00401361
00401337  |.  8B4D E4       |MOV ECX,[LOCAL.7]
0040133A  |.  8D45 F8       |LEA EAX,[LOCAL.2]
0040133D  |.  0345 E4       |ADD EAX,[LOCAL.7]
00401340  |.  83E8 08       |SUB EAX,8
00401343  |.  0FB610        |MOVZX EDX,BYTE PTR DS:[EAX]             ;   #Movemos byte[posicionActual] (leido de antes)
00401346  |.  B8 07000000   |MOV EAX,7                               ;  EAX=7 (Len)
0040134B  |.  2B45 E4       |SUB EAX,[LOCAL.7]
0040134E  |.  0FB64428 F0   |MOVZX EAX,BYTE PTR DS:[EAX+EBP-10]      ;  movemos a eax el ultimo byte (byte[len(byte) - posicionActual])
00401353  |.  8D0402        |LEA EAX,DWORD PTR DS:[EDX+EAX]
00401356  |.  89448D C8     |MOV DWORD PTR SS:[EBP+ECX*4-38],EAX     ;  Guardamos suma de los 2 bytes en [EBP+ECX*4-38]
0040135A  |.  8D45 E4       |LEA EAX,[LOCAL.7]
0040135D  |.  FF00          |INC DWORD PTR DS:[EAX]                  ;  Siguiente
0040135F  |.^ EB D0         \JMP SHORT Crackme.00401331

Es la base del algoritmo. Lo que hace el Señor Sangre, es sumar el 1º byte con el 8º, el 2º con el 7º etc. Si hechamos un vistazo al buffer donde se almacena, podremos ver nuestro serial creado, y al ser de serial único, prefiero no regalarlo

Sigamos.
 
00401361  |> \C70424 500000>MOV DWORD PTR SS:[ESP],50                ; ||||||||
00401368  |.  E8 E3060000   CALL                ; |||||||\putchar
0040136D  |.  C70424 610000>MOV DWORD PTR SS:[ESP],61                ; |||||||
00401374  |.  E8 D7060000   CALL                ; ||||||\putchar
00401379  |.  C70424 730000>MOV DWORD PTR SS:[ESP],73                ; ||||||
00401380  |.  E8 CB060000   CALL                ; |||||\putchar
00401385  |.  C70424 730000>MOV DWORD PTR SS:[ESP],73                ; |||||
0040138C  |.  E8 BF060000   CALL                ; ||||\putchar
00401391  |.  C70424 3A0000>MOV DWORD PTR SS:[ESP],3A                ; ||||
00401398  |.  E8 B3060000   CALL                ; |||\putchar
0040139D  |.  C70424 200000>MOV DWORD PTR SS:[ESP],20                ; |||
004013A4  |.  E8 A7060000   CALL                ; ||\putchar
004013A9  |.  8D45 B8       LEA EAX,[LOCAL.18]                       ; ||
004013AC  |.  83C0 0C       ADD EAX,0C                               ; ||
004013AF  |.  894424 10     MOV DWORD PTR SS:[ESP+10],EAX            ; ||
004013B3  |.  8D45 B8       LEA EAX,[LOCAL.18]                       ; ||
004013B6  |.  83C0 08       ADD EAX,8                                ; ||
004013B9  |.  894424 0C     MOV DWORD PTR SS:[ESP+C],EAX             ; ||
004013BD  |.  8D45 B8       LEA EAX,[LOCAL.18]                       ; ||
004013C0  |.  83C0 04       ADD EAX,4                                ; ||
004013C3  |.  894424 08     MOV DWORD PTR SS:[ESP+8],EAX             ; ||
004013C7  |.  8D45 B8       LEA EAX,[LOCAL.18]                       ; ||
004013CA  |.  894424 04     MOV DWORD PTR SS:[ESP+4],EAX             ; ||
004013CE  |.  C70424 073040>MOV DWORD PTR SS:[ESP],Crackme.00403007  ; ||ASCII "%i %i %i %i"
004013D5  |.  E8 66060000   CALL                  ; |\scanf

Generamos la cadena "Pass: " caracter por caracter manualmente, y pasamos a recojer 4 valores enteros.


Toque final

004013ED  |> /837D E8 03    /CMP [LOCAL.6],3
004013F1  |. |7F 24         |JG SHORT Crackme.00401417
004013F3  |. |8B4D E8       |MOV ECX,[LOCAL.6]
004013F6  |. |B8 03000000   |MOV EAX,3
004013FB  |. |89C2          |MOV EDX,EAX
004013FD  |. |2B55 E8       |SUB EDX,[LOCAL.6]
00401400  |. |8B448D B8     |MOV EAX,DWORD PTR SS:[EBP+ECX*4-48]     ;  Buffer con nuestro serial falso
00401404  |. |3B4495 C8     |CMP EAX,DWORD PTR SS:[EBP+EDX*4-38]     ;  ¿Te suena esta dirección? Buffer con serial generador
00401408  |. |74 06         |JE SHORT Crackme.00401410               ;  Buen chico
0040140A  |. |C645 EF 01    |MOV BYTE PTR SS:[EBP-11],1
0040140E  |. |EB 07         |JMP SHORT Crackme.00401417              ;  Chico Malo
00401410  |> |8D45 E8       |LEA EAX,[LOCAL.6]
00401413  |. |FF00          |INC DWORD PTR DS:[EAX]                  ;  Siguiente.
00401415  |.^\EB D6         \JMP SHORT Crackme.004013ED

Ahí vemos que compara los bytes falsos por los bytes generados en el algoritmo.
Me pareció un serialme simple pero entretenido...


 
Zona 0


Esta es el código del Keygen, programado en VB (Por pereza)
 
Option Explicit

Private Sub Form_Load()
Dim B1 As String
Dim B2 As String
Dim i As Integer

Open "c:\data" For Binary As #1
    B1 = Space(LOF(1))
    Get #1, , B1
Close #1
For i = 1 To 4
    B2 = Asc(Mid(B1, i, 1)) + Asc(Mid(B1, Len(B1) - (i - 1), 1)) & vbCrLf & B2
Next
MsgBox B2, vbInformation
End Sub

Un Saludo!

No hay comentarios:

Publicar un comentario