Está en la página 1de 6

Descompilar, parchear e ingeniera inversa en Java

Crackear el cdigo con depuradores heterodoxos


Comprender las interioridades desconocidas de las aplicaciones
Este escrito est enfocado en como se utiliza una herramienta heterodoxa la cual nos
permite realizar distintas aproximaciones, para poder observar como se ejecutan
interiormente las aplicaciones. A la realizacin de este trabajo se le da el nombre de
depuracin debugging, lo cual nos permitir aprender el interior desconocido de las
aplicaciones. Trabajar con el cdigo fuente es generalmente la forma adecuada de
realizar el estudio de la ejecucin de una aplicacin, pero existen ciertos casos donde la
utilizacin del depurador es irremplazable, estos pueden ser cuando:
Trabajas con una aplicacin grande en la cual no puedes realizar un rastreo.
Leyendo el cdigo fuente de una aplicacin no te proporciona una clara
comprensin de la lgica de ejecucin, debido a la sofisticada trama de objetos y
a las extraas prcticas de programacin utilizadas.
Ests trabajando con una aplicacin agresivamente ofuscada

Depuradores convencionales y sus limitaciones


El lenguaje Java fue diseado pensando en poder aplicarle la depuracin. Las Java
Debug API dependen del concepto de vista remota para realizar el proceso de
depuracin. Los depuradores estndar tienen implementados un cierto rango de
caractersticas, algunas de ellas como poder colocar puntos de ruptura y poder ejecutar
paso a paso el cdigo de la aplicacin dependen del programador de la aplicacin. Los
depuradores ms avanzados adems de stas incluyen caractersticas adicionales como
pueden ser puntos de ruptura condicionales los cuales paran la ejecucin cuando una
variable tiene cierto valor o cuando cierta excepcin es producida.
Estos depuradores convencionales nos pueden ayudar para solucionar errores en el
cdigo, pero no sirven para realizar ingeniera inversa o arreglar problemas en una
aplicacin compleja. El problema ms grande con estos depuradores es que nos
muestran la informacin en el momento que ocurre y no sabemos lo que va ha ocurrir y
adems la informacin se pierde totalmente. Para ser efectivos, los depuradores
convencionales necesitan poder colocar puntos de ruptura estratgicamente a lo largo
del cdigo para facilitar el trabajo tedioso, especialmente si no conocemos el cdigo.
Por ejemplo, refirindonos a la aplicacin Chat queremos conocer que procesos se
utilizan para recibir los mensajes. En principio podemos cargarlo y ejecutarlo en modo
de depuracin, pero Cmo sabrs donde colocar los puntos de ruptura? Adems an
siendo Chat una aplicacin pequea, aunque vayas realizando el cdigo paso a paso no
te ser de ninguna ayuda, ya que los mensajes son recibidos por un hilo RMI asncrono.
Slo la descompilacin y un estudio apurado del cdigo podrn ayudarte a conseguir el
mtodo receiveMessage definido en ChatServerRemote e implementado en
ChatServer. Pero si adems intentas realizar ingeniera inversa en la versin ofuscada
con Zelix KlassMaster de la aplicacin Chat. El trabajo an se dificulta mucho ms.
Con lo cual necesitas una buena herramienta que te ayudar en este trabajo. Dicha
herramienta puede ser el Omniscient debugger.

Hacking y cracking con Omniscient Debugger


La depuracin con Omniscient, permite grabar el estado del programa en ejecucin y
poder ir hacia atrs de lo ocurrido para examinar su estado. La diferencia con respecto a
los depuradores convencionales es que la aplicacin no puede ser utilizada en modo de
depuracin con la cual no puede ser pausada. La idea principal del depurador
Omniscient es grabar toda la informacin posible respecto a los hilos y variables, sus
valores y los flujos de estos tanto de entrada como de salida y el cargado de las clases.
Una vez la informacin ha sido grabada, la aplicacin puede ser parada o cerrada.
Entonces el depurador puede utilizarse para rastrear la ejecucin desde su inicio hasta su
final, o inicindolo desde un punto en particular identificado por una llamada a un
mtodo o un mensaje escrito por el flujo de salida estndar. Esto se realiza colocando
puntos de ruptura en los lugares necesarios.
Aqu, slo daremos una explicacin de cmo se ejecuta el Omniscient Debugger (ODB)
de Bil Lambda. Est distribuido bajo licencia GPL y puede descargarse de
http://www.lambdacs.com/debugger/debugger.html. Todava necesita un considerable
desarrollo, especialmente de UI, pero realiza trabajos de grabacin e investigacin
asombrosamente buenos. ODB usa una tcnica de adorno del bytecode basada en la
insercin de registros de informacin de depuracin al cdigo. Supongamos que no
conocemos nada de la aplicacin Chat y utilizamos el depurador ODB para aprender
cmo Chat procesa los mensajes entrantes.

Grabar la ejecucin de la aplicacin Chat


Para empezar grabaremos la ejecucin de Chat en ODB. Existe una versin de ODB en
el directorio CovertJava/lib. Yo utilizar la versin nueva ODB1.5. Bien ejecutaremos
debugChat.bat, que est localizado en CovertJava/bin este archivo batch configura el
entorno de ODB y nos ejecuta covertjava.chat.ChatApplication. Cuando nos pregunte
por la localizacin del cdigo fuente de ChatApplication, seleccionaremos No Source
Available para restringir el trabajo slo al bytecode. La figura 9.1 nos muestra la
ventana del depurador despus del paso de inicializacin.

La interconexin de usuario de ODB no es que sea muy intuitiva, pero despus de


utilizarla un poco, vers que se puede navegar con efectividad. Arriba de todo despus
de la barra de mens, tenemos la barra de herramienta de instantneas Stamp. El
depurador ODB graba la ejecucin del programa en una secuencia de instantneas y con
la barra de herramientas Stamp, puedes ir hacia atrs o hacia delante de la secuencia.
Tambin existen varios paneles que muestran informacin con respecto el estado de la
aplicacin:
Threads: Este panel muestra los hilos grabados. Si el nombre de un hilo finaliza con - significa que en la instantnea actual el hilo no ha sido creado todava. Si el hilo ha
finalizado, se mostrar Dead.
Stack: Este panel muestra el call stack del hilo seleccionado y en ese momento.
Locals: Este panel muestra los nombres y valores de las variables locales
correspondientes al mtodo seleccionado en el call stack o en el panel Method Traces.
This: Este panel muestra el resultado de las llamadas a toString ( ), en el objeto del
cual se ha seleccionado el mtodo.
Method Traces: Este panel muestra la secuencia de los mtodos llamados, incluyendo
las llamadas anidadas que estn endentadas.
Code: Este panel muestra el cdigo fuente si est disponible.
TTY Output: Este panel muestra las llamadas interceptadas a System.out.println
(ODB no soporta actualmente otros mtodos de salida).
Objects: Este panel muestra las versiones de los campos de cadena de los objetos que
se estn observando en ese momento.
Vamos a explicar la informacin mostrada en la figura 9.1. Podemos ver lo siguiente,
despus de la inicializacin, la aplicacin Chat tiene tres hilos de ejecucin. El primero
de ellos es <main_0>, el cual lo tenemos seleccionado actualmente y no tiene ningn
call stack ya que actualmente ha finalizado su ejecucin; sin embargo en el panel
Method Traces podemos ver todos los mtodos ejecutados en este hilo. Si nos vamos
deslizando a lo largo del panel Method Traces tendremos un log completo de los
nombres de los mtodos y valores de los parmetros de los eventos. Seleccionando un
mtodo en el panel Method Traces, tendremos lo que el mtodo ha ejecutado hasta este
momento y adems se actualizan todos los otros paneles con la informacin
correspondiente respecto al mtodo. De la misma forma si seleccionamos un mensaje
del panel TTY Output habilitamos el poder ver quien lo ha imprimido y cuando. Para
rastrear la ejecucin del programa desde el inicio, haremos clic en el botn First
Timestamp (Any Thread) en la barra de herramientas de Stamp (parecido al botn
rebobinar de un DVD), y entonces hacemos clic en el botn Next Timestamp (Any
Thread) (parecido al botn Play de un DVD) para avanzar paso a paso.

Navegar por lo mensajes procesados por el cdigo


Bien ahora estamos preparados para crackear los mensajes procesados por el cdigo de
la aplicacin Chat. En primer lugar arreglaremos un bug que tiene ODB el cual nos

impide obtener informacin de las clases cargadas dinmicamente. Si tienes cerrada la


ventana Debugger Controller, pulsa Alt+Tab la seleccionas y esta aparecer tiene un
botn Stop Recording y algunos check box que especifican las opciones de grabacin.
Haz clic en el botn Stop Recording; cuando el label cambie a Start Recording, otra vez
clic. Entonces pulsa Alt+Tab y abre la ventana de la aplicacin Chat. Ahora en el
combo box Host Name escribe localhost y en el campo de texto escribe el mensaje
Hello. Pulsa enter para enviar el mensaje y asegrate que aparece en el campo de
conversacin de Chat. Ahora hacemos clic en el botn Last Timestamp Recorded
(Any Thread) en la barra de herramientas de Stamp, lo cual nos muestra rpidamente
las ltimas secuencias grabadas. En el panel TTY Output deberemos ver ahora ms
lneas. Clic en la lnea que dice Received message from host. La ventana de
depuracin que debemos ver tiene que ser similar a la figura 9.2.

De la informacin mostrada en los paneles del depurador, podemos saber que el


mensaje ha sido imprimido por el mtodo ChatServer.receiveMessage y ejecutado en
un hilo de RMI TCP Connection. Esto tiene sentido porque, como sabemos, la
aplicacin Chat depende de RMI para mandar los mensajes. Si nos desplazamos por el
panel Method Traces, podemos ver exactamente lo que ha ocurrido antes y despus de
la llamada a System.out.println. Podemos ver que el texto de mensaje es obtenido por
la clase MessageInfo y aadido a JEditorPane dentro de MainFrame. As pues, an
sin utilizar el cdigo fuente, tenemos una comprensin bastante buena del
procesamiento lgico de los mensajes en la aplicacin Chat.
El trabajo ha sido fcil ya que el rastro del mensaje, Received message from host
nos ha llevado directamente al mtodo responsable del procesamiento de ste. Qu
hubiera ocurrido si no tuviramos esta pista? Pues que otras formas de acercamientos
nos hubieran llevado al mismo lugar. Primero despus de grabar todas las acciones que
realiza la aplicacin, hay que mirar bien el panel Threads. Siendo conocedores de la
arquitectura Java, esto nos ayudar a decidir qu hilo hay que mirar. Por ejemplo,

conociendo la comunicacin remota entre las aplicaciones Java y sabiendo que utilizan
RMI y que RMI procesa las llamadas entrantes en su propio hilo, podemos buscar tales
hilos. No te sorprendas, despus de hacer un rpido avance hasta el final con la
depuracin del mensaje enviado, puedes volver a ver un nuevo hilo RMI TCP
Connection Seleccionando el hilo en el panel Threads muestra los mtodos
ejecutados y he aqu, otra vez vemos ChatServer.receiveMessage al inicio del rastro.
Otra forma buena de hallar la lgica de procesamiento de los mensajes es utilizando la
caracterstica de ODB Search. Aunque no es muy sofisticada, nos permite buscar una
cadena en el panel de rastros. En nuestro caso conocemos el texto del mensaje Hello
Si no estamos seguros del hilo que ejecuta el procesamiento lgico de mensajes, pulsas
la opcin en el men del debugger Code/ Any Thread OK . Entonces podemos
seleccionar Search desde el men Trace y escribir Hello en la lnea de comandos de
abajo. Pulsando enter el depurador hallar y seleccionar el rastro que contiene la
cadena buscada, que en este caso es como supones, ChatServer.receiveMessage.
Una vez localizados la clase y el mtodo, podemos usar el cdigo fuente o el cdigo
descompilado para estudiar la lgica de ejecucin. Ahora si puedes utilizar un
depurador convencional para ejecutar la aplicacin en modo de depuracin y ver en
vivo los datos ya que sabemos donde colocar los puntos de ruptura.

Usar ODB para crackear la versin ofuscada de Chat


En el escrito DPIIjava3, Ofuscacin de clases y en el escrito DPIIjava4, Hackear y
crackear mtodos y variables de una clase no pblica, se explic la ofuscacin y las
dificultades para crackear las aplicaciones agresivamente ofuscadas. Descompilar y
comprender una aplicacin ofuscada es muy pesado y posiblemente imposible. Utilizar
un depurador como ODB es la mejor forma de trabajar con dichas aplicaciones, antes
que tratar de imaginar la sucesin de las llamadas de los mtodos, ya que puedes
simplemente estudiar la versin grabada por l. Lo mismo se puede aplicar para
localizar el punto de inicio de las clases que podrn utilizarse para ofuscar el cdigo.
Para que nos quede claro este punto vamos a realizar el mismo ejercicio anterior pero
esta vez con la versin ofuscada.
Cambiamos el CLASSPATH dentro de debugChat.bat de lib\chat.jar por
lib\obfuscated\chat.jar. Ejecutamos el depurador y realizamos los mismos pasos
descritos en el prrafo anterior. Despus de que el mensaje haya sido enviado,
avanzamos hasta el final de la depuracin con la barra de herramientas Stamp.
Comparamos la informacin mostrada en los paneles de depuracin con la otra
informacin mostrada por el Chat no ofuscado, veremos que fundamentalmente es la
misma. Y, aunque los nombres de mtodos y clases de Chat han cambiado, el call stack
y los valores de los parmetros no lo han hecho. Tampoco tienes la informacin de
sistema como las clases de ncleo de Java y los nombres de los hilos. El listado 9.1
muestra el contenido del panel Method Traces del Chat ofuscado.
LISTADO 9.1 Contenido del panel Method Traces
**<d_0>.receiveMessage(Hello, <MessageInfo_1>) -> void
<MessageInfo_1>.a() -> localhost
<PrintStream_0>.println(Received message..) -> void
<f_0>.a(Hello, <MessageInfo_1>) -> void
<f_0>.b(Hello, <MessageInfo_1>) -> void

<MessageInfo_1>.b() -> localhost


<MessageInfo_1>.a() -> localhost
b -> localhost
<JEditorPane_0>.setText(<HTML><BODY><fon..) -> void
b -> void
a -> void
receiveMessage -> void
Puedes utilizar el depurador parado para hallar cualquier mtodo que haya dado como
salida la impresin del mensaje Received message from host o cualquier mtodo
que en su rastro incluya la cadena Hello. Esto nos proporciona una gran ventaja para
localizar el punto de inicio para estudiar la aplicacin.

También podría gustarte