Cómo crackear mi primer programa legalmente (parte III)
Cómo crackear mi primer programa legalmente (parte III)
En la parte II de esta serie de tutoriales, vimos cómo encontrar y acceder al código ensamblador que se ejecuta cuando pulsamos el botón Probar 2. Para encontrar dicho código, me ha hecho falta tener a mano estas informaciones:
- Un depurador o desensamblador, en este caso, como el programa ha sido realizado en ensamblador a 32 bits y usa directamente las API de Windows, he decidido usar la herramienta OllyDBG.
- El editor de recursos "Resource Hacker" nos ha ayudado a conocer las ID de los diversos controles.
- La tabla de los mensajes de Windows ha sido muy importante para entenderlos.
- Finalmente, entender las API de Windows y los parámetros de ellas.
Voy a escribir de nuevo, para tenerlo de referencia, el código asm (ensamblador) que es ejecutado al pulsar el botón Probar 2.
004010F1 >> cmp eax,3EB 004010F6 |. jnz 004011BD 004010FC |. push 200 00401101 |. push 403004 00401106 |. push 3EA 0040110B |. push dword ptr ss:[ebp+8] 0040110E |. call 004011EA ; <jmp.&user32.GetDlgItemTextA> 00401113 |. cmp eax,3 00401116 |. je short 0040111D 00401118 |. jmp 004011A1 0040111D |. push 402040 ; ASCII "luZ" 00401122 |. push 403004 00401127 |. call 004011D2 ; <jmp.&kernel32.lstrcmpA> 0040112C |. or eax,eax 0040112E |. jnz short 004011A1 00401130 |. push 402044 ; ASCII "nombreimagen" 00401135 |. push dword ptr ds:[403000] ; asm02.00400000 0040113B |. call 004011F0 ; <jmp.&user32.LoadBitmapA> 00401140 |. or eax,eax 00401142 |. jnz short 0040115A 00401144 |. push 0 00401146 |. push 402064 ; ASCII "Error carga de imagen" 0040114B |. push 402051 ; ASCII "Ha habido un error" 00401150 |. push dword ptr ss:[ebp+8] 00401153 |. call 004011FC ; <jmp.&user32.MessageBoxA> 00401158 |. jmp short 004011A1 ...
Función GetDlgItemTextA
La primera parte del código (las 4 primeras líneas), nos llevan a una conocida API de Windows: GetDlgItemTextA. Veamos el código:
004010FC |. push 200 00401101 |. push 403004 00401106 |. push 3EA 0040110B |. push dword ptr ss:[ebp+8] 0040110E |. call 004011EA ; <jmp.&user32.GetDlgItemTextA> ...
La función es muy sencilla de entender (GetDlgItemTextA: Recupera el título o el texto asociado a un control en un cuadro de diálogo) y hay que pasarle 4 parámetros:
GetDLGItemTextA(
HWND hwndDlg, // Manipulador del cuadro de diálogo del control
int nIDDlgItem, // Identificador del control
LPTSTR lpString, // Búfer que recibe la información
int nMaxCount // Máximo número de caracteres
);
Usando OllyDBG, depura el crackme y pon un breakpoint en la dirección 0040110E call 004011EA. Para que se detenga ahí, tendrás que escribir cualquier cosa en el textbox (yo he escrito karmany.NET, como se ve en la imagen 1 y pulsar el botón Probar 2). Ahora observa la pila para ver los parámetros que vamos a pasarle a la función:
CPU Stack
Address Value Comments
0018F8D4 /00180380 ; |hDialog = 00180380, class = #32770
0018F8D8 |000003EA ; |ItemID = 1002.
0018F8DC |00403004 ; |String =
0018F8E0 |00000200 ; \MaxCount = 512.
Como vimos en el anterior tutorial al abrir el crackme con Resource Hacker, el ID 1002 corresponde al control textbox (la caja donde he escrito karmany.NET). Por lo tanto, y en resumen, estas primeras 4 líneas lo que hacen es obtener el texto que hay escrito en el cuadro de texto 1. El texto, como ves en el código sobre estas líneas, va a ser almacenado en la dirección 00403004, así que en OllyDBG paso la función GetDlgItemTextA pulsando F8 y veo esto:
CPU Dump
Address Hex dump ASCII
00403004 6B 61 72 6D|61 6E 79 2E|4E 45 54 00|00 00 00 00| karmany.NET
Otro tema importante es que la función GetDlgItemTextA, devuelve en el registro eax el número de caracteres obtenidos. karmany.NET tiene 0B caracteres.
Verifica el número de caracteres
... 00401113 |. cmp eax,3 00401116 |. je short 0040111D 00401118 |. jmp 004011A1 0040111D |. push 402040 ; ASCII "luZ" ...
Compara si el número de caracteres es igual a 3. Si la longitud del texto escrito es distinta de 3, nos saca fuera de la subrutina (jmp 004011A1). Ahora ya sé que karmany.NET no va a ser un serial válido, así que lo cambio y pongo solamente kar.
Función lstrcmpA
Lo siguiente que nos encontramos es esto:
... 0040111D push 00402040 ; /String2 = "luZ" 00401122 push 00403004 ; |String1 = "kar" 00401127 call 004011D2 ; \KERNEL32.lstrcmp 0040112C or eax,eax 0040112E jnz short 004011A1 ...
lstrcmpA es una función muy conocida que tiene solo dos parámetros y compara dos cadenas de texto. Como puedes observar, compara nuestro kar con luZ y si son diferentes, nos saca de la subrutina. La comparación la hace distinguiendo mayúsculas de minúsculas, por lo tanto, reinicio todo y escribo exactamente luZ 1 y pulso otra vez el botón Probar 2.
Carga de un Bitmap
... 00401130 |. push 402044 ; ASCII "nombreimagen" 00401135 |. push dword ptr ds:[403000] ; asm02.00400000 0040113B |. call 004011F0 ; <jmp.&user32.LoadBitmapA>
El código sobre estas líneas, carga una imagen (gráfico) en formato bitmap. Para ello hace uso de la función LoadBitmapA que se define así:
HBITMAP LoadBitmap(
HINSTANCE hInstance, ;Manejador de la instancia de la aplicación
LPCTSTR lpBitmapName ;Cadena de texto que define al recurso buscado
);
Si la función tiene éxito, la función devuelve en eax el handle al recurso (a la imagen). Para que conozcas qué imagen va a ser cargada, abre asm02.exe en Resource Hacker y despliega Bitmap, verás lo siguiente:
Si la imagen se carga correctamente, el código se sigue ejecutando en 0040115A:
... 0040113B |. call 004011F0 ; <jmp.&user32.LoadBitmapA> 00401140 |. or eax,eax 00401142 |. jnz short 0040115A ...
Envía la imagen con SendMessageA
SendMessage es posiblemente una de las funciones más utilizadas, principalmente por la versatilidad de su uso, me explico: muchas veces querrás realizar una determinada acción y es posible que no recuerdes o no conozcas la función que necesitas. Pues bien, para estos casos, puedes utilizar SendMessage pasándole un determinado mensaje (como su nombre indica, SendMessage es Enviar Mensaje.) En nuestro caso:
... 0040115A push eax ; /lParam = DB050C7E 0040115B push 0 ; |wParam = IMAGE_BITMAP 0040115D push 172 ; |Msg = STM_SETIMAGE 00401162 push dword ptr ds:[403804] ; |hWnd = 003007C8, class = Static, text = #1111 00401168 call 00401202 ; \USER32.SendMessageA ...
El mensaje enviado es STM_SETIMAGE que significa que se va a asociar una nueva imagen (un mapa de bits) con un control estático, es decir, que la imagen que se ha cargado se va a poner en un control estático. El registro eax lleva el handle de la imagen y el control estático tiene de texto 1111. Observa a qué corresponde en Resource Hacker, desplegando Dialog.
Las 4 últimas funciones ShowWindow
ShowWindow, como podrás imaginar, lo que hace es mostrar u ocultar una ventana. El código en OllyDBG, viene muy bien explicado:
... 0040116D push 0 ; /Show = SW_HIDE 0040116F push dword ptr ds:[403808] ; |hWnd = 004D0564, class = Static 00401175 call 00401208 ; \USER32.ShowWindow 0040117A push 0 ; /Show = SW_HIDE 0040117C push dword ptr ds:[40380C] ; |hWnd = 004006F0, class = Button, text = Probar 00401182 call 00401208 ; \USER32.ShowWindow 00401187 push 0 ; /Show = SW_HIDE 00401189 push dword ptr ds:[403810] ; |hWnd = 00160280, class = Edit 0040118F call 00401208 ; \USER32.ShowWindow 00401194 push 5 ; /Show = SW_SHOW 00401196 push dword ptr ds:[403814] ; |hWnd = 001C07C6, class = Button, text = X 0040119C call 00401208 ; \USER32.ShowWindow
SW_HIDE oculta la ventana, mientras que SW_SHOW la muestra. Los manejadores fueron obtenidos en otra parte del código mediante GetDlgItem. Por orden de ejecución, el código hace lo siguiente:
- Oculta el control estático que está en la parte inferior
- Oculta el botón Probar 2
- Oculta el textbox donde se escribe
- Muestra el botón X
Espero que toda esta explicación te haya servido para entender el código. Aunque en este momento no es seguro, es posible que continúe hablando sobre este interesante CrackME, por ejemplo, para modificarlo y hacer que acepte cualquier serial o hacer otras cosas un poco más avanzadas. Ya veremos...
Gracias
Buscador Ricardo narvaja
Y en ese buscador busca por PECompact