Intro
Hoy tenemos aquí otro crackme sacado del baúl de los recuerdos. En este caso se trata de una protección por tiempo límite a través de un keyfile llamado «data.det«. Disponemos de tres días o nueve sesiones antes de que el crackme expire.
El algoritmo
La primera vez que ejecutamos el crackme, crea el fichero «data.det» y realiza lo siguiente:
- Lee el fichero data.det que inicialmente tiene 10 bytes a cero y el último byte un 60(`).
- Comprueba que tenga 11 bytes (B) y continúa.
- Al detectar el fichero vacío le mete valores codificandolos con XOR 6969. Los almacena en memoria 4030AB y siguientes.
00401000 t>/$ 6A 00 PUSH 0 ; /pModule = NULL
00401002 |. E8 0B020000 CALL <JMP.&KERNEL32.GetModuleHandleA> ; \GetModuleHandleA
00401007 |. A3 F4304000 MOV DWORD PTR DS:[4030F4],EAX ; kernel32.BaseThreadInitThunk
0040100C |. 6A 00 PUSH 0 ; /hTemplateFile = NULL
0040100E |. 68 80000000 PUSH 80 ; |Attributes = NORMAL
00401013 |. 6A 03 PUSH 3 ; |Mode = OPEN_EXISTING
00401015 |. 6A 00 PUSH 0 ; |pSecurity = NULL
00401017 |. 6A 00 PUSH 0 ; |ShareMode = 0
00401019 |. 68 000000C0 PUSH C0000000 ; |Access = GENERIC_READ|GENERIC_WRITE
0040101E |. 68 A2304000 PUSH timetria.004030A2 ; |FileName = "DATA.DET"
00401023 |. E8 DE010000 CALL <JMP.&KERNEL32.CreateFileA> ; \CreateFileA
00401028 |. 83F8 FF CMP EAX,-1
0040102B |. 74 07 JE SHORT timetria.00401034
0040102D |. A3 14314000 MOV DWORD PTR DS:[403114],EAX ; kernel32.BaseThreadInitThunk
00401032 |. EB 18 JMP SHORT timetria.0040104C
00401034 |> 6A 30 PUSH 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
00401036 |. 68 38304000 PUSH timetria.00403038 ; |Title = "I don't like this !"
0040103B |. 68 02304000 PUSH timetria.00403002 ; |Text = "Where is my DATA.DET file?\r\nI can't run without it..."
00401040 |. 6A 00 PUSH 0 ; |hOwner = NULL
00401042 |. E8 B3010000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
00401047 |. E9 22010000 JMP timetria.0040116E
0040104C |> 6A 00 PUSH 0 ; /pOverlapped = NULL
0040104E |. 68 E0304000 PUSH timetria.004030E0 ; |pBytesRead = timetria.004030E0
00401053 |. 6A 32 PUSH 32 ; |BytesToRead = 32 (50.)
00401055 |. 68 AB304000 PUSH timetria.004030AB ; |Buffer = timetria.004030AB
0040105A |. FF35 14314000 PUSH DWORD PTR DS:[403114] ; |hFile = NULL
00401060 |. E8 B9010000 CALL <JMP.&KERNEL32.ReadFile> ; \ReadFile
00401065 |. 833D E0304000 0B CMP DWORD PTR DS:[4030E0],0B
0040106C |. 0F85 E9000000 JNZ timetria.0040115B
00401072 |. BB AB304000 MOV EBX,timetria.004030AB
00401077 |. 68 E4304000 PUSH timetria.004030E4 ; /pSystemTime = timetria.004030E4
0040107C |. E8 97010000 CALL <JMP.&KERNEL32.GetSystemTime> ; \GetSystemTime
00401081 |. 803B 00 CMP BYTE PTR DS:[EBX],0
00401084 |. 75 22 JNZ SHORT timetria.004010A8 ; Si existe el fichero salta a las comprobaciones
00401086 |. 51 PUSH ECX
00401087 |. 33C9 XOR ECX,ECX
00401089 |. EB 15 JMP SHORT timetria.004010A0
0040108B |> 66:8B81 E4304000 /MOV AX,WORD PTR DS:[ECX+4030E4] ; |
00401092 |. 66:35 6969 |XOR AX,6969 ; |
00401096 |. 66:8981 AB304000 |MOV WORD PTR DS:[ECX+4030AB],AX ; |
0040109D |. 83C1 02 |ADD ECX,2 ; | Bucle de codificacion de data.det por primera vez
004010A0 |> 83F9 08 CMP ECX,8 ; |
004010A3 |.^ 76 E6 \JBE SHORT timetria.0040108B ; |
004010A5 |. 59 POP ECX ; kernel32.7580EE1C
004010A6 |. EB 3A JMP SHORT timetria.004010E2
Vigilando el proceso de creación del archivo podemos llegar a la conclusión de como se genera.
- Los dos primeros bytes son el año = 2014 = 0x7DE. 7DE XOR 6969 = 6EB7.
- Los dos siguientes son el mes = 10 = 0xA. A XOR 6969 = 6963.
- Los dos siguientes usa un 4 (día de la semana???) = 0x4. 4 XOR 6969 = 696D.
- Los dos siguientes son el día del mes = 2 = 0x2. 2 XOR 6969 = 696B
- Los dos siguientes usa un 1 = 0x1. 1 XOR 6969 = 6968.
- El número de sesiones lo deja como está, 60.
Estado de la memoria:
004030AB B7 6E 63 69 6D 69 6B 69 68 69 60 ·ncimikihi`
- Finalmente le resta 1 al número de sesiones y guarda el fichero.
004010E2 |> \A0 B5304000 MOV AL,BYTE PTR DS:[4030B5]
004010E7 |. 34 69 XOR AL,69
004010E9 |. 3C 00 CMP AL,0
004010EB |. /74 59 JE SHORT timetria.00401146
004010ED |. |FEC8 DEC AL
004010EF |. |A2 01304000 MOV BYTE PTR DS:[403001],AL
004010F4 |. |34 69 XOR AL,69
004010F6 |. |A2 B5304000 MOV BYTE PTR DS:[4030B5],AL
004010FB |. |6A 00 PUSH 0 ; /Origin = FILE_BEGIN
004010FD |. |6A 00 PUSH 0 ; |pOffsetHi = NULL
004010FF |. |6A 00 PUSH 0 ; |OffsetLo = 0
00401101 |. |FF35 14314000 PUSH DWORD PTR DS:[403114] ; |hFile = 00000034 (window)
00401107 |. |E8 18010000 CALL <JMP.&KERNEL32.SetFilePointer> ; \SetFilePointer
0040110C |. |6A 00 PUSH 0 ; /pOverlapped = NULL
0040110E |. |68 E0304000 PUSH timetria.004030E0 ; |pBytesWritten = timetria.004030E0
00401113 |. |6A 0B PUSH 0B ; |nBytesToWrite = B (11.)
00401115 |. |68 AB304000 PUSH timetria.004030AB ; |Buffer = timetria.004030AB
0040111A |. |FF35 14314000 PUSH DWORD PTR DS:[403114] ; |hFile = 00000034 (window)
00401120 |. |E8 05010000 CALL <JMP.&KERNEL32.WriteFile> ; \WriteFile
En cada ejecución realiza tres comprobaciones.
Recordemos el contenido del fichero:
B7 6E 63 69 6D 69 6B 69 68 69 60 ·ncimikihi`
1) Mes y año (4 primeros bytes)
004010A8 |> \8B0D AB304000 MOV ECX,DWORD PTR DS:[4030AB] ; ECX=69636EB7
004010AE |. 81F1 69696969 XOR ECX,69696969 ; 69636EB7 xor 69696969 = A07DE (A = mes y 7DE = año)
004010B4 |. A1 E4304000 MOV EAX,DWORD PTR DS:[4030E4]
004010B9 |. 3BC1 CMP EAX,ECX ; Compara con mes y año actuales
004010BB |. 0F85 85000000 JNZ timetria.00401146 ; Bad boy
2) Día (7º y 8º byte)
004010C1 |. 66:8B0D B1304000 MOV CX,WORD PTR DS:[4030B1] ; CX = 696B
004010C8 |. 66:81F1 6969 XOR CX,6969 ; 696B xor 6969 = 2
004010CD |. 66:A1 EA304000 MOV AX,WORD PTR DS:[4030EA] ; AX = día actual obtenido con GetSystemTime
004010D3 |. 66:2BC1 SUB AX,CX ; Los resta
004010D6 |. 66:83F8 03 CMP AX,3 ; Compara con 3
004010DA |. 77 6A JA SHORT timetria.00401146 ; Si el resultado >=3 Bad Boy
3) Sesiones (11º byte)
004010DC |. 2805 00304000 SUB BYTE PTR DS:[403000],AL ;
004010E2 |> A0 B5304000 MOV AL,BYTE PTR DS:[4030B5] ; AL = numero de sesiones actual
004010E7 |. 34 69 XOR AL,69 ; 61 Xor 69 = 8
004010E9 |. 3C 00 CMP AL,0 ; Compara con 0
004010EB |. 74 59 JE SHORT timetria.00401146 ; Salta si hemos superado las 9 sesiones. Bad boy
004010ED |. FEC8 DEC AL ; Si no le resta 1
004010EF |. A2 01304000 MOV BYTE PTR DS:[403001],AL
004010F4 |. 34 69 XOR AL,69 ; y le hace xor 69 para codificar el nuevo valor de sesión
004010F6 |. A2 B5304000 MOV BYTE PTR DS:[4030B5],AL
Con esto ya podemos alterar el archivo a nuestro antojo sin necesidad de parchear.
Keygen
Try
ano = ano Xor 26985
mes = mes Xor 26985
dia = dia Xor 26985
anos = Hex(ano).ToString
mess = Hex(mes).ToString
dias = Hex(dia).ToString
If txtsesiones.Text <= 255 Then
sesioness = Hex(sesiones)
Else
sesiones = 255
End If
sesioness = Hex(sesiones)
'key = 00 00 00 00 00 00 00 00 00 00 00
'key = año+año+mes+mes+X+X+dia+dia+X+sesiones
key = Chr(Convert.ToInt32(anos.Substring(2, 2), 16)) & Chr(Convert.ToInt32(anos.Substring(0, 2), 16)) _
& Chr(Convert.ToInt32(mess.Substring(2, 2), 16)) & Chr(Convert.ToInt32(mess.Substring(0, 2), 16)) _
& Chr(106) & Chr(105) _
& Chr(Convert.ToInt32(dias.Substring(2, 2), 16)) & Chr(Convert.ToInt32(dias.Substring(0, 2), 16)) _
& Chr(103) & Chr(105) _
& Chr(Convert.ToInt32(sesioness.Substring(0, 2), 16))
'Creo el archivo llave
Dim ruta As String = Application.StartupPath & "\DATA.DET"
If File.Exists(ruta) Then
File.Delete(ruta)
End If
Using sw As StreamWriter = New StreamWriter(ruta, True, System.Text.Encoding.Default)
sw.Write(key)
sw.Close()
End Using
MsgBox("DATA.DET generado correctamente", MsgBoxStyle.Information + MsgBoxStyle.OkOnly, "Info")
Catch ex As Exception
MsgBox("Ocurrió algún error" & vbCrLf & ex.Message)
End Try
Links
En el BTM anterior nos remontábamos al año 2006 para ver un pequeño gazapo ocurrido en la serie Dexter. En
Introducción Activar un botón en memoria Activar el botón de forma permanente Serial Hardcodeado Links Introducción Este crackme pertenece a
AperiSolve es un conjunto de herramientas de análisis esteganográfico que nos ayuda a echar un primer vistazo cuando sospechamos que
Karpoff.es Hace unos días intenté contactar con Karpoff ya que fué una inspiración para mi y muchos otros, lo conseguí