- Introducción
- Herramientas disponibles
- CrkViz-1 (Serial a la vista)
- CrkViz-2 (Parcheando rutina aleatoria)
- CrkViz-3 (Nag+Keygen)
- CrkViz-4 (Límite de ejecuciones+Keygen)
- CrkViz-5 (Serial a la vista)
- Notas finales
- Enlaces
Introducción
Esta vez vamos a analizar los CrackMes de un antiguo colaborador de Karpoff Spanish Tutor, CrkViZ. En estas cinco soluciones vamos a pelearnos con Visual Basic 5/6 nativo y Pcode, con el registro de Windows y tendremos que parchear algúna rutina antidebug. Los CrackMes son del año 2000 y aunque algunos estaban ya solucionados, los analizaremos igualmente para ver la diferencia que existe con los análisis realizados en aquellos años, sí, estamos hablando del Softice.
Herramientas disponibles
Cuando hablamos de Visual Basic 5/6, podemos destacar 3 herramientas que nos facilitan mucho la vida, VB Decompiler, VB Reformer y ExDec. Las dos primeras se defienden bien tanto con código nativo como pcode y ExDec solamente nos sirve para pcode. Aún así, si todo lo demás falla, Ollydbg nos sacará de apuros.
CrkViz-1
Este primer crackme está compilado en Pcode y hoy día, con las herramientas de que disponemos no supone ninguna dificultad. Tan solo debemos abrirlo con VB Decompiler y ya nos encontramos con el serial válido.
Los opcodes obtenidos con ExDec se ven de la siguiente manera.
...... 402F14: 04 FLdRfVar local_008C 402F17: 21 FLdPrThis 402F18: 0f VCallAd 7b3fc340 402F1B: 19 FStAdFunc local_0088 402F1E: 08 FLdPr local_0088 402F21: 0d VCallHresult 7b3fbe88 402F26: 6c ILdRf local_008C 402F29: 1b LitStr: 57230198 <-------------- 402F2C: Lead0/30 EqStr 402F2E: 2f FFree1Str local_008C 402F31: 1a FFree1Ad local_0088 402F34: 1c BranchF: 403012 402F37: 21 FLdPrThis 402F38: 0d VCallHresult 7b3fc2b0 402F3D: 3a LitVarStr: ( local_00AC ) Gracias por Registrar!! 402F42: Lead2/00 FStVarCopy 402F46: 27 LitVar_Missing 402F49: 27 LitVar_Missing 402F4C: 3a LitVarStr: ( local_00AC ) CrkViz 402F51: 4e FStVarCopyObj local_00BC 402F54: 04 FLdRfVar local_00BC 402F57: f5 LitI4: 0x40 64 (...@) 402F5C: 04 FLdRfVar local_009C 402F5F: 0a ImpAdCallFPR4: _rtcMsgBox 402F64: 36 FFreeVar 402F6D: 27 LitVar_Missing 402F70: 25 PopAdLdVar 402F71: 27 LitVar_Missing ......
CrkViz-2
Este segundo crackme también está compilado en pcode. La rutina del serial es muy sencilla pero al introducir un número aleatorio nos obliga a parchear. Cargamos el crackme en VB Decompiler y nos muestra esto:
Básicamente vemos que genera un número aleatorio entre 1 y 999999999 y luego le suma 1. La forma de afrontar esto es parcheando. Nos fijamos en el offset aproximado (4037F2) y abrimos el crackme en un editor hexadecimal. La forma de convertir el offset que nos muestra VB Decompiler a lo que nos muestra un editor hexadecimal es la siguiente.
VBdec_offset - Image Base - VirtualOffset + RawOffset = Offset_Editor.H 4037F2 - 400000 - 1000 + 400 = 2BF2
Una vez localizados los bytes, los cambiamos por ceros y guardamos.
Una vez parcheado, el serial correcto es 1.
CrkViz-3
En esta tercera entrega, CrkViz aumentó la dificultad. El crackme está compilado en código nativo y nos enfrentamos a un serial asociado a un nombre y a una rutina antidebug que en realidad es una Nag, ya que se muestra siempre.
Afrontar la nag es muy sencillo, basta con localizarla y parchear la llamada.
CPU Disasm Address Hex dump Command Comments 004058E2 8D4D DC LEA ECX,[EBP-24] 004058E5 C785 BCFDFFFF B MOV DWORD PTR SS:[EBP-244],CrkMeViz-3.004033B8 ; UNICODE " Debugger detectado!!! " 004058EF C785 B4FDFFFF 0 MOV DWORD PTR SS:[EBP-24C],8 004058F9 FFD7 CALL EDI 004058FB B9 04000280 MOV ECX,80020004 00405900 B8 0A000000 MOV EAX,0A 00405905 898D FCFDFFFF MOV DWORD PTR SS:[EBP-204],ECX 0040590B 898D 0CFEFFFF MOV DWORD PTR SS:[EBP-1F4],ECX 00405911 8D95 B4FDFFFF LEA EDX,[EBP-24C] 00405917 8D8D 14FEFFFF LEA ECX,[EBP-1EC] 0040591D 8985 F4FDFFFF MOV DWORD PTR SS:[EBP-20C],EAX 00405923 8985 04FEFFFF MOV DWORD PTR SS:[EBP-1FC],EAX 00405929 C785 BCFDFFFF 8 MOV DWORD PTR SS:[EBP-244],CrkMeViz-3.00403188 ; UNICODE "Error" 00405933 C785 B4FDFFFF 0 MOV DWORD PTR SS:[EBP-24C],8 0040593D FF15 C8914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarDup>] 00405943 8D85 F4FDFFFF LEA EAX,[EBP-20C] 00405949 8D8D 04FEFFFF LEA ECX,[EBP-1FC] 0040594F 50 PUSH EAX 00405950 8D95 14FEFFFF LEA EDX,[EBP-1EC] 00405956 51 PUSH ECX 00405957 52 PUSH EDX 00405958 8D45 DC LEA EAX,[EBP-24] 0040595B 6A 10 PUSH 10 0040595D 50 PUSH EAX 0040595E FF15 50914000 CALL DWORD PTR DS:[<&MSVBVM50.#595>] ; rtcMsgBox - NOPear para evitar la NAG 00405964 8D8D F4FDFFFF LEA ECX,[EBP-20C]
Antes de llegar al keygen vemos que realiza unas llamadas al registro de Windows, ponemos un breakpoint «bp RegOpenKeyW» y ejecutamos.
CPU Disasm Address Hex dump Command Comments 00405677 |. 8B8D B8FDFFFF MOV ECX,DWORD PTR SS:[EBP-248] 0040567D |. B8 54334000 MOV EAX,CrkMeViz-3.00403354 ; UNICODE "<Unregister>" 00405682 |. 68 B4304000 PUSH CrkMeViz-3.004030B4 ; UNICODE "Serial number" 00405687 |. 894A 04 MOV DWORD PTR DS:[EDX+4],ECX 0040568A |. 8985 BCFDFFFF MOV DWORD PTR SS:[EBP-244],EAX 00405690 |. 68 84304000 PUSH CrkMeViz-3.00403084 ; UNICODE "Register" 00405695 |. 68 58304000 PUSH CrkMeViz-3.00403058 ; UNICODE "CrkMeViz3" 0040569A |. 8942 08 MOV DWORD PTR DS:[EDX+8],EAX 0040569D |. 8B85 C0FDFFFF MOV EAX,DWORD PTR SS:[EBP-240] 004056A3 |. 8942 0C MOV DWORD PTR DS:[EDX+0C],EAX 004056A6 |. FF15 C0914000 CALL DWORD PTR DS:[<&MSVBVM50.#689>] ; rtcGetSetting - Lee el numero de serie del registro ........ 0040574F |. 68 9C304000 PUSH CrkMeViz-3.0040309C ; UNICODE "User Name" 00405754 |. 68 84304000 PUSH CrkMeViz-3.00403084 ; UNICODE "Register" 00405759 |. 68 58304000 PUSH CrkMeViz-3.00403058 ; UNICODE "CrkMeViz3" 0040575E |. 8948 08 MOV DWORD PTR DS:[EAX+8],ECX 00405761 |. 8B8D C0FDFFFF MOV ECX,DWORD PTR SS:[EBP-240] 00405767 |. 8948 0C MOV DWORD PTR DS:[EAX+0C],ECX 0040576A |. FF15 C0914000 CALL DWORD PTR DS:[<&MSVBVM50.#689>] ; rtcGetSetting - Lee el Usuario del registro
Reconstruyendo la llamada al registro vemos que lee de esta ruta: HKEY_CURRENT_USER\Software\VB and VBA Program Settings\CrkMeViz3\Register el contenido de User Name y del Serial number.
Quizá uno de los fallos de éste crackme, es que no comprueba la autenticidad de estos parámetros y si los modificas parece que estás registrado. Un ejemplo:
La rutina de comprobación del serial no es para nada complicada pero recordemos que estamos tratando con VB y éste delega el trabajo duro en otras librerias de modo que tenemos que «meternos» a tracear las llamadas para ver los valores que multiplica y divide.
CPU Disasm Address Hex dump Command Comments 00405A86 FF15 3C914000 CALL DWORD PTR DS:[<&MSVBVM50.#518>] ;MSVBVM50.rtcLowerCaseVar 00405A8C 8D95 14FEFFFF LEA EDX,[EBP-1EC] 00405A92 8D8D ACFEFFFF LEA ECX,[EBP-154] 00405A98 FFD6 CALL ESI 00405A9A 8D95 ACFEFFFF LEA EDX,[EBP-154] 00405AA0 8D8D 4CFEFFFF LEA ECX,[EBP-1B4] 00405AA6 FFD7 CALL EDI 00405AA8 8D95 4CFEFFFF LEA EDX,[EBP-1B4] 00405AAE 8D8D 7CFFFFFF LEA ECX,[EBP-84] 00405AB4 FFD7 CALL EDI 00405AB6 8D85 14FEFFFF LEA EAX,[EBP-1EC] 00405ABC 8D8D 7CFFFFFF LEA ECX,[EBP-84] 00405AC2 50 PUSH EAX 00405AC3 6A 01 PUSH 1 00405AC5 8D95 04FEFFFF LEA EDX,[EBP-1FC] 00405ACB 51 PUSH ECX 00405ACC 52 PUSH EDX 00405ACD C785 1CFEFFFF 0 MOV DWORD PTR SS:[EBP-1E4],1 00405AD7 C785 14FEFFFF 0 MOV DWORD PTR SS:[EBP-1EC],2 00405AE1 FF15 68914000 CALL DWORD PTR DS:[<&MSVBVM50.#632>] ;MSVBVM50.rtcMidCharVar (Esto lo hace 6 veces, lo omito para abreviar.) ........ 00405CE1 FF15 34914000 CALL DWORD PTR DS:[<&MSVBVM50.#516>] ;MSVBVM50.rtcAnsiValueBstr (Lo mismo, otras 6) ........ 00405E7C C785 BCFDFFFF 2 MOV DWORD PTR SS:[EBP-244],52E 00405E86 C785 B4FDFFFF 0 MOV DWORD PTR SS:[EBP-24C],2 00405E90 50 PUSH EAX 00405E91 FF15 84914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>] | ->MSVBVM50.__vbaVarMul ........ 741C19D3 0FB745 FE MOVZX EAX,WORD PTR SS:[EBP-2] ;Valor1 741C19D7 0FB74D F2 MOVZX ECX,WORD PTR SS:[EBP-0E] ;Valor2 741C19DB 6BC0 12 IMUL EAX,EAX,12 ;Valor1*Valor2 ........ 00405E97 8D8D 04FEFFFF LEA ECX,[EBP-1FC] 00405E9D 50 PUSH EAX 00405E9E 51 PUSH ECX 00405E9F FF15 84914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>] 00405EA5 8D95 F4FDFFFF LEA EDX,[EBP-20C] 00405EAB 50 PUSH EAX 00405EAC 52 PUSH EDX 00405EAD FF15 84914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>] 00405EB3 50 PUSH EAX 00405EB4 8D85 E4FDFFFF LEA EAX,[EBP-21C] 00405EBA 50 PUSH EAX 00405EBB FF15 84914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>] 00405EC1 8D8D D4FDFFFF LEA ECX,[EBP-22C] 00405EC7 50 PUSH EAX 00405EC8 51 PUSH ECX 00405EC9 FF15 84914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>] 00405ECF 50 PUSH EAX 00405ED0 8D95 B4FDFFFF LEA EDX,[EBP-24C] 00405ED6 8D85 C4FDFFFF LEA EAX,[EBP-23C] 00405EDC 52 PUSH EDX 00405EDD 50 PUSH EAX 00405EDE FF15 94914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarDiv>] | ->MSVBVM50.__vbaVarDiv ........ 741C8094 DD43 08 FLD QWORD PTR DS:[EBX+8] ;Recupera el resultado de las multiplicaciones anteriores 741C8097 0FBF47 08 MOVSX EAX,WORD PTR DS:[EDI+8] ;EAX = 1326 (52E) 741C809B 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX 741C809E DA75 F8 FIDIV DWORD PTR SS:[EBP-8] ;Divide los dos resultados 741C80A1 DD5E 08 FSTP QWORD PTR DS:[ESI+8] ........ 00405F44 FF15 24914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaLenBstr>] ;Len(nombre) ........ 00405F85 FF15 94914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarDiv>] ;Resultado anterior / Len(nombre) ........
En resumen:
- Pasa nuestro nombre a minúsculas.
- Obtiene el valor ascii de los 6 primeros dígitos del nombre.
- Los multiplica entre sí y divide el resultado acumulado entre 1326 (52E).
- Divide el resultado anterior entre el tamaño del nombre.
Ejemplo para deurus
64*65*75*72*75*73 = 1A605D70EB8 1A605D70EB8 / 52E = 5179FBF4 5179FBF4 / 6 = D9454A9
Al estar correctamente registrados desaparece el botón de registrar.
CrkViz-4
El cuarto crackme es prácticamente igual que el tercero salvo que en vez de nag ahora contamos con limitación de ejecuciones. Del mismo modo utiliza el registro de Windows para guardar los datos de registro y las ejecuciones que llevamos.
Ponemos un breakpoint «bp RegOpenKeyW» y llegamos a la conclusión de que la ruta es HKEY_CURRENT_USER\Software\VB and VBA Program Settings\ODBC\Register y los valores se guardan en Counter, User Name y Serial number respectivamente. Este crackme hereda el fallo del anterior y si alteramos los valores el crackme nos muestra como usuarios autorizados, aunque sabemos que no estamos registrados ya que seguimos limitados por ejecuciones. Ni que decir tiene que lo mismo que modificamos el nombre y número de serie, podemos modificar el contador a nuestro favor. Crear un archivo «Reiniciar_contador.reg» con el siguiente contenido sería suficiente.
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\VB and VBA Program Settings\ODBC] [HKEY_CURRENT_USER\Software\VB and VBA Program Settings\ODBC\Register] "Counter"="0" "User Name"="deurus" "Serial number"="12345"
El keygen es prácticamente igual que en el crackme anterior, solo cambia el divisor.
CPU Disasm Address Hex dump Command Comments ........ 00404BD2 C785 BCFDFFFF C MOV DWORD PTR SS:[EBP-244],6C1 00404BDC C785 B4FDFFFF 0 MOV DWORD PTR SS:[EBP-24C],2 00404BE6 FF15 A0914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>] | ->MSVBVM50.__vbaVarMul 741C19F9 0FBF4F 08 MOVSX ECX,WORD PTR DS:[EDI+8] ;Valor1 741C19FD 0FBF43 08 MOVSX EAX,WORD PTR DS:[EBX+8] ;Valor2 741C1A01 0FAFC8 IMUL ECX,EAX ;Valor1*Valor2 ........ 00404BEC 8D8D 04FEFFFF LEA ECX,[EBP-1FC] 00404BF2 50 PUSH EAX 00404BF3 51 PUSH ECX 00404BF4 FF15 A0914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>] 00404BFA 8D95 F4FDFFFF LEA EDX,[EBP-20C] 00404C00 50 PUSH EAX 00404C01 52 PUSH EDX 00404C02 FF15 A0914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>] 00404C08 50 PUSH EAX 00404C09 8D85 E4FDFFFF LEA EAX,[EBP-21C] 00404C0F 50 PUSH EAX 00404C10 FF15 A0914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>] 00404C16 8D8D D4FDFFFF LEA ECX,[EBP-22C] 00404C1C 50 PUSH EAX 00404C1D 51 PUSH ECX 00404C1E FF15 A0914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>] 00404C24 50 PUSH EAX 00404C25 8D95 B4FDFFFF LEA EDX,[EBP-24C] 00404C2B 8D85 C4FDFFFF LEA EAX,[EBP-23C] 00404C31 52 PUSH EDX 00404C32 50 PUSH EAX 00404C33 FF15 B0914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarDiv>] | ->MSVBVM50.__vbaVarDiv 741C8094 DD43 08 FLD QWORD PTR DS:[EBX+8] ; Recupera el resultado de las multiplicaciones anteriores 741C8097 0FBF47 08 MOVSX EAX,WORD PTR DS:[EDI+8] ; EAX = 1729 (6C1) 741C809B 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX 741C809E DA75 F8 FIDIV DWORD PTR SS:[EBP-8] 00404C39 8BD0 MOV EDX,EAX ........ 00404CA0 FF15 3C914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaLenBstr>] ;Len(nombre) ........ 00404CF1 FF15 B0914000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarDiv>] ;Resultado anterior / Len(nombre)
En resumen:
- Pasa nuestro nombre a minúsculas.
- Obtiene el valor ascii de los 6 primeros dígitos del nombre.
- Los multiplica entre sí y divide el resultado acumulado entre 1729 (6C1).
- Divide el resultado anterior entre el tamaño del nombre.
Ejemplo para deurus
64*65*75*72*75*73 = 1A605D70EB8 1A605D70EB8 / 6C1 = 3E7C594A 3E7C594A / 6 = A6A0EE2
CrkViz-5
Este último crackme está compilado en código nativo y simplemente se trata de una comparación lineal. La única diferencia reside en que no hay botón de registro, la comprobación la gestiona un evento «On Change«, de modo que está comprobando el tamaño del serial que introducimos y cuando éste tiene 8 dígitos llegamos aquí.
........ 0040A64F . C745 9C CDD4DD02 MOV DWORD PTR SS:[EBP-64],2DDD4CD ;2DDD4CD = 48092365 0040A656 . C745 94 03800000 MOV DWORD PTR SS:[EBP-6C],8003 0040A65D . FF15 08C14000 CALL DWORD PTR DS:[<&MSVBVM50.__vbaVa> ;MSVBVM50.__vbaVarTstEq 0040A663 . 66:85C0 TEST AX,AX 0040A666 . 0F84 BA000000 JE CrkMeViZ.0040A726 ;Si salta BAD BOY ........
Luego el serial correcto es 48092365.
Notas finales
¿Ha sido indoloro no?, claro que sí, Visual Basic es un coñazo de tracear pero hay que reconocer que con el tiempo las herramientas han mejorado mucho y nuestra vida es mucho más sencilla. Bueno, pués esto ha sido todo, como siempre os dejo todo el material utilizado y un Keygen.