Está en la página 1de 31

Programa: AlcaTool v5.

51
Tutorial C01B

Protección: SVKP v1.3x + Dongle.

Objetivo: Desempaquetar SVKP y saltear la Dongle.

Descripcion: Programa para extraer y escribir las flash en los celulares Alcatel.

Dificultad: Newbie, Facililla, Media, Avanzado, Difícil, Elite.

Download: Pídanmelo por e-mail porque su tamaño excede el límite de subida del servidor.

PeiD, OllyDbg, Ollyscript plugin, Hex Work Shop, ImportReconstructor, Snippet


Herramientas:
Creator, Revirgin, DeDe, PeEditor.

Cracker: SACCOPHARYNX Fecha: 23/12/2004

INTRODUCCION
Viendo como se están dando mis tiempos, podría decir que esté será el último tute del año. Y solo lo
será porque se tratá de un SVKP muy cabrón, porque no estaba en mis planes hacerlo, pero viendo lo
dificultoso que fue, quiero compartirlo con el resto de los crackers ya que el packer me dio mucho más
trabajo a lo que me tenía acostumbrado.

AL ATAKE
Intro
El objetivo del tute es desempaquetar SVKP para luego poder debuggear tranquilos y eliminar las protecciones que tiene el EXE las
cuales chequean que la Dongle esté conectada al puerto USB. Tendremos muchas dificultades para arreglar la IAT, siendo necesario
no solo el uso de ImportReconstructor sino también de Revirgin, y la necesidad de realizar varios injertos. El programa fue
desempaquetado originalmente en WinXP SP1, pero como necesitaba que funcione también en otros sistemas, cuando probé en ellos
el desempaquetado que obtuve en WinXP, este no funcionaba y tuve que hacer unas reparaciones.

Pesentando a la victima
Como su nombre lo dice, AlcaTool es una herramienta para manipular el contenido de las flashes de varios modelos de celulares
Alcatel, desbloqueado de los mismos, etc. No dispongo de un celular Alcatel para testearlo, pero parece una herramienta interesante.

Manos a la obra
Lo primero que haremos será testearlo con PeiD, el cual nos informa lo siguiente:
Figura 01

Ya había desempaquetado los SVKP 1.3x, pero supongo que ese "x" que se desconoce, habrá introducido variantes que nos
complican, o tal vez se trate solo de opciones de empaquetamiento que justo no se usaron len os anteriores SVKP que crackee
anteriormente. De todas formas ahí están y hay que pasarlas.

El packer ya nos dará bastante trabajo como para también tener que llegar al OEP de la forma clásica en los tutes que leí, asi que lo
haremos lo más sencillo posible. Antes que nada aclaro que utilicé Olly v1.10 final (ya emparchado el bug que al generarse una
excepción hace que Olly se cierre) y OllyScript 0.92. No describiré como emparchar la versión 1.10 de Olly, pero si alguien no sabe
como hacerlo pueden descargar del link OllyPatched_v110+OllyScript_v092+ScriptForSVKP.rar un pack con el Olly v1.10 emparchado
+ el OllyScript que utilicé + el script para hallar el OEP de manera sencilla. Reemplazan el EXE original de Olly, copian el archivo
OllyScript.DLL en la carpeta de Olly, y el script "SVKP - find target's OEP.txt" donde tengan sus scripts. Con eso ya estamos listos
para empezar.

Cargamos AlcaTool551.exe en Olly y vamos a Plugins->OllyScript->Run Script... y seleccionamos el script que mencioné
anteriormente. El mismo pone en marcha la ejecución de Olly y vemos que las excepciones se pasan automáticamente. Cuando el
script termina su trabajo nos informa que estamos en el EP y que justo arriba está el lugar de los STOLEN BYTES. Damos OK y vemos
que nos detuvimos en la dirección 4CBB30.

Como el código se ve ofuscado vamos a "Analysis->Remove Analysis From Module" y esto nos mejora la visión:

Figura 02

Vemos que justo encima de 4CBB30 está el lugar de los STOLEN BYTES. No confundirse que no son 7 bytes, sino 12, porque también
debemos contar los cinco "90" (nop) que van desde 4CBB24 hasta 4CBB28. Es así como sabemos que 4CBB30 es tan solo una
dirección cercana al OEP y que este en realidad debe comenzar en 4CBB24. Como SVKP no ha variado en lo referente a hallar el OEP,
servirá mi experiencia previa para completar los STOLEN.

Si le damos un vistazo a los registros vemos que en EAX está el valor 4CB964:

Figura 03

lo cual significa que el código de los STOLEN debe cargar este valor en EAX. Asi que empecemos su reconstrucción:

004CBB24 . 55 PUSH EBP


004CBB25 . 8BEC MOV EBP,ESP
004CBB27 . 83C4 F0 ADD ESP,-10
004CBB2A . 53 PUSH EBX
004CBB2B . B8 64B94C00 MOV EAX,004CB964
004CBB2B . B8 64B94C00 MOV EAX,004CB964

Las instrucciones de 4CBB24 y 4CBB25 son clásicos bytes de un EP. La instrucción de 4CBB2B se deduce de ver el valor de los
registros, y las instrucciones de 4CBB27 y 4CBB2A las deduje de la experiencia con otros STOLENs.

Asi que cuando el programa está suspendido en 4CBB30 reparamos los STOLENs con las instrucciones de arriba:

Figura 04

y vamos a OllyDump y seleccionamos Dump Debugged Process con los siguientes seteos (sin reconstruir la IAT):

Figura 05

Damos Dump y guardamos el archivo con el nombre AlcaDump.exe para ser claros y prolijos. Vemos que el EXE dumpeado ocupa 20
preciosos MBs de nuestro disco, pero seguimos.

Ahora debemos hallar la IAT y repararla en el dumpeado. Para hallarla, con el programa aún detenido en en 4CBB30, presionamos
ALT+M, nos posicionamos sobre la sección code de AlcaTool, presionamos CTRL+B, y buscamos los bytes FF 25 que son típicos de la
JUMP TABLE que nos llevan a la IAT. Los hallamos justo aquí en 401208:

Figura 06

Si en el disassembler vamos a 401208 vemos:


Figura 07

Ya sabemos que la dirección 17F61EC pertenece a la IAT. En el Dump vamos a ella y la delimitamos observando hacia arriba y hacia
abajo. En este caso es realmente fácil hacerlo y nos queda:

InicioIAT = 17F6140

FinIAT = 17F67E7

TamañoIAt = (FinIAT - InicioIAT) + 1 = 0x6A8 bytes

Figura 08

Figura 09

Aca empiezan los problemas. Si prestamos atención vemos que todas las entradas apuntan a direcciones del tipo 7092XXXX o bien
son 00000000, y si presionamos ALT+M también vemos que existen dos zonas de memoria nuevas:

A) 7900000 de tamaño 2B000


B) 7930000 de tamaño 3000

Figura 10

Estas zonas de memoria no existían antes de que empecemos a ejecutar el script, por consiguiente se deduce que fueron creadas en
el proceso de desempaquetamiento por SVKP. Luego de varias pruebas, descubrí que en dichas zonas de memoria se ejecutan las
primeras líneas de cada API que el programa utiliza, para hacer luego si el salto a la API real, pero no al inicio de esta sino a un punto
más avanzado del código. Además de esto en dichas zonas se ejecutan otras rutinas que estaban en el programa original (aquí SVKP
hace algo parecido a lo de Xtreme Protector, copiando rutinas del programa original a la zona de su propio código para luego
camuflarlas con código redundante).

Cómo podemos arreglar esto y que inconvenientes nos depara? Este tipo de protección es bastante difícil de reparar, más que difícil
diría tediosa, por lo tanto lo más lógico es hacer un injerto en el EXE dumpeado para que desde un archivo BIN cargue el contenido
de esas zonas de memoria en las mismas direcciones de memoria donde lo realiza el desempaquetador. Pero no nos apresuremos. Si
hacemos esto, no necesitaríamos reparar la IAT, verdad? ya que la zona de memoria existiría gracias a nuestro injerto y la ejecución
del programa no daría error. Asi que es muy tentador hacer esto y no reparar la IAT a través de un injerto, que en este caso será,
un PEQUEÑO INJERTO MÁGICO.

