INTRODUCCIÓN
Hace unos meses, MadAntrax hizo un crackme curioso, en el que el registro se hacía mediante un keyfile. Como nadie más parece haberse interesando en él, publico ya el tutorial que hice entonces.
Dicho autor es moderador del subforo de Visual Basic y yo he descargado varias de sus colaboraciones, con lo que ya me imaginaba que este crackme iba tener bastante complejidad.
El crackme está compilado con Visual Basic en P-Code, así que este tutorial puede resultar de utilidad para saber analizarlos.
El post original de este crackme es el siguiente:
http://foro.elhacker.net/ingenieria_inversa/madcrack_crackme_v1_by_madantrax-t225985.0.html
TUTORIAL
La verdad que los programas compilados en Visual Basic con P-Code suelen ser más difíciles de analizar. Voy a mostrar cómo examiné este primer crackme de MadAntrax y seguro que para muchos P-Code puede ayudar.
Si utilizamos RDG Packer Detector 0.65 vemos que está empacado con UPX y nos muestra que ha sido compilado con Visual Basic. Si se ejecuta el crackme vemos que aparece un archivo oculto llamado "iexplore.exe" y tenemos un cuadrado de color rojo que para que esté crackeado tiene que estár de color verde, según el autor.
Descompilar UPX es sencillo y en Crackmes y tutoriales hay un link de cómo descomprimir UPX para ReNewbies, realizado por Shaddy.
Yo descomprimí UPX pero al ejecutarlo ví que el archivo "iexplore.exe"(que no le gusta OllyDBG) no aparece y algunas cosas más que no voy a comentar, así que debe de hacer algo el crackme para saber que ha sido descomprimido. Por este motivo sólo debuggeé el crackme directamente desde OllyDBG con un simple plugin para ocultarlo. El OEP es muy sencillo de descubrir: 401130
Por otro lado, como ya tengo el crackme descomprimido con UPX, lo analicé con P32Dasm v2.3 y lo desensambla perfectamente, y se obtiene muchísima información:
Código:
VB6 Aplicación detectada ... PCode
Form1 Eventos:
2. splet
3. lel
6. crypt
8. Check_KeyFile
clsCRC Eventos:
2. AddBytes
3. AddString
4. Algorithm
5. Algorithm
6. CalculateBytes
7. CalculateFile
8. CalculateString
9. Value
10. Value
12. Clear
El autor nos deja mucha información.
Hay muchas cosas interesantes, por ej.
Código:
00003DE3: 0D VCallHresult App.Get_Path()
...
00003DEB: 1B LitStr: "edocyek\"
00003DEE: 0B ImpAdCallI2 StrReverse()
...
00003DF6: 2A ConcatStr
Es muy fácil de entender. Primero toma la ruta del crackme. Después de una cadena "edocyek\" hace la inversa (StrReverse) obteniendo "\keycode" y lo une a la ruta. Después con ese archivo hace unas determinadas operaciones y finalmente tenemos un salto (BranchF) que nos pone el cuadrado rojo o verde.
La dificultad de P-Code es que se trabaja con opcodes y puede resultar muy lioso pero con un poco de práctica se entiende todo fácilmente.
Voy a hacer un ejemplo. La subrutina que nos interesa es la que nos pone el cuadrado verde o rojo. Esta subrutina es la Form1 1.8 (Check_KeyFile-->nombre muy llamativo jeje) y comienza en 00003DA0.
He mostrado que nos da la ruta de un archivo denominado "keycode". Y después de esto viene lo más difícil, aparece lo siguiente:
Código:
00003E3A: 1B LitStr: "edocyek\"
00003E3D: 0B ImpAdCallI2 StrReverse()
00003E42: 23 FStStrNoPop var_D0
00003E45: 2A ConcatStr
00003E46: 46 CVarStr var_B4
00003E49: 25 PopAdLdVar
00003E4A: 04 FLdRfVar var_A4
00003E4D: FF3E VarLateMemCallLdRfVar
00003E55: 04 FLdRfVar var_100
00003E58: 0A ImpAdCallFPR4 Hex()
Lo más difícil es saber qué hace la función VarLateMemCallLdRfVar. Ni P32Dasm ni VB Decompiler nos da información, así que tiene que ser OllyDBG quién nos tenga que ayudar.
Como se observa, la función comienza por los opcodes FF3E y está en el offset 3E4D. Voy a cargar el crackme original en el OllyDBG.
Como el OEP es 401130 pongo un Hardware Breakpoint allí y pulso F9. Ahora estoy parado en el OEP.
Ahora tengo que parar antes de VarLateMemCallLdRfVar que está en 3ED4, por lo tanto como la image base está en 400000 pues la dirección final es 403ED4.
Parado en el OEP, voy a la ventana de dump, botón derecho goto --> 403ED4 (ahí tienes que ver ya los bytes FF 3E) y pongo un Breakpoint --> memory on access. Pulso F9 y se detiene en un
MOV AL,BYTE PTR DS:[ESI+2]
que está dentro de MSVBVM60.dll. Estamos justo antes de la llamada a VarLateMemCallLdRfVar.
Ahora simplemente hay que ir traceando con F7 hasta llegar a una Call ... y si miramos la pila observaremos algo parecido a esto:
Código:
0013F7EC 00402694 UNICODE "CalculateFile"
0013F7F0 00000001
0013F7F4 0013F804
0013F7F8 80000003
0013F7FC 0013F8D4
0013F800 0013F920
0013F804 00000008
0013F808 00000000
0013F80C 00174EF4 UNICODE "C:\Documents and Settings\usuario\Escritorio\keycode"
Como se observa, la función a la que hace referencia es a "CalculateFile"
Ya he mostrado cómo acceder desde el OllyDBG a cualquier opcode que nos muestre VB Decompiler Lite, así que cada uno ya puede examinar el código que quiera. Se pierde bastante tiempo sabiendo lo que hace cada cosa... también me ha costado a mi.
Si vamos ahora a VB Decompiler veremos que "CalculateFile" llama a la subrutina "CalculateBytes" y ésta última a su vez llama a la subrutina "AddBytes", que es la importante que interesa.
Ésta (AddBytes) tiene una función muy conocida y muy curiosa:
loc_4039A9: ImpAdCallFPR4 CallWindowProc(%x1, %x2, %x3, %x4, %x5)
A la que se le pasan 5 parámetros.
Ya sabéis parar antes de esta CallWindowProc, así que vamos a hacerlo.
Cuando estéis ahí, poner un BP en CallWindowProcA, F9 y mirar la pila:
Código:
0013EAB4 660FD37B /CALL to CallWindowProcA from MSVBVM60.660FD379
0013EAB8 0016E130 |PrevProc = 0016E130
0013EABC 00160628 |hWnd = 00160628
0013EAC0 00174E58 |Message = MSG(174E58)
0013EAC4 00176C48 |wParam = 176C48
0013EAC8 00000004 \lParam = 4
Hay que observar ese interesante PrevProc = 0016E130, así que vamos en la ventana de desensamblado a esa dirección y nos encontramos con lo siguiente:
Código:
0016E130 55 PUSH EBP
0016E131 89E5 MOV EBP,ESP
0016E133 57 PUSH EDI
0016E134 56 PUSH ESI
0016E135 50 PUSH EAX
0016E136 53 PUSH EBX
0016E137 51 PUSH ECX
0016E138 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
0016E13B 8B00 MOV EAX,DWORD PTR DS:[EAX]
0016E13D 8B75 0C MOV ESI,DWORD PTR SS:[EBP+C]
0016E140 8B7D 10 MOV EDI,DWORD PTR SS:[EBP+10]
0016E143 8B4D 14 MOV ECX,DWORD PTR SS:[EBP+14]
0016E146 31DB XOR EBX,EBX
0016E148 8A1E MOV BL,BYTE PTR DS:[ESI]
0016E14A 30C3 XOR BL,AL
0016E14C C1E8 08 SHR EAX,8
0016E14F 33049F XOR EAX,DWORD PTR DS:[EDI+EBX*4]
0016E152 46 INC ESI
0016E153 49 DEC ECX
0016E154 ^ 75 F2 JNZ SHORT 0016E148
0016E156 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+8]
0016E159 8901 MOV DWORD PTR DS:[ECX],EAX
0016E15B 59 POP ECX
0016E15C 5B POP EBX
0016E15D 58 POP EAX
0016E15E 5E POP ESI
0016E15F 5F POP EDI
0016E160 89EC MOV ESP,EBP
0016E162 5D POP EBP
0016E163 C2 1000 RETN 10
Éste es todo el código que utiliza para obtener un CRC del archivo "keycode". Después hace ya una última operación que es un NOT.
¿Y con qué se compara?
Bueno, es también bien fácil...
Subrutina Check_KeyFile
...
Código:
00003E7D: 3A LitVarStr: "2@G855G"
00003E82: 4E FStVarCopyObj var_B4
00003E85: 04 FLdRfVar var_B4
00003E88: 10 ThisVCallHresult --> %x2 = crypt(%x1) ;aquí está el truco
00003E8D: 04 FLdRfVar var_F0
00003E90: FB33 EqVarBool =
00003E92: 36 FFreeVar var_B4 var_F0
00003E99: 1C BranchF 00003EAA
Con toda esta explicación pienso que ya están destripadas las entrañas del crackme, espero que se entienda.
Yo a partir de este momento creé un programa en ensamblador que fuera examinando CRC's y descubrí que si el archivo keycode tiene los siguientes caracteres: "4R)@" queda el cuadrado perfectamente de color verde... objetivo logrado.
Un saludo
karmany
09 - septiembre - 2008