APIS 32 v2.4 / Descompresión del ejecutable usando el ProcDump y parcheado del código en tiempo de ejecución para que acepte cualquier número de registro. By Black Fenix.

Aquí estoy de nuevo, esta vez con un tema nuevo que parece ser se ha puesto bastante de moda:
La compresión/encriptación de los ejecutables. Para el ejemplo usaremos un programa llamado APIS 32 v2.4 se trata de un monitorizador de las funciones del API de windows, también permine la exportación de simbolos con lo que se puede monitorizar cualquier función que se encuentre en una DLL. Este programa está comprimido, pero desconozco el nombre del compresor utilizado, aunque también podría ser que estuviera comprimido con alguna utilidad del mismo autor del programa.

Objetivo: Modificar el ejecutable comprimido para que se cambie lo que sea necesario en tiempo de ejecución logrando que sirva cualquier número de registro que le introduzcamos, habilitanto a si todas las funciones del programa. Para lograr esto necesitaremos poder descomprimir el ejecutable y una vez que se sabe lo que hay que cambiar, hacer el parche en el ejecutable comprimido. Esta lección promete bastante ya que se introduciran varios temas no tocados hasta el momento, aprenderemos el manejo del ProcDump y tambien algunas cosillas básicas sobre la estructura de los archivos PE (Portable Executable), será largo pero valdrá la pena.

SoftIce para Windows
W32DAsm 8.93
ProcDump 32 v1.2
Editor Hexadecimal (Ultra-Edit, HView etc.)

Nota: Puedes buscar estas tools en www.astalavista.box.sk, el APIS 32 lo puedes bajar de uno de estos sitios:

http://madmat.hypermart.net
http://www.cryogen.com/protectit
http://www.chat.ru/~madmat
http://www.crackstore.com

En principio procederemos de la forma normal, ejecutar el programa, introducir los datos de registro y copiar el mensaje de error que nos aparece.

Desensamblamos el ejecutable apis32.exe y vemos que no hay ninguna referencia a cadenas, ni tabla de funciones de importación.Esto son dos de los sintomas más normales en los archivos comprimidos/encriptados. Si examinamos el código por encima veremos que no parece un código muy lógico, repetición de instrucciones, escrituras a puerto frecuentes etc. esto es debido a que este no es el código real del programa. Bueno pero sabemos que de alguna manera el ejecutable debe descomprimirse/desencriptarse a si mismo y por lo tanto el código que realiza este trabajo debe aparecer. Efectivamente, y sólo sólo puede estar en un sitio: el punto de entrada del programa (Program Entry Point). Vamos al menu Goto/Program Entry Point y el W32DAsm nos llevará al punto de entrada del programa. Veremos algo así:

:0041A000669Cpushf
:0041A00260pushad
:0041A003E8CA000000call 0041A0D2 //llamada a la rutina de descompresión
:0041A0080300add eax, dword ptr [eax] // todo esto ya no se ejecutará
:0041A00A0400add al, 00
:0041A00C0500060007add eax, 07000600
:0041A0110008add byte ptr [eax], cl
:0041A0130009add byte ptr [ecx], cl
:0041A015000Aadd byte ptr [edx], cl
:0041A017000Badd byte ptr [ebx], cl
:0041A019000D000F0011add byte ptr [11000F00], cl
:0041A01F0013add byte ptr [ebx], dl
:0041A0210017add byte ptr [edi], dl
:0041A023001Badd byte ptr [ebx], bl
:0041A025001Fadd byte ptr [edi], bl a

Ok, según el W32DAsm este es el punto de entrada del programa, pero el código no parece muy lógico a partir de la llamada (call) de la tercera linea. Probablemente, después de la llamada, ya no se vuelve a la siguiente línea, sino que el programa saltará al punto de entrada del programa original (el punto de entrada del programa descomprimido), es de suponer que lo que sigue a la llamada, son datos de la sección.

Antes de continuar, vamos a hechar un vistazo a las diferentes secciones del ejecutable, para ello utilizaremos el ProcDump. Ejecutamos el ProcDump y hacemos click en el botón PE Editor, seleccionaremos el ejecutable apis32.exe y aceptamos (deberemos salir del W32DAsm para que el Procdump pueda leer el archivo). Nos aparecerá un cuadro de dialogo como el siguiente:

Para saber el punto de entrada exacto del programa, sumaremos el valor de Image Base con el valor Entry Point, resultando ser igual que el que nos daba el W32DAsm. Podemos asegurar pues que este el el punto de entrada. Ahora miraremos en que sección se encuentra el punto de entrada, hacemos click en el botón Sections y nos aparece un cuadro de diálogo como el siguiente:

Vemos que aparecen las secciones .itext , .idata , .rsrc y por último .madmat. Si miramos el valor Virtual Offset de la sección .madmat, vemos que coincide con el valor Entry Point anterior, esto nos indica que esta sección es la encargada de descomprimir/desencriptar el ejecutable y que por lo tanto contiene el código que estamos buscando.Es curioso también que coincida con parte de la URL del autor http://madmat.hypermart.net :)

Salimos del ProcDump cancelando todos los cuadros de diálogo abiertos.Volvemos a desensamblar el ejecutable y nos vamos al punto de entrada del programa (menu Goto/Program Entry Point), una vez allí vamos a ver que es lo que hace la llamada que hay en la segunda línea. Nos situamos sobre esta (linea azul encima de la linea de código ) y pulsamos el botón Call de la barra de botones. Esto nos llevará al código siguiente:

:0041A0D550push eax
:0041A0D68BC8mov ecx, eax
:0041A0D88BD0mov edx, eax
:0041A0DA81C168D20000add ecx, 0000D268
:0041A0E081C2DC150000add edx, 000015DC
:0041A0E68920mov dword ptr [eax], esp
:0041A0E88BE1mov esp, ecx
:0041A0EA50push eax
:0041A0EB812C2400A00100sub dword ptr [esp], 0001A000
:0041A0F2FF30push dword ptr [eax]
:0041A0F450push eax
:0041A0F580042408add byte ptr [esp], 08
:0041A0F950push eax
:0041A0FA80042446add byte ptr [esp], 46
:0041A0FE50push eax
:0041A0FF80042465add byte ptr [esp], 65
:0041A10350push eax
:0041A104800424A1add byte ptr [esp], A1
:0041A10850push eax
:0041A109800424BFadd byte ptr [esp], BF
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0041A172(U)
:0041A10D833A00cmp dword ptr [edx], 00000000
:0041A1100F84A7140000je 0041B5BD
:0041A116F70200000080test dword ptr [edx], 80000000
:0041A11C741Bje 0041A139
:0041A11EFDstd
:0041A11F8B0Amov ecx, dword ptr [edx]
:0041A12181E1FFFFFF7Fand ecx, 7FFFFFFF
:0041A1278B742418mov esi, dword ptr [esp+18]
:0041A12B8BFEmov edi, esi
:0041A12D037204add esi, dword ptr [edx+04]
:0041A130037A08add edi, dword ptr [edx+08]
:0041A133F3repz
:0041A134A5movsd
:0041A13583C20Cadd edx, 0000000C
:0041A138FCcld
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0041A11C(C)
:0041A13952push edx
:0041A13AFF32push dword ptr [edx]
:0041A13C8B5A08mov ebx, dword ptr [edx+08]
:0041A13F035C2420add ebx, dword ptr [esp+20]
:0041A14353push ebx
:0041A1448B5A04mov ebx, dword ptr [edx+04]
:0041A147035C2424add ebx, dword ptr [esp+24]
:0041A14B53push ebx
:0041A14CE84A000000call 0041A19B
:0041A15185C0test eax, eax
:0041A153741Fje 0041A174
:0041A1558B7C2404mov edi, dword ptr [esp+04]
:0041A15983C40Cadd esp, 0000000C
:0041A15C5Apop edx
:0041A15D8B4A0Cmov ecx, dword ptr [edx+0C]
:0041A160C1F902sar ecx, 02
:0041A16333C0xor eax, eax
:0041A165F3repz
:0041A166ABstosd
:0041A1678B4A0Cmov ecx, dword ptr [edx+0C]
:0041A16A83E103and ecx, 00000003
:0041A16DF3repz
:0041A16EAAstosb
:0041A16F83C210add edx, 00000010
:0041A172EB99jmp 0041A10D
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0041A153(C)
:0041A1748B642424mov esp, dword ptr [esp+24]
:0041A17883C426add esp, 00000026
:0041A17BC3ret

Fijate en los las instrucciones repz movsd, son muy típicas en las rutinas de descompresion/desencriptación, ya que se debe copiar el código y esta es una de las pocas formas de hacerlo. No nos interesa el algoritmo de compresión que se este utilizando, nuestro objetivo es encontrar la línea de código que nos envie al punto de entrada del programa descomprimido. Puede que lo que busquemos este en la línea 41a17b (ret), ya que es posible que allí se retorne al punto de entrada del programa descomprimido.Es hora del Soft-Ice.

Cargaremos el Symbol Loader del Soft-Ice y haremos click en Files/Open Module y seleccionaremos el fichero apis32.exe. Esto cargará el EXE en memoria y podremos trazarlo desde su punto de entrada original con Load/Module. Pulsaremos F8 una sola vez y entraremos en el código.Ahora pondremos un BPX en la línea 41a17b con:

> bpx 41a17b

y pulsaremos g para continuar. El BPX no surtirá efecto y en su lugar obtendremos un cuadro anunciandonos que el programa a efectuado una operación no válida. Parece que estamos equivocados y el ret no se ejecuta como esperabamos.Volviendo a examinar el código anterior buscando otro punto donde se pueda saltar, vemos una comparación bastante sospechosa en la línea 41a10D:

:0041A10D 833A00 cmp dword ptr [edx], 00000000
:0041A110 0F84A7140000 je 0041B5BD

Si nos fijamos, el salto se ejecutara cuando el dword apuntado por [EDX] sea igual a 0, enviandonos a una dirección bastante lejana a este código, el resto de los saltos, nunca llegan a salir de esta rutina, por lo que bamos a trazar de nuevo con el Soft-Ice hasta llegar a esta línea, una vez allí, pondremos un BPX a la dirección donde se saltará con:

> bpx 41B5BD

ahora pulsamos g+ENTER para continuar y nuestro BPX habrá surtido efecto, veremos lo siguiente:

:0041B5BD8B642414mov esp, dword ptr [esp+14]
:0041B5C15Epop esi
:0041B5C28BFEmov edi, esi
:0041B5C481C6D7150000add esi, 000015D7
:0041B5CA6A05push 00000005
:0041B5CC59pop ecx
:0041B5CDF3repz
:0041B5CEA4movsb
:0041B5CF61popad
:0041B5D0669Dpopf
:0041B5D2E9E99FFEFFjmp 004055C0 // salto incondicional a una dirección bastante "diferente"
:0041B5D7E9BBB5FEFFjmp 00406B97

Esto si que parece el fín de la rutina de descompresión, ya que restauran los registros y los flags que fueron empujados al inicio del programa y se salta incondicionalmente a una posición de código bastante diferente.Si seguimos trazando con F8, ejecutando el salto, veremos que este nos lleva a lo siguiente:

:004055C055push ebp
:004055C18BECmov ebp, esp
:004055C36AFFpush FFFFFFFF
:004055C56810804000push 00408010
:004055CA6818544000push 00405418
:004055CF64A100000000mov eax, dword ptr fs:[00000000]
:004055D550push eax
:004055D664892500000000mov dword ptr fs:[00000000], esp
:004055DD83C4A8add esp, FFFFFFA8
:004055E053push ebx
:004055E156push esi
:004055E257push edi
:004055E38965E8mov dword ptr [ebp-18], esp
* Reference To: KERNEL32.GetVersion, Ord:014Ch
:004055E6FF15B8024100Call dword ptr [004102B8] // Esto es el tipico inicio de todos los ejecutables
:004055EC33D2xor edx, edx
:004055EE8AD4mov dl, ah
:004055F08915A0BB4000mov dword ptr [0040BBA0], edx
:004055F68BC8mov ecx, eax
:004055F881E1FF000000and ecx, 000000FF
:004055FE890D9CBB4000mov dword ptr [0040BB9C], ecx
:00405604C1E108shl ecx, 08
:0040560703CAadd ecx, edx
:00405609890D98BB4000mov dword ptr [0040BB98], ecx
:0040560FC1E810shr eax, 10
:00405612A394BB4000mov dword ptr [0040BB94], eax
:00405617E8840E0000call 004064A0
:0040561C85C0test eax, eax
:0040561E750Ajne 0040562A
:004056206A1Cpush 0000001C
:00405622E839010000call 00405760
:0040562783C404add esp, 00000004
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040561E(C)
:0040562AC745FC00000000mov [ebp-04], 00000000
:00405631E86A0C0000call 004062A0
:00405636E8550C0000call 00406290
* Reference To: KERNEL32.GetCommandLineA, Ord:00AAh
:0040563BFF1574034100Call dword ptr [00410374] // Esto es tipìco al inicio de todos los ejecutables

Las llamadas a GetVersion y GetCommandLineA, delatan con toda seguridad, que este es el punto de entrada del programa original, por lo que apuntaremos su dirección que es 41B5BD. Si continuamos con la ejecución del programa, veremos que este funciona correctamente.

Ahora llega el momento de la verdad, vamos a usar el ProcDump para volcar el ejecutable una vez se halla descomprimido, para ello vamos a utilizar un script del ProcDump. Abriremos el fichero script.ini que se encuentra con el ProcDump, y agregaremos una linea al final de la sección [INDEX], la sintaxis será:

Pxx=APIS32 v2.4

xx= Numero de línea que toce, teniendo en cuenta que va en hexadecimal, por ejemplo si tenemos una sección INDEX tal que así:

[INDEX]
P1=Hasiuk/NeoLite
P2=PESHiELD
P3=Standard
P4=Shrinker 3.3
P5=Wwpack32 I
P6=Manolo
P7=Petite<1.3
P8=Wwpack32 II
P9=Vbox Dialog

deberemos escribir

PA=APIS32 v2.4

ahora creamos una sección que se llame igual que la línea que indica PXX (en nuestro caso [APIS32 v2.4] justo debajo y segiidamente le añadiremos las siguiente lineas:

L1=LOOK E9,E9,9F,FE,FF
L2=BP
L3=WALK
L4=EIP
L5=STEP

La línea L1, le indica al ProcDump que busque esta secuencia de bytes en el código del ejecutable, esta secuencia de bytes es el salto que hay en la línea 41B5D2

:0041B5D2 E9E99FFEFF jmp 004055C0

Este es el salto que nos envia al punto de entrada del ejecutable original, por lo que el ProcDump buscará esta posición de memoria.

Con la línea L2 le decimos que ponga un breakpoint en esa misma posición de memoria que se encontró.

La línea L3 le indica al ProcDump que ejecute la siguiente instrucción a partir de la posición donde se puso el breakpoint, en este caso lo que se hace es que el salto se ejecuta, situandonos en el punto de entrada del programa original.

Una vez en el punto de entrada original, la línea L4 le indica al ProcDump, que use el valor actual de EIP como punto de entrada del programa que va a volcar y posteriormente con la línea L4 finalizamos el trazado y procedemos al volcado del ejecutable.

Salvamos los cambios al fichero script.ini y ejecutamos el ProcDump. (Antes, entrar en el Soft-Ice y desactivar todos los breakpoints, ya que sino, el ProcDump encontrará los breakpoint del SI y se colcagará al descomprimir el ejecutable). Pulsamos sobre Unpack, seleccionamos APIS 32 v2.4 y pulsamos OK, ahora buscamos el archivo apis32.exe y lo seleccionamos para descomprimirlo. Nos aparecerá un cuadro de mensaje solicitando un nombre para el fichero descomprimido, le llamaremos apis32un.exe y lo guardaremos junto al original. Ahora, sin salir del ProcDump, podemos ejecutar el fichero recien descomprimido y veremos que este funciona perfectamente, y además ocupa más que el comprimido.

Ahora ya casi tenemos el fichero original, a este fichero le sobra el código que antes usaba para descomprimirse, ese código está en la sección .madmat, por lo que vamos a eliminarla para reducir el tamaño del ejecutable. Dentro del ProcDump, hacemos click en PE Editor, seleccionamos el archivo descomprimido y en el marco que dice "Apply changes method" activaremos la opción "To PE file", ya que sino, solo eliminariamos la sección de la cabezera y no del archivo. ahora pinchamos sobre el botón Sections, veremos los nombres de todas las secciones. Click con el botón derecho, nos aparece un menú con varias opciones, seleccionamos Kill Section. Esto eliminará la sección. Pulsamos Ok y Ok de nuevo y salimos del ProcDump. Si miramos el ejecutable veremos que ahora tiene unos 45K menos que antes, debido a que le hemos eliminado la sección .madmat. El ejecutable debe ser totalmente funcional, puedes comprobarlo tu mismo.

Bueno la parte más difícil ya está, ahora sólo quedá buscar donde se comprueba el número de série. Para ello procederemos de la manera estandar, buscando la referencia a la cadena que nos muestra el mensaje que se nos da al intentar registrarnos sin éxito, esta cadena dice algo así:

The registration information you entered... bla bla

Vale, desensamblamos el archivo que hemos descomprimido y buscamos esta cadena. Cuando la encontremos, doble click sobre esta y el W32DAsm nos transportará al siguiente código:

:00401764FF15F8024100Call dword ptr [004102F8]
:0040176AE8312F0000call 004046A0 // llama a la rutina en 4046a0
:0040176FA374CE4000mov dword ptr [0040CE74], eax // guarda valor de retorno en memoria mmm....
:00401774EB01jmp 00401777 // salto incondicional de un solo byte
:00401776B8BYTE B8
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00401774(U)
:004017770AC0or al, al // comprueba si el valor de retorno es 0
:004017797402je 0040177D // si es así, nos envia al código que hace referencia a la cadena de error
:0040177BEB2Cjmp 004017A9 // salto incondicional, buen chico, programa registrado.
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00401779(C)
* Possible StringData Ref from Data Obj ->"The registration information you " ->"provided is incorrect. Please"
:0040177DBFE8904000mov edi, 004090E8 // referencia a la cadena
:00401782BAE0D14000mov edx, 0040D1E0

Que te parece? Pues lo tipico, llamada a una función que comprueba los datos, se guarda el resultado de la comprobación, se comprueba este resultado y se actua en consecuencia. Podrimos hacer los cambios aquí, pero eso no es lo más elegante, vamos a ver que hace la función 4046a0.

:004046A051push ecx
:004046A153push ebx
:004046A255push ebp
:004046A356push esi
:004046A457push edi
:004046A56A50push 00000050
:004046A768A0C64000push 0040C6A0
* Possible StringData Ref from Data Obj ->"UserKey"
:004046AC6808964000push 00409608 // clave del registro que contiene el código introducido.
:004046B1E81A030000call 004049D0 // obtiene valor de la clave y retorna su longitud en EAX
:004046B683C40Cadd esp, 0000000C // restaura la pila
:004046B983F810cmp eax, 00000010 // comprueba que el código tenga una longitud superior a 10h caracteres,
:004046BC7D08jge 004046C6 // si, es válido, se pasa a comprobar el nombre
:004046BE33C0xor eax, eax // código no válido debido a su longitud
:004046C05Fpop edi
:004046C15Epop esi
:004046C25Dpop ebp
:004046C35Bpop ebx
:004046C459pop ecx
:004046C5C3ret
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004046BC(C)
:004046C66A2Fpush 0000002F
:004046C86800CF4000push 0040CF00
* Possible StringData Ref from Data Obj ->"UserName"
:004046CD68F8954000push 004095F8 // clave del registro que contiene el nombre del usuario introducido
:004046D2E8F9020000call 004049D0 // obtiene valos de la clave y su longitud en caracteres
:004046D783C40Cadd esp, 0000000C // restaura la pila
:004046DA83F805cmp eax, 00000005 // comprueba que el nombre tenga una longitud de 5 caracteres o más
:004046DD7D08jge 004046E7 // superior o igual a 5 caracteres, pasa a computar si el nombre y código son correctos
:004046DF33C0xor eax, eax // si es inferior a 5 caracteres, error, nombre muy corto
:004046E15Fpop edi
:004046E25Epop esi
:004046E35Dpop ebp
:004046E45Bpop ebx
:004046E559pop ecx
:004046E6C3ret

El código que sigue a este, se encarga de comprobar si el número y el nombre són válidos, no nos interesa como lo hace, por lo que avanzaremos el código hasta llegar al primer ret que encontremos, veremos lo siguiente:

* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00404807(U)
:0040481503EAadd ebp, edx
:0040481741inc ecx
:004048184Edec esi
:0040481975DAjne 004047F5
:0040481B33C0xor eax, eax
:0040481D5Fpop edi
:0040481E85EDtest ebp, ebp // comprueba si ebp es 0
:004048205Epop esi // restaura registro
:004048215Dpop ebp
:004048220F94C0sete al // pone al a 1 si ebp=0
:004048255Bpop ebx
:0040482659pop ecx
:00404827C3ret // retorna, si al=1, el código es válido.

La línea 404822 parece bastante sospechosa, ya que se pone AL a 0 o a 1 según una comparación anterior, si cambiamos la instrucción sete al (0F94C0) por setne al (0F95C0), y intentamos registrar el programa introduciendo un nombre más largo de 5 caracteres y un código más largo de 12 (10h) caracteres, veremos que el programa se registrará. Pruebaló, apunta el offset de esta instrucción, abre el archivo descomprimido, vete al offset que apuntaste y cambia el 94 por un 95. Salva los cambios y pruebaló, verás que el programa se ha registrado. Para desregistrarlo, puedes borrar la clave del registro H_KEY_LOCAL_MACHINE/SoftWare/APIS32/UserKey.

Pero si lo hacemos así, resultará que si por casualidad se acierta el código de registro, este no se registrará, por lo que la manera más correcta será cambiar el test ebp,ebp (85 ED) por xor ebp,ebp (33 ED), haciendo que ebp sea siempre 0 y por lo tanto el sete al posterior siempre pondra al a 1. Por lo tanto sabemos que el único byte de código que es necesario cambiar es el 85 (test) por un 33 (test) que se halla en la posición 40481. Apuntaremos estos datos, ya que los necesitamos para realizar el parche.

Ahora ya sabemos que es lo que hay que cambiar, falta saber cómo vamos a hacer para cambiarlo en el ejecutable comprimido. Pues es sencillo, vamos a buscar un sitio dentro del ejecutable donde podamos colocar nuestro parche. Podemos editar el archivo comprimido con el editor hexadecimal, y ver que después del mensaje de copyright "API Spy 32 - Copyright (c) 1999 Vitaly Evseenko", hay bastante sitio. Pues nada podemos colocar nuestro código detrás del mensaje en el offset 250h del archivo (Nota: esto es posible, porque la primera sección del ejecutable empieza en el offset 1000h, por lo tanto si nosotros colocamos nuestro código aquí, no estaremos sobresccribiendo nada, ya que estamos escribiendo el código en el espacio sobrante de la cabezera del archivo). Por lo tanto si la Image Base Address del programa comprimido es 40000h (puedes comprobarlo con el ProcDump si editas la cabezera de este), sabemos que nuestro código se encontrará en la posición 400250h una vez que este se haya cargado en memoria. Por lo tanto, deberemos saltar a esta posición después de que el programa se haya descomprimido, este salto lo podemos realizar justo donde se hace el salto de la línea:

:0041B5D2 E9E99FFEFF jmp 004055C0 // salto al punto de entrada del programa

por lo tanto deberemos cambiar esta línea por

:0041b5d2 E9794CFEFF jmp 400250 // salta a nuestra rutina que parchea el código.

Cómo sabemos que se debe cambiar el E9E99FFEFFF por E9794CFEFF? Pues fácil, si estamos en la posición 41B5D2 y queremos saltar a la 400250, restaremos (porque vamos hacia atras) a 400250 la dirección 41B5D2 dando como resultado FFFE4C7E, a este dirección faltan restarle los 5 bytes que ocupa el salto quedando FFFE4C79, que en ordenamiento Intel resulta 794CFEFF que es el valor que junto con el código del salto (E9) debemos cambiar.

Bien ahora, hay que saber que instrucción haremos servir para parchear el código, sabemos que el byte que debemos cambiar está en la dirección 40481E y debemos cambiarlo por un 33 (xor), esto deberá hacerse con la instrucción siguiente:

mov byte ptr [40481e],33

luego faltá que saltemos al punto de entrada del programa con un:

jmp 4055c0

Para saber la codificación de estas instrucciones, vamos a usar el SoftIce. Activaremos los breakpoints que teniamos y ejecutaremos el programa comprimido, aparecerá el SoftIce y iremos trazando hasta llegar al salto jmp 4055c0 (línea 41B5D2) , la cambiaremos por jmp 400250 (nuestra posición de código) con:

> a 41B5D2
> jmp 400250
> pulsar enter 2 veces

Pulsaremos F8 y esto nos enviará al lugar donde deberá estar nuestro código, allí ensamblarenos las lineas
de código que necesitamos con :

> a
> mov byte ptr [40481e],33
> jmp 4055c0
> pulsar enter 2 veces

Ahora vamos a ver el código de operación necesario para estas instrucciones con:

> d 400250

en la ventana de datos veremos los valores:

66C6051E48400033E963530000

esta es la cadena de bytes que corresponden a las instrucciones que hemos ensamblado, se divide de la siguiente manera:

66C6051E48400033 -> mov byte ptr [40841E],33
E963530000 -> jmp 4055C0

Continuaremos con la ejecución del programa y veremos que este funciona correctamente y nos dirá que está registrado al nombre que pusimos anteriormente. Si no pusijmos ningún nombre, bastará que
introduzcamos un nombre de más de 5 carácteres y un código de más de 12 para que se registre.

Tiempo para hacer las modificaciones al ejecutable comprimido, el primer cambio será cambiar el salto de la rutina de descompresión por el salto a nuestra código de parcheado. Recordar que el offset para este salto es E9D2, (puedes comprobarlo con el W32DAsm) cambiaremos la cadena que encontremos en este lugar del archivo (E9E99FFEFF) por la que calculamos anteriormente (E9794CFEFF). Luego iremos al offset 250h y allí reemplazaremos lo que haya (debe haber ceros) por los bytes 66,C6,05,1E,48,40,00,33,E9,63,53,00,00 nuestro código de parcheado.

Pues ya está a correr. Este a sido un tutorial bastante largo pero creo que el contenido a sido bastante interesante, y hemos visto cosas nuevas, podiamos haber hecho un keygenerator, pero mi propósito
era mostrar como se puede parchear un archivo comprimido en tiempo de ejecución. Podriamos haber prescindido de descomprimir el ejecutable y haber buscado la rutina de comprobación del número con el Soft-Ice, pero lo he hecho así para mostrar el uso del ProcDump, con el cual podemos descomprimir un ejecutable, sin tener que hacerlo manualmente.


You are inside Reversed Minds pages.

por Mr. Silver / WKT!.
La información aquí vertida es exclusivamente para uso educacional, no puedo hacerme responsable del uso que se haga de esta, por lo que atiendo a la honradez de cada uno :), recuerda que debes comprar el software que utilices :)