Pero ocurre una vez que el programa fue desempaquetado y queremos debuggarlo para eliminar la protección de la Dongle? Ocurriría
que no podríamos poner por ejemplo "BP CreateFileA" porque el código inicial de la API se ejecutaría en la zona de SVKP y el BP no
surtiría efecto. Habría que poner el BP en una zona de código más alla del inicio de la API, lo cual implica desplazarnos hasta esa
zona por cada BP que queramos poner y eso ya sería muy denso, porque es más fácil escribir "BP CualquierAPI" y listo.

Pero como también necesitamos que dicha zona de memoria exista porque no solo se utiliza para ejecutar parte de las APIs, la
solución más conveniente y a la vez más trabajosa, es hacer las dos cosas: reparar la IAT y hacer el injerto que cargue el contenido
de esas zonas desde un par de archivos BIN en las mismas direcciones que lo hace SVKP.

Asi que lo primero que haremos será reparar la IAT. La primera dirección de la IAT comienza en 17F6140, asi que reiniciamos Olly
presionando CTRL+F2 y en el Dump nos vamos a dicha dirección:

Figura 11

El objetivo es detectar la rutina que escribe la IAT y ver si podemos hacer que escriba los valores correctos de los punteros a las
APIs. Para detectarla nos valeremos del uso de BreakPoints. Ponemos un BP Memory On Write en 17F6140 y damos F9 (RUN) y a
medida que saltan las excepciones las pasamos con ALT+F9, hasta que finalmente Olly se detiene en 78BF177 a raíz del BP:

Figura 12

Si tracean un poquito con F8 verán que se repite muchas veces el ciclo que va desde 78BF125 hasta 78BF17F. Salimos del ciclo
poniendo un HBP en 78BF181 y dando F9 otra vez para que la ejecución del programa continue. De esa manera Olly se detiene en
dicha dirección y vemos que la tabla de importaciones contiene los valores siguientes:

Figura 13

Como los valores finales aún no fueron escritos damos F9 otra vez y el primer BP que pusimos surte efecto nuevamente:

Figura 14

Si presionamos F8 una sola vez vemos que en la primera entrada de la tabla se carga el mismo valor final que hay en la figura 08:
Figura 15

Si comparamos las figuras 12 y 14 vemos que las dos rutinas que escriben la IAT son distintas, pero como verán a continuación la
que nos importa es la segunda. Entonces si presionamos F8 una vez más, cosa que Olly deje al EXE suspendido en la dirección
78B61DC, y vemos el contenido de los registros, notaremos algo muy interesante:

Figura 16

El registro EAX apunta a la API Kernel32.GetCurrentThreadId, asi que lo primero que pensé fue que el valor correcto que iba en la
primera entrada era el de esta API. Luego de hacer sucecivas pruebas colocando un HBP en 78B61DC y modificando a mano algunos
de los valores de la IAT por los de las direcciones de las APIs que iba obteniendo cuando Olly se detenía en el HBP, descubrí que mi
suposición era correcta, ya que al retirar todos los BPs y dar RUN, el EXE se había ejecutado sin problemas.

Como las entradas son muchas, para no tener que cargar a mano en cada una el puntero a la API correspondiente, realicé un
pequeño injerto en forma manual. Reiniciamos Olly nuevamente y borramos todos los BPs, ponemos nuevamente el BP Memory On
Write en la primera entrada de la IAT y realizamos los mismos pasos descriptos anteriormente hasta que Olly se detiene nuevamente
en 78B61D9.

Ahora en el mismo Olly realizamos el PEQUEÑO INJERTO MÁGICO (solo deben modificar el EXE para que quéde como el siguiente
código en amarillo):

Figura 17

Debido a que el código que está después del RETN de la dirección 78B6209 no se ejecuta mientras la IAT es escrita, desvío el flujo
del programa a través del saltó que introduje en 78B61D9 a una zona de memoria posterior al RETN la cual comienza en 78B622B.

Si prestan atención la nueva instrucción que está ahora en 78B622F, es la que originalmente estaba en 78B622B, pero con la
pequeña sutileza de que antes ejecuto la instrucción:

078B622B 8B4424 1C MOV EAX,DWORD PTR SS:[ESP+1C]

la cual si se fijan en el STACK o pila mientras el EXE aún permanece suspendido en 78B61D9, verán que se encarga de obtener el
puntero a la API verdadera desde la posición ESP+1C:

Figura 18

12E034 + 1C = 12E050, dirección donde está el puntero a la API verdadera que debe estar en la IAT. Luego de que se ejecuta esta
instrucción, en EAX tenemos el puntero deseado y ejecutamos la instrucción original que ahora está en 78B622F y de esa forma
cargamos en la IAT el puntero indicado. Esa fue la explicación del injerto manual. Ahora pasemos a ejecutarlo.
Solo hay que considerar que cuando la IAT fue reparada debemos deshacer el injerto. Para eso con el EXE aún suspendido en
78B61D9 eliminamos todos los BPs y en el Dump nos desplazamos a la última entrada de la IAT, nos posicionamos sobre el último byte
de esta entrada (17F67E7), y ponemos un BP Hardware On Write ahí. Damos F9 y Olly se detiene aquí:

Figura 19

justo cuando nuestro injerto va a escribir el valor final. Si prestan atención a la figura 19, las entradas anteriores poseen valores muy
comunes a los que estamos acostumbrados a ver en las IATs reparadas. Asi que presionamos F8 dos veces más, una para escribir
este último valor y otra para ejecutar el JUMP de la dirección 78B6231 que nos lleva a parte del código original.

Luego de esto marcamos con el mouse solamente el código modificado, damos click derecho, y damos Undo Selection y así dejamos
todo como estaba orignalmente por las dudas. Digo por las dudas porque luego de este injerto continué con la ejecutión del EXE para
ver que la IAT quedó funcionando bien. Si quieren pueden hacerlo, pero consideren que tendrán que reiniciar el EXE nuevamente y
reparar la IAT otra vez mediante el injerto.

Una vez cambiado el código del injerto por el código original, borramos todos los BPs, vamos a la dirección 4CBB30, ponemos un HBP
ahí, y damos F9 para que Olly se detenga justo en esa dirección. Háganme caso y con el EXE parado en 4CBB30 completan los
STOLENs bytes nuevamente (sin importar que ya lo hayamos hecho antes y que esos cambios están en el dumpeado). Dejamos el
EXE supendido y ejecutamos ImportReconstructor, seleccionamos el proceso alcatool551.exe y cargamos los siguientes valores que
ya obtuvimos:

Figura 20

presionamos Get Imports y oh oh, ImportReconstructor (IR) nos dice que no puede leer la memoria del proceso:

Figura 21

What the hell is going on here? Fui a Olly, presione ALT+M, me dirigí al sección donde está contenida la IAT, di click derecho con el
mouse, y seleccioné la opción Set Access->Full Access. Intenté leer la IAT nuevamente con IR y nuevamente no obtuve éxito. No
me detuve a ver el porqué de esto, simplemente realicé lo siguiente:

Recuerdan que dije que el EXE ocupa 20 MBs? Entonces lo que hice fue suponer que si su tamaño es tan grande debería haber una
zona vacía y que a la vez se puedea leer, lo suficientemente grande como para copiar la IAT ahí. Por cuestiones de simplicidad, ya
que la IAT está entre 17F6140 y 17F67E7 inclusive, fui al Dump y marqué toda esa zona, le di BINARY COPY, y luego me desplacé a
13F6140 y marqué hasta 13F67E7. Le di BINARY PASTE y así obtuve una copia de la IAT en un zona de memoria que podía leer.
Modifiqué el valor del RVA de la IAT en IR:
Figura 22

y ahora si puede leer la IAT con IR al presionar Get Imports:

Figura 23

Vemos que aún quedan entradas sin resolver. Nuestro injerto resolvíó la mayoría de ellas pero aún quedan algunas. Las entradas que
quedan son 10 en mi caso:

Entrada nro. Dirección de la entrada ...apunta a...

1 13F6198 790AE6C
2 13F61A8 7907E2A
3 13F61BC 7905379
4 13F61FC 791BC35
5 13F6244 790AE6C
6 13F62EC 791AB8B
7 13F62F0 7919B75
8 13F6308 790AE6C
9 13F658C 791BC35
10 13F67D0 79164E6

Dejemos momentáneamente el proceso de cracking. Como dije anteriormente, en las dicciones 790XXXX o 791XXXX además del
código inicial de las APIs, se ejecutan otras cosas, y por esa razón necesitamos dumpear a dos archivos BIN las zonas de memoria A
y B que ya vimos, para luego cargarlas y que el programa continue la ejecución. Aquí me voy a adelantar en comentarles algo para
no hacerles hacer todas las pruebas que hice yo, porque sino el tute sería interminable.

Una de las otras cosas que se ejecutan en estas zonas de memoria es una rutina desencriptadora, que justamente desencripta parte
del código donde debemos emparchar para eliminar la protección de la Dongle. Nunca he provado empaquetar con SVKP asi que no se
las opciones que trae, pero es evidente que si parte de las protecciones que el EXE tiene para detectar que la Dongle esté
conectada al puerto USB, están encriptadas, no es casualidad y si lógico pensar de que fueron encriptadas con toda
predeterminación, asi que de ahí deduzco que este packer debe tener alguna opción para encriptar parte del EXE, para luego ser
desencriptada desde la zona de su propio código.

El tema fue que primero emparché el programa en memoria y funcionó todo perfecto, pero cuando fui a hacer los cambios en el
programa ya reparado y en disco, me encontré con que los bytes eran diferentes a los de la memoria. Como estaba seguro que no
me había equivocado en pasar los offset de memoria a disco, me puse a debuggear y fue como descubrí que la zona donde
necesitaba emparchar estaba encriptada. Pero como en el momento que dumpeamos el EXE a disco (cuando estábamos en el OEP),
estás zonas estaban encriptadas, el EXE se dumpeó con algunas zonas encriptadas. Yo solo descubrí las zonas donde debía hacer el
parche, pero podían haber más y no sabía en donde, por tal razón preferí dejar el EXE con las partes encriptadas que existan y
cargar las zonas de memoria A y B desde un archivo, ya que implicaba más trabajo cambiar en el EXE dumpeado lo encriptado por lo
desencriptado y tener que buscar y anular la rutina desencriptadora porque sino está intentaría desencriptar algo que ya lo estaba.

De ahí, que si iba a cargar estas zonas desde un par de archivos, no me molesté en reparar las 10 entradas que IR no pudo reparar,
ya que la zona de memoria a donde apuntan estas 10 entradas malas es la misma que la zona que cargaré desde los archivos. Y
como 10 entradas es realmente poco, era mucha mala suerte que justo alguna de ellas corresponda a alguna API en la que justo
necesitaba poner un BP.

Ahora continuemos con el cracking. Luego de haber dado Get Imports en IR obtuvimos algo como la figura 23 muestra, y como
dijimos que no repararemos las 10 entradas malas, dejamos todo así y CERRAMOS IMPORT RECONSTRUCTOR.
Pero cómo es eso? Pués si, aquí comenazaron los dolores de cabeza para mí. Solo comentaré lo que ocurrió para que sirva de
experiencia. Está bien que no reparemos esas 10 entradas malas, pero porqué no el archivo dumpeado? Si aún no se perdieron,
deben recordar que lo primero que hicimos fue dumpear el EXE con los STOLENs hallados y el OEP seteado, asi que ahora lo más
lógico es presionar Fix Dump en IR para reparar la IAT de ese EXE, en la cual todas las entradas apuntan a la zona de SVKP.

Pues eso fue lo que hice y siempre obtenía un EXE con una IAT que contenía más de 10 entradas que apuntaban a la zona de SVKP,
a pesar de que el injerto solo había dejado 10 entradas sin resolver. Por alguna extraña razón Import Reconstructor no podía
plasmar correctamente en el archivo dumpeado la IAT del EXE que tenemos suspendido en 4CBB30. Probablemente se debe a que
tuvimos que cambiar la IAT de lugar para que IR la lea y eso generó algún conflicto. Pero lo cierto es que parte de las entradas de
la IAT que estaban reparadas en el EXE suspendido, al darle Fix Dump a IR, quedaban corruptas nuevamente en el archivo
dumpeado.

Por eso digo de cerrar IR, y por eso anteriormente les hice completar nuevamente los STOLEN BYTES, porque ahora con el programa
suspendido en 4CBB30 y con la IAT reparada (excepto las 10 entradas restantes), dumpearemos nuevamente con OllyDump y con los
mismos parámetros que muestra la figura 05. Deshechamos el dumpeado anterior y llamamos a este AlcaOllyDumpIAT_OK.exe.

Si hicieron las cosas como expliqué, deberían tener el EXE AlcaTool551.exe suspendido en 4CBB30. Y aunque no lo crean, ahora es
cuando debemos usar Import Reconstructor, porque si bien el archivo que acabamos de dumpear tiene la IAT reparada, por alguna
extraña razón algunas entradas de la JUMP TABLE quedaron mal: Si abren en Olly el archivo AlcaOllyDumpIAT_OK.exe, y van a la
dirección 401360 (que forma parte de la JUMP TABLE) verán que apunta a 17F6220, y que a pesar de que esa entrada de la IAT
apunta a 771214EC, en la dirección 401360 Olly no nos indica a que API pertenece:

Figura 23b

Creanme que si no lo reparamos dará algunos problemitas luego. Para reparar esto ejecutamos IR, seleccionamos el archivo que
tenemos suspendido en Olly, y luego cargamos los mismos valores que muestra la figura 22. Nuevamente a Get Imports y luego a Fix
Dump. Seleccionamos el archivo AlcaOllyDumpIAT_OK.exe e IR nos crea el archivo AlcaOllyDumpIAT_OK_.exe, al cual lo renombramos
y lo llamamos AlcaOllyDumpIAT_OK-ImpRec.exe, para no ir perdiendo los EXEs anteriores y para saber en que parte del proceso de
cracking está cada uno por si por alguna extraña razón deberíamos volver hacia atrás. Si ahora cargan en Olly al archivo
AlcaOllyDumpIAT_OK-ImpRec.exe y van nuevamente a la dirección 401360, verán la JUMP TABLE reparada:

Figura 23c

Por lo tanto la forma de obtener un EXE sin entradas malas en la IAT más que las 10 que ya nombramos, y que además su JUMP
TABLE esté correcta, consiste en dumpear (con la IAT reparada por medio del INJERTO MAGICO) el EXE cuando esté detenido en
4CBB30, y una vez hecho esto cargar este EXE detenido en Olly en el IR y Fixear el dumpeado. Ufffffffff, que trabajo me dio.

Continuemos con el cracking.


Ahora debemos dumpear las zonas de memoria A y B. Para eso presionamos ALT+M y nos posicionamos sobre la zona A (7B00000),
damos click derecho y seleccionamos Dump, lo cual abrirá una nueva ventana llamada Dump - 7900000..792AFFF. Nos posicionamos
en el primer byte de esta nueva ventana, damos click derecho para seleccionar Copy->Select All, y luego click derecho nuevamente
pero esta vez para seleccionar Binary->Binary Copy. Deberían obtener algo así:

Figura 24

Luego vamos a un editor hexa, creamos un archivo nuevo y pegamos lo que acabamos de copiar. En Hex Work Shop hay que ir a
Edit->Paste Especial y poner esta configuración:

Figura 25

damos Paste y listo. Guardamos el archivo y lo llamamos RAM1.BIN. Ahora deben hacer lo mismo para la zona B (7930000), pero
cuando guardan el archivo lo llaman RAM2.BIN. A menos que SVKP varíe los tamaños de estas zonas entra distintas PCs, el archivo
RAM1.BIN debería tener un tamaño de 172 Kb y el archivo RAM2.bin un tamaño de 12 Kb.

Muy bien, entonces ahora que tenemos esas zonas en disco debemos hacer un injerto en el EXE dumpeado para cargarlas. Cerramos
Olly y lo abrimos nuevamente, pero esta vez cargando en él el archivo AlcaOllyDumpIAT_OK-ImpRec.exe.

Anteriormente, al momento de llegar al OEP en el programa empaquetado, estas zonas ya estaban cargadas en memoria, asi que en
el programa dumpeado debemos cargarlas cuanto antes para que todo funcione bien. Yo recomiendo hacerlo antes de la primera
llamada. Una vez que caragron el archivo dumpeado en Olly deberían tener algo así:

Figura 26

Ahora debemos realizar el injerto que cargue los archivos en memoria. Yo he dividido el injerto en dos partes: Injerto A e Injerto B. El
primero carga RAM1.BIN y el segundo carga RAM2.BIN. Ambos injertos se enlazaran mediante instrucciones JMP.

Para comenzar debemos fijar donde hacer la llamada al injerto A que luego llamará al injerto B. Como ya dijimos, deben ejecutarse
antes de la primera CALL , asi que el JMP al primer injerto lo puse en 4CBB2B, que es la dirección que contiene la instrucción:
MOV EAX, 4CB964

la cual será reemplazada de la siguiente forma:

Figura 26 b

Ahora haremos el injerto que cargue el archivo RAM1.bin. Para eso buscamos una zona de memoria vacía (llena de 00) lo
suficientemente grande para que quepa el injerto. Esta zona comienza a partir de 4CBC00 y el injerto que deben hacer a mano con el
EXE suspendido en 4CBB24 es el siguiente:

Figura 27

Este injerto lo primero que hace es reservar la memoria virtual en 7900000 (primer VirtualAlloc) seguido de un commit (segundo
VirtualAlloc) para confirmar la orden. Luego abre el archivo RAM1.BIN (CreateFileA), y por último lee (ReadFile) el contenido del mismo
dentro de la zona A (7900000). Aca debo hacer tres aclaraciones importantes:

1) Si se fijan el la figura 27, más precisamente en la dirección 4CBC40, existe la instrucción PUSH 4CBC96 la cual es un puntero al
nombre del archivo. Por lo tanto para que el injerto funcione, deben ir a esta dirección en el Dump y cargar lo siguiente:

Figura 28

Sin olvidar el 00 al final del nombre del archivo para que indique el final de la cadena.

2) Algo parecido ocurre en 4CBC4E: PUSH 4CBC9F, donde se carga en la pila el puntero a la cantidad de bytes a leer: Vamos
nuevamente al Dump pero esta vez a la dirección 4CBC9F y cargamos 2B000 en orden inverso:

Figura 29

3) La siguiente es una aclaración importante si desean que el EXE funcione en cualquier PC o sistema operativo. Antes que nada
pregúntense: Cuál es la función principal de la IAT? La respuesta es almacenar una lista de punteros a las APIs, verdad? Pues no. A
mi parecer la función principal es permitir la exportación de un EXE de una PC a otra sin ncesidad de recompilar el código fuente, ya
que cuando se carga el EXE, el sistema operativo debe cargar en la IAT las direcciones que las APIs tienen en la PC donde el EXE se
ejecuta, debido a que estas direcciones no son las mismas entre distintas PCs y/o sistemas operativos. Y que tiene que ver esto con
nuestro injerto? Sencillo, si cuando estamos haciendo el injerto, y en las direcciones 4CBC12, 4CBC2A, 4CBC45, y 4CBC5E, editamos
escribiendo directamente:

4CBC12 CALL VirtualAlloc


4CBC2A CALL VirtualAlloc
4CBC45 CALL CreateFileA
4CBC45 CALL CreateFileA
4CBC5E CALL ReadFile

al guardar el injerto en el EXE, generaremos un EXE inexportable debido a que al editar de esa manera Olly inserta en el ejecutable
una llamada directa a la dirección de la API, pero esa dirección no será la misma en otra PC. Por esa razón cuando editen en las
cuatro direcciones anteriores, lo que deben escribir es CALL XXXXXX, donde XXXXXX es la dirección de la JUMP TABLE que apunta a
la entrada de la IAT que contiene la API deseada. La dirección de la API deseada cambia de una PC a otra, bien, pero esta dirección
siempre se almacena en la misma entrada de la IAT, por eso es que hay que hacer las llamadas a la JUMP TABLE, ya que esta no
varía de una PC a otra.

Por ejemplo, si se van a la dirección 406258 verán el inicio de la JUMP TABLE:

Figura 30

Entonces lo que deben hacer es buscar en la JUMP TABLE los saltos a las entradas de la IAT que apuntan a VirtualAlloc, CreateFileA,
y ReadFile. Los saltos son:

Figura 31 (CreateFileA)

Figura 32 (ReadFileA)

Figura 33 (VirtualAlloc)

Esto significa que al editar las direcciones 4CBC12, 4CBC2A, 4CBC45, y 4CBC5E, debemos escribir:

4CBC12 CALL 406518


4CBC2A CALL 406518
4CBC45 CALL 406330
4CBC5E CALL 4064B8

esa es la forma correcta de injertar para obtener un ejecutable exportable.

Se que me extiendo mucho pero creo que vale la pena esta agonía crackeana, jeje. Con esto tenemos listo el injerto A que carga a
RAM1.BIN. Si observan en la dirección 4CBC63 de la figura 27, hay un salto a 4CBD72. Ese es el salto o otro injerto, el injerto B, el
cual cargará el archivo RAM2.BIN. Podrían haberse hecho los dos injertos en uno. El problema fue que yo hice el primero solo para
probar y no le di importancia al segundo, y a continuación del injerto A había hecho otro injerto (que luego debemos realizar con
Snippet Creator al que llamaremos injerto C) y no me quedaba espacio para continuar el injerto B al final del injerto A. En fin, el
injerto B es este:
Figura 34

Es similar al de la figura 27, salvo que carga el archivo RAM2.BIN, asi que deben hacer las mismas consideraciones que antes, o sea,
en la dirección 4CBDB9, existe la instrucción PUSH 4CBC86 la cual es un puntero al nombre del archivo. Lo mismo pasa en 4CBDC7,
donde tenemos PUSH 4CBC8F y se carga en la pila el puntero la cantidad de bytes a leer (en este caso son 0x3000).

Por lo tanto para que el injerto B funcione, deben ir en el Dump a las direcciones 4CBC86 y 4CBC8F e injertar:

Figura 35

sin olvidar nuevamente el 00 al final del nombre del archivo para escribir seguido a eso 00 30 00 00 que es 0x3000 en orden inverso.

Al final de este injerto, en 4CBDE3, vemos que un salto nos lleva a 4CBC68, dirección que pertence al injerto A. A partir de esa
dirección lo que se realiza es restaurar la pila, ejecutar la instrucción que reemplazamos por la llamada al injerto A, y realizamos un
salto a 4CBB30 para continuar con la ejecución normal del programa.

Una vez que ambos injertos están listos y con el programa suspendido aún en el OEP (4CBB24), nos vamos al disassembler,
presionamos el botón derecho del mouse, y de las opciones que se despliegan seleccionamos Copy To Executable->All Modification.
Luego elegimos Copy All, y cuando se abre la siguiente ventana:

Figura 36

damos click derecho, seleccionamos Save File, y guardamos todos estos cambios en un archivo llamado AlcaOllyDumpIAT_OK-
ImpRec-InjertosAB.exe.

Ya tenemos el EXE con el OEP y los SOTLENs reparados, al igual que gran parte de la IAT, y las 10 entradas sin resolver no deberían
generar conflicto porque cargamos las zonas A y B desde los BINs. Asi que si ejecutamos el EXE, debería funcionar.

Pero al ejecutarlo da error, o no arranca, y si lo ejecuyamos bajo Olly genera excepciones. Alguno dirá, para qué hicimos el injerto si
igual da errores? Bueno, tranquilos. Vamos a analizar que pasa.
Cargamos en Olly el archivo AlcaOllyDumpIAT_OK-ImpRec-InjertosAB.exe y damos RUN para ver donde se genera la excepción.
Llegamos a aquí:

Figura 37

Olly dice que esa instrucción hace un uso ilegal de los registros, pero como el código está muy ofuscado y el DeJunk no desofusca
nada, puse un HBP en 7916ED1, pero en el programa empaquetado, y cuando Olly se detuvo comparé los registros del empaquetado
con el contenido de los registros de AlcaOllyDumpIAT_OK-ImpRec-InjertosAB.exe y ambos eran iguales. De hecho, en el programa
empaquetado también se generá la misma excepción, asi que lo que yo supongo es que en realidad no es la excepción lo que nos
saca fuera del programa, sino que luego de esta debe haber alguna rutina dentro del código de las Zonas A o B que chequea si el
programa fue desempaquetado, entonces nos saca fuera.

La solución que hallé consta en observar la pila cuando se genera la excepción. En dicho momento el contenido de la misma es el
siguiente:

Figura 38

En color amarillo vemos que se nos indica que la dirección de retorno es 4C1A13, a la cual retonamos después de una llamada a
44E4FC, la cual obviamente debe ser la instrucción anterior a la de la dirección 4C1A13. O sea, esta fue la última llamada que se
ejecutó en el código de usuario. Vamos a esa dirección:

Figura 39

Vemos que efectivamente en 4C1A0E está la llamada. Si reiniciamos Olly y ponemos un HBP en esa dirección, cuando Olly se detiene
ahí y entremos a la CALL con F7, veremos el JUMP o salto que nos lleva a la zona de memoria donde se produce la excepción:
Figura 40

Repito, la excepción se produce tanto en el empaquetado como en el desempaquetado, pero supongo que luego de ella hay algún
tipo de control, ya que no es ella quién nos saca del programa, porque si ponemos un HBP en la instrucción inmediata a 7916ED1 (o
sea en 7916ED3) y pasamos la excepción, el programa se puede seguir debuggeando. Por eso mis sospechas de que hay alguna
rutina anti-unpacking. No me puse a buscarla. Simplemente NOPEE el JMP de la dirección 44E4FC que se ve en la figura 40 y el
programa arrancó.

Asi que con un editor hexa abrimos el archivo AlcaOllyDumpIAT_OK-ImpRec-InjertosAB.exe y nos vamos a la dirección 4E4FC.
Cambiamos los bytes:

FF25D0677F01 por 909090909090

guardamos todo en un nuevo archivo llamado AlcaOllyDumpIAT_OK-ImpRec-InjertosAB-ExcepOut.exe y ya el programa arranca:

Figura 41

y nos informa de que no detecta la Dongle en el puerto USB.

Antes de continuar con la detección de la no existencia de la Dongle. Voy a detenerme en otro detalle: Yo he crackeado a esta
víctima en XP, pero cuando ejecutaba el EXE en otros sistemas operativos que tengo en mi PC, el mismo no funcionaba. Lo que
ocurría es que por alguna razón la IAT del EXE obtenido tenía los mismos valores en c/u de sus entradas, tanto en WinXp, WinMe, y
Win2000, lo cual es incorrecto, ya que como dijimos antes, la IAT debe permitir la exportación del EXE ya que las diercciones de las
APIs no son las mismas. Al no ser las mismas entre distintos sistemas y la IAT permanecer igual, obviamente da error.

Supongo que IR debe tener algún bug y al haber cambiado de lugar la IAT anteriormente nos ha dejado un EXE que solo funciona en
la PC donde fue crackeado.

Para reparalo, primero debemos hacer una copia del último EXE que obtuvimos. Seguido a eso cargamos en Olly el original de esa
copia y lo dejamos suspendido en el OEP. Luego copiamos la IAT con BINARY COPY y BINARY PASTE, como ya lo hicimos antes,
nuevamente desde 17F6140-17F67E7 hasta 13F6140-13F67E7, porque REVIRGIN tampoco puede leer la IAT si esta está en su
dirección original.

Antes de ejecutar REVIRGIN, me adelanto y les hago hacer otras cosas para que no tengan que usar nuevamente REVIRGIN luego,
como me pasó a mí, ya que en el proceso original de cracking me fueron surgiendo inconvenientes inesperados.
Con el último EXE suspendido en Olly, presionamos ALT+E para ver los módulos ejecutables. Seleccionamos la DLL Kernel32 y damos
CTRL+N para obtener la lista de APIs de esta librería. Buscamos GetModuleHandleA y también VirtualProtect:

Figura 42

Figura 43

En mi caso estas direcciones son 77E7AD86 y 77E6169E respectivamente (pueden ser otras en sus PCs). Pero.... por qué buscamos
las direcciones de GetModuleHandleA y de VirtualProtect? Bueno, a eso me refería con adelantarme para no hacerles usar
nuevamente Revirgin. En cuanto a la dirección de VirtualProtect debemos introducirla en una de las entradas vacias (00 00 00 00)
que quedaron en la IAT para poder usarla, ya que el programa no hace uso de ella y no tiene entrada en la tabla.

Vamos al programa suspendido en el OEP en Olly y buscamos la primera entrada vacía de la IAT, la cual es la de la dirección
13F61F0:

Figura 44

En esa dirección cargamos en orden inverso la dirección de la IAT VirtualProtect, que en mi caso es 77E6169E:

Figura 45

Aunque parezca mentira, también debemos cargar esa dirección en 17F61F0 de la misma forma que lo hicimos en 13F61F0, porque
sino REVIRGIN no reconocerá la entrada cuando lo usemos. Ya verán más adelante para que necesitamos esta API. Ahora
ejecutamos REVIRGIN y seleccionamos el EXE suspendido en Olly al que acabamos de modificarle la IAT. En OEP, RVA, y LENGTH
cargamos los valores 4CBB24, 13F6140 (ya que copiamos la IAT), y 6A8 respectivamente, y damos click en IAT Resolver y en
Resolve again. Ahora en la columna IATRva buscamos la entrada correspondiente a 13F6308:
Figura 46

damos click derecho sobre la columna address correspondiente a la IATRva 13F6308, entramos en modo Edit y cargamos la dirección
de la API GetModuleHandleA, que en mi caso es 77E7AD86, damos ENTER, y luego click solamente en Resolve again. En ese momento
REVIRGIN carga el nombre de la API en la columna Name, y estamos listos para dar generate! y seleccionar la copia que hicimos del
EXE que tenemos suspendido en Olly. REVIRGIN nos informa que quedan entradas sin resolver pero igual le damos OK.

Una vez reparada la copia de AlcaOllyDumpIAT_OK-ImpRec-InjertosAB-ExcepOut.exe la renombramos como AlcaOllyDumpIAT_OK-


ImpRec-InjertosAB-ExcepOut-Revirgin.exe y listo el proceso: ESTE EXE DEBERIA FUNCIONAR EN CUALQUIER PC.

Ahora daré la explicación de porqué les hice poner en 13F6308 un puntero a la API GetModuleHandleA. Antes de hacer esa
modificación, el EXE que obtenía funcionaba solamente en el sistema operativo donde lo crackee, o sea XP. Cuando ejecuté el EXE
en WinME o W2000, ya que por razones laborales necesitaba que así sea, el maldito seguía resistiéndose. Asi que lo cargué en Olly
(pero esta vez estando en ME o 2000) y le di RUN. Al generarse la excepción, fui al STACK, y subí hasta encontrar el último RETURN:

Figura 47

Observamos que en 12FF7C nos dice que regresa a 41EA4E luego de una llamada a 41E9A4, asi que vamos a ver que hay en esta
última dirección:
Figura 48

Por el contenido de la pila, es evidente que la excepción se produce luego de entar en la CALL de 41E9A9, asi que vamos a la
dirección 406400 a ver que tenemos:

Figura 49

Es parte de la JUMP TABLE que apunta a la entrada 17F6308 de la IAT, la cual contiene el valor 790AE6C. Esto quiere decir que se
producirá un salto a la dirección 790AE6C, y a pesar de haber cargado a través de los BINs la zona A donde se encuentra esta
dirección, el EXE da error en WinME o Win2000, no así en WinXP que fue donde lo crackee.

Para reparar esto debemos posicionarnos sobre 406400 y dar CTRL+R para ver las referencias:

Figura 50

Nos paramos sobre la referencia de la dirección 40B792 y le damos ENTER. Llegamos a quí:

Figura 51

Si analizamos ese código tenemos la solución. Carga en la pila el string "kernel32.dll", realiza la CALL que genera la excepción, y si el
valor devuelto no es 0 llama a GetProcAddress pasándole como primer parámetro el valor devuleto por la CALL que genera la
excepción.

El primer parámetro que se le pasa a GetProccAddress es un handle a una DLL, el cual se obtiene haciendo una llamada a
LoadLibraryA o bien a GetModuleHandleA, por lo tanto todos los CALL 406400 llaman a una de estas dos APIs. Si en cada una de
las referencias que vemos en la figura 50 reemplazamos CALL 406400 por CALL GetModuleHandleA o CALL LoadLibraryA, veremos que
el EXE se ejecuta correctamente hasta mostrar el MesssageBox de la Dongle, tanto en WinXP, WinME, y Win2000.

Esto se puede reparar de dos formas: Una eficaz y otra eficiente. La eficaz consite en buscar la entrada de la JUMP TABLE que
apunta a la entrada de la IAT que a su vez apunta a LoadLibraryA:
Figura 52

La entrada de la IAT que apunta a esta API es 17F62C0, asi que en 406400 podríamos reemplazar:

JMP DWORD PTR DS:[17F6308] por JMP DWORD PTR DS:[17F62C0]

A esto lo llamo eficaz porque solo se podría hacer gracias a que el programa usa la API LoadLibraryA y casualmente devuelve lo
mismo que GetModuleHandleA. Pero si observamos la figura 49 y consideramos que las APIs están ordenadas alfabéticamente y
LoadLibraryA ya tiene su entrada, es muy probable que en 406400 lo que en realidad vaya es GetModuleHandleA.

Asi que la solución eficiente fue la que acabamos de hacer en REVIRGIN.

Ahora si vamos a encargarnos de la Dongle.

Cargamos en Olly el último EXE generado (AlcaOllyDumpIAT_OK-ImpRec-InjertosAB-ExcepOut-Revirgin.exe) y en la Command Bar


escribimos BP CreateFileA seguido de ENTER. Al dar RUN Olly se detiene en nuestros injertos (ya que usamos esa API para abrir los
BINs), por lo tanto pasamos con F9, hasta que en la tercera vez se detiene para ver en la pila que se intenta abrir un driver:

Figura 53

Vemos que se está buscando el driver \\.\GNTCFG. No les recuerda al MELTICE? jeje. Presionamos ALT-F9 y vemos con que nos
encontramos al retornar al código del usuario:

Figura 54

En ese momento si nos fijamos el contenido del registro EAX veremos que es -1 o bien FFFFFFFF (a menos que alguno de uds. tenga
la Dongle instalada, jejeje). En 44E595 se almacena el contenido de este registro y luego se compara para saber si es -1. La API
CreateFileA devuelve -1 si hubo un error, asi que debemos lograr que la comparación no de 0. Para eso antes de ejecutar la
instrucción de la dirección 44E595 editamos el registro EAX y le ponemos cualquier número entero positivo y seguimos traceando con
F8. Yo puse 19. Seguimos tracenado hasta llegar al RETN sin ejecutarlo.

Aquí vamos a hacer un pequeño parche porque esta rutina es llamada en varias partes del programa.

Figura 54b

Pero de que se tratan las NOPs desde las direcciones 44E57C hasta 44E581? Pués son el lugar que ocuparán la llamada al injerto C
que luego agregaremos, ya que ahora solo estamos haciendo los parches en memoria. Y por qué necesitamos un injerto C para hacer
los parches? Sencillo porque algunos de ellos no podremos hacerlos editando el EXE porque este tiene zonas encriptadas que
debemos esperar que se desencripten.

Al retornar por el RETN de 44E5A8 llegamos a una zona de código ofuscado. Damos click derecho y seleccionamos Analysis->Remove
analysis y nos encontramos con esto:

Figura 55

La API DeviceIoControl envía códigos de control a un driver para que efectua alguna operación, pasándole como primer parámetro el
handle del Driver, que es el valor que anteriormente cargamos en EAX. Pero como el driver en realidad no existe, si dejamos que la
llamada a esta API se ejecute, obetendremos un error.

Asi que lo que debemos hacer es nopear esta zona. Marcamos en el dissasembler desde 44EA05 hasta 44EA29 inclusive, damos click
derecho y seleccionamos BINARY->Fill with NOPs. El TEST EAX, EAX de 44EA2E lo dejamos porque EAX no vale NULL al retornar de la
rutina anterior. Como esta rutina de la Figura 55 está encriptada al comenzar la ejecución del EXE, no podemos emparcharla
directamente en disco, por eso lo hará nuestro injerto C.

Si seguimos traceando luego de nopear todas esas direcciones, llegaremos a la CALL de la dirección 44EA42. Si entramos con F7
llegamos a aquí:

Figura 56

Es evidente que si en realidad el driver no existe, intentar cerrar el Handle a este dará error también, asi que la operatoria es la
misma que antes: nopear desde 44E5BD hasta 44E5BE inclusive. Como esa rutina si está desencriptada al inicio de la ejecución,
haremos luego el parche en disco. Seguimos traceando y al retornar de esta API llegamos hasta aquí:

Figura 57

Rutinas como la de la Figura 57 encontraremos en millones de partes de este programa. Es evidente que se trata de una rutina de
desencriptación por la cantidad de XORs que posee. De hecho si tracean con F8, cuando lleguen a la dirección 44EACC JMP EDX
saltarán a una dirección del tipo 12ECCC, y si a partir de ahí continuan con F8 unas poquitas líneas hasta llegar a donde muestra la
figura 58:

Figura 58

luego de ejecutar la instrucción de 12ECEB, verán que el PUSH 101010 de 12ECFF cambia su valor a PUSH 44EB49 como muestra la
siguiente figura:

Figura 59

Esto muestra que a medida que el programa no encuentre anomalías ira desencriptando correctamente determinando la ruta a seguir
por medio de estos pushes.

Seguimos con F8 porque hay más rutinas que nos tirarán fuera. Llegamos hasta aquí:

Figura 60

Si hicieron los parches correctamente y siguen con F8, deberían llegar sin problemas hasta 4C0C2D donde está la llamada a 44F258.
Una vez que llegamos ahí entramos con F7 y seguimos con F8. Llegaremos a una zona que desencripta la cual es muy parecida a la
de la figura 57. La pasamos y seguimos hasta llegar a aquí:

Figura 61
Mmmmmm, y porqué esta zona está en otro color si nosotros no editamos esta parte? Sencillo, porque la rutina desencriptadora fue
la que la editó para proteger ese CALL venenoso a 44ED5C que se realiza en 44F36F. Entremos a él con F7:

Figura 62

Observen las APIs que se utilizan: GetTickCount (seguramente para detectar debuggers), y DeviceIoControl y CloseHandle
nuevamente. Es evidente de que se trata de una rutina que no quiere que lleguemos a nuestros propósitos. Bueno, yo traceé un rato
e hice algunas pruebas y en conclusión, la rutina debe devolver 0 en el registro EAX para que todo esté correcto. Vemos que las dos
direcciones interesantes donde se cargan valores en EAX son:

44EDA9 MOV EAX,1


y
44EDEC MOV EAX,1

les aseguro que emparchando esta rutina correctamente nos ahorramos emparchar muchísimos saltos, ya que si buscan referencias a
la misma no econtrarán más que la de la dirección 44F36F, pero si buscan referencias a 44F258 verán la cantidad enorme que hay. Y
como dentro de 44F258 se llama a 44F36F, si emparchamos la rutina de la figura 62, nos ahorraremos trabajo.

Pues el mejor parche es modificar 44EDA9 y 44EDEC para que queden MOV EAX, 0, y luego nopear desde 44EDB0 hasta 44EDEB, y
desde 44EDF3 hasta 44EE06. Si bien la llamada a la rutina de la Figura 62 está encriptada al inicio de la ejecución, por suerte la
propia rutina no lo está, asi que este parche luego lo haremos en disco también. Por ahora hacemos estos cambios en memoria y
seguimos traceando hasta salir de esta rutina y llegar hasta 4C0C32 (justo después de la llamada a 44F258 en 4C0C2D).

En 4C0C3B vemos una llamada CALL 476EA8. Esta se ejecuta si no hubiésemos emparchado la rutina anterior y es la que nos muestra
el MessageBox que se ve en la figura 41.

En 4C0C60 hay otra llamada maligna (CALL 44FB08), ya que internamente llama a la última rutina que acabamos de emparchar. No
nos preocupamos porque ya devuelve 0.

Seguimos con F8 y llegamos hasta aquí:


Figura 63

Vemos que aquí se llama a 476EA8 que es la CALL que nos muestra el MessageBox si las comparaciones de 6 bytes entre los bytes
apuntados por EAX y EDX no son iguales. Estamos frente a otro tipo de control, el cual muy probablemente se repita en muchos
lados como las llamadas a 44F258. De hecho, posiciónense con el mouse sobre 4C0E88 y den click derecho para seleccionar "Find
references to->Immediate constant"; se abrirá una ventana con aproximadamente 40 referencias.

Obviamente no vamos a emparchar cada una de estas rutinas. Asi que lo que haremos será hacer un parche más profundo (deep in
the code) como hicimos antes. En realidad el parche es sencillo:

Usar BINARY COPY y BINARY PASTE para copiar estos 6 bytes (10 13 9C 3A 8E AD) desde 4DC37C-4DC381 hasta 4E191C-4E1921.
Como al comienzo de la ejecución tanto 4E191C como 4DC37C (que son las direcciones donde apuntan EAX y EDX respectivamente)
no están encriptadas podemos copiar esos 6 bytes desde 4DC37C a 4E191C en disco con un editor Hexa.

Ahora podemos dar RUN y el programa arranca:

Figura 64

Cabe mencionar que el programa tiene millones de chequeos cuando presionamos sobre sus controles. Por ejemplo, si no hubiéramos
hecho los parches anteriores, al seleccionar un celular a través de la combo Phone Type hubiera detectado que la Dongle no está y
nos sacaría fuera.

Pero aún queda un escollo más: Si damos click sobre el botón Connect! el programa detecta que fue desempaquetado. Hagamos una
copia del último EXE y abrámosla con PeiD. Veremos que está hecho en Delphi. Por lo tanto abrimos la copia con DeDe y cuando este
terminó de procesarla vamos a Procedures y seleccionamos Unit 1:

Figura 65

y como el Evento SendBootTLClick es el nombre más relacionado con el botón Connect (no por el nombre en si, sino porque el envío
de la señal de BOOT es lo primero que debe hacerse con los celulares) vamos en el EXE que tenemos en Olly a la dirección que indica
el respectivo RVA = 48EFE8, ponemos un HBP allí, cerramos DeDe y borramos la copia, volvemos al programa cargado con Olly, y
damos click en Connect! (antes de dar click asegúrense de seleccionar un puerto COM que existe en sus PCs y que a la vez esté
libre).

BINGO !!!!! el HBP surte efecto y salta Olly:


Figura 66

A partir de aquí traceamos con F8 hasta alcanzar el JUMP de la dirección 48F1E6:

Figura 67

Damos F8 y llegamos al valor apuntado por ECX:

Figura 68

aquí hace lo siguiente:

0012F384 BE 00004000 MOV ESI,400000 ; ASCII "MZP" ;Carga en ESI la BASE


0012F389 8B46 3C MOV EAX,DWORD PTR DS:[ESI+3C] ;Carga 0x100 en EAX
0012F38C 03C6 ADD EAX,ESI ;Le suma la BASE a EAX
0012F38E 8B40 28 MOV EAX,DWORD PTR DS:[EAX+28] ;Carga el OEP en EAX sin la base
0012F391 03C6 ADD EAX,ESI ;Le suma la BASE
0012F393 BE 00BC4C00 MOV ESI,4CBC00
0012F398 3BC6 CMP EAX,ESI ;Si el OEP es >= a 4CBC00 conside-
0012F39A 77 17 JA SHORT 0012F3B3 ;ra que el programa aún está empaquetado.

En la Figura 01 vimos que el EP del empaquetado es 142C000, y si le sumamos la base sería 182C000, lo cual es el valor correcto que
deberíamos obtener en EAX antes de la comparación de la dirección 12F398. El mejor parche que podemos hacer es este:

Figura 69

Momentáneamente lo hacemos en memoria para seguir traceando. El único inconveniente es que luego este parche deberíamos
hacerlo con el injerto C porque esta parte de código está encriptada al inicio. Es más, recién se desencripta por completo cuando
alcanzamos la dirección 48F1E6 de la figura 67. Asi que ahí deberíamos poner otra llamada al injerto C. Digo deberíamos porque no lo
vamos a hacer, debido a que existen muchas de estas rutinas, y para resolver esto deberíamos poner una llamada al injerto C por
cada rutina. La solución más eficiente que hallé luego la verán.

and the last but not least...seguimos con F8 y llegamos a esto:


Figura 70

Cuando alcanzamos la CALL de la dirección 12F394 debemos entrar con F7 para que no se produzca una excepción, y seguir
traceando hasta alcanzar la dirección 12F3A1. En ese momento los registros contienen estos valores:

Figura 71

Claramente vemos que ".tsehp" es el nombre de la última sección que agregó REVIRGIN cuando reparó la IAT, y que ".svkp "
(INCLUIDO EL ESPACIO AL FINAL DE LA CADENA), es el nombre de la última sección que tenía el EXE original empaquetado. Entonces
es evidente que aquí se realiza algún chequeo. Pero esto es realmente muy fácil de solucionar. Luego lo haremos con PeEditor.

Estos son todos los controles que encontré en el programa. Tal vez haya más, pero no los hallé porque no tengo un celular Alcatel
para probar lo que pasa después de establecer la conexión con el mismo y de que se activen los botones restantes.

Muy bien, entonces reiniciemos en Olly el último EXE que generamos (AlcaOllyDumpIAT_OK-ImpRec-InjertosAB-ExcepOut-
Revirgin.exe) dejándolo suspendido en el OEP y comencemos a hacer en las zonas desencriptadas del archivo los parches que antes
hicimos en memoria.

El primer parche a hacer es el de la figura 54b, con la diferencia de que ahora le vamos a agregar la llamada al injerto C que luego
realizaremos:

Figura 72

El push de la dirección 44E57C es la llamada al injerto C, e indica que está injertado a partir de la dirección 4CBCA3. Puse la llamada
aquí porque al alcanzar esta dirección por primera vez durante la ejecución del programa, las zonas encriptadas se habían
desencriptado.

El próximo parche a realizar es el NOPEADO de las instrucciones de las direcciones 44E5BD y 44E5BE que se ven en las figura 56:
Figura 73

Continuando con los parches de las rutinas no encriptadas, ahora les toca el turno a las rutinas de la figura 62:

Figura 74

Figura 75

Seguimos avanzando y ahora nos encargaremos de copiar 6 bytes a partir de 4DC37C. En el Dump vamos a esa dirección,
seleccionamos, y damos BINARY COPY:

Figura 76
para ir luego a 4E191C y dar BINARY PASTE:

Figura 77

Recordemos que este último parche lo realizamos para salir victoriosos de las rutinas de control como la que se observa en la Figura
63. Con esto hemos finalizado todos los parches que podemos realizar sin la necesidad de un injerto, asi que en el dissasembler
damos click derecho, seleccionamos Copy To Executable->All Modifications->Save File, y guardamos todo en un nuevo archivo
llamado AlcaOllyDumpIAT_OK-ImpRec-InjertosAB-ExcepOut-Revirgin-Patched.exe.

Ya es el momento de develar el porqué de la insericón de la API VirtualProtect. Cómo vimos, el EXE chequea en muchos lugares el
valor del OEP, y que realizar una llamada al injerto C en cada uno de estos lugares es algo engorroso. Entronces como el valor del
OEP es tomado desde el RVA 400128, mi intención es que el injerto sobreescriba en memoria el OEP que está en esa dirección,
cambiando el valor 24 BB 0C 00 (OEP invertido del desempaquetado y sin la base) por este otro 00 C0 42 01 (OEP invertido del
empaquetado sin la base).

El problema era que para realizar esto, necesitaba que esa zona tenga ACCESO DE ESCRITURA para no generar un fallo. Dicha zona
está dentro de la sección del header, pero si cambiamos las características de esta sección con por ejemplo PeEditor para habilitar la
escritura, el fallo se produce igual.

La única forma de que no se produzca es cambiando los permisos de la sección que ocupa el header, utilizando la API VirtualProtect,
la cual será llamada desde nuestro injerto C. La sección del header va desde 400000 hasta 401000. La API necesita de estos
parámetros:

BOOL VirtualProtect(
LPVOID lpAddress, // address of region of committed pages (400000)
DWORD dwSize, // size of the region (1000)
DWORD flNewProtect, // desired access protection (4 == PAGE_READWRITE)
PDWORD lpflOldProtect // address of variable to get old protection
);

Ahora si hagamos el injerto C para emparchar las rutinas encriptadas y sobreescribir el OEP. Debemos considerar que el injerto será
llamado en 44E57C y que luego deberá restaurar las instrucciones originales que hicimos antes en memoria en esa dirección (o sea
los 6 nops).

Anteriormente ya habíamos insertado la llamda en 44E57C. Asi que abrimos Snippet Creator, creamos un nuevo proyecto, vamos a
Action->New Target y seleccionamos UNA COPIA del último EXE generado (no el original porque SC hará lío), luego vamos a Project
Options, y configuramos de esta manera:

Figura 78

y damos OK. Con esa configuración idicamos que el injerto C estará a partir de 4CBCA3, que será llamado desde 44E57C, que no
retornará el control al programa, ya que eso lo programaremos nosotros, y que tampoco restaurará automáticamente las
instrucciones originales. Todo esto lo realizamos solamante para que Snippet Creator genere el injerto (en un archivo BIN) cuando
vayamos a Action->Assemble seguido de Action->Patch Target File, ya que finalmente el archivo que genera debemos injertarlo
manualmente en 4CBCA3, debido a que como el EXE tiene un tamaño de 20 MBs, parece ser muy grande para SC y este da error sin
injertar nada y además dañando el EXE, por eso dije de usar una copia.

Si alguien no tiene ganas de generar el archivo BIN, puede descargarlo pulsando aquí, ya que es el mismo para cualquier PC.

Los que quieren hacer el injert sigan. Luego de dar Ok en Project Options, vamos a la pantalla de edición y copiamos este código:

jmp init

;NOP para nopear las instrucciones de la figura 55 para el envío de órdenes al Driver.
patch1 db 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h,
090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h,
090h, 090h, 090h, 090h, 090h, 090h, 090h, 090h

;OEP del empaquetado


patch2 db 000h, 0C0h, 042h, 001h

;Instruccones originales en el lugar de la primera llamada


original1 db 090h, 090h, 090h, 090h, 090h, 090h

;Variable usada por VirtualProtect en la cual se almacenará el tipo de protección


;previa del Header
OldProtection dd 0

init:
pushad

;Emparchando instrucciones de la figura 55, desde 44EA0C hasta 44EA2D inclusive.


mov edi, 44EA0Ch
lea esi, patch1
mov ecx, 22h
rep movsb

;Llamada a VirtualProtect para otorgar permisos de escritura en el Header


lea esi, OldProtection
push esi
push 4
push 1000h
push 400000h
mov esi, dword ptr ds:[17F61F0h] ;En esta dirección de la IAT está el puntero a la API
CALL ESI

;Sobreescribiendo el OEP en memoria


mov edi, 400128h
lea esi, patch2
mov ecx, 6
rep movsb

;Restaurando los bytes en la primer llamada


mov edi, 44E57Ch
lea esi, original1
mov ecx, 6
rep movsb

;Retornando a 44E582 (lugar posterior a la primera llamada) para seguir con la ejecución normal
popad
push 44E582h
ret

nop

Deberían obtener algo así:


Figura 79

Click en Assemble y luego Action->Patch Target File, ya que a pesar de que Snippet Creator no injertará nuestro injerto por el bug
que comenté antes, si generará un archivo BIN en la carpeta del proyecto, cuyo nombre será el nombre_del_proyecto.bin (en mi
caso Alca.bin).

Abrimos el archivo AlcaOllyDumpIAT_OK-ImpRec-InjertosAB-ExcepOut-Revirgin-Patched.exe con un editor hexa y nos desplazamos al


offset CBCA3. Con el mismo editor abrimos el archivo Alca.bin y copiamos todos sus bytes:

Figura 80

para pegarlos en el offset CBCA3 del otro archivo:

Figura 81

Ahora vamos a Guardar como y nombramos al archivo AlcaOllyDumpIAT_OK-ImpRec-InjertosAB-ExcepOut-Revirgin-Patched-


Snipped.exe

Si damos RUN nos sale una MessageBox diciendo:


Figura 82

Esto se debe a que Olly no plasmó en el EXE la modificación del la figura 77, asi que supongo que esto ocurrió porque esas
direcciones pertenecen a la data section y no a la code section. Asi que abrimos el último EXE con el editor hexa y vamos al offset
E191C para insertar estos 6 bytes: 10 13 9C 3A 8E AD.

Figura 83

Solo resta cambiar el nombre de la última sección para que al dar Connect! no se detecte que el programa fue desempaquetado.
Abrimos el EXE final con PeEditor, vamos a la última sección, y realizamos el cambio:

Figura 84

procurando dejar un ESPCAIO AL FINAL DE LA CADENA .svkp, como vimos anteriormente para que la comparación de OK. Damos
Apply Changes y ya está terminado el proceso de cracking. Si ahora ejecutamos el EXE y damos Connect! no debería haber errores,
solo un mensaje diciendo que no se estableció la conexión con el celular, debido a que en mi caso, no poseo un Alcatel:

Figura 85

Trabajo que medió el útlimo tutorial de este año, uffffffffff. Me despido hasta el 2005 si los Dioses del Metal quieren y deseando Feliz
Navidad y próspero Año Nuevo a todos los colegas. Hasta la próxima.

Saludos
Tutorial dedicado a la memoria de Dimebag "Diamond" Darrell. Donde quieras que estés amigo, tus guitarras permanecerán por siempre
con vida en nuestras memorias, almas, y corazones. Thanks for the music.

Desde las profundidades del abismo...


http://www.sleepersbrains.com/
saccopharynx@yahoo.com

También podría gustarte