lunes, 29 de marzo de 2010

Inyección de código en ensamblados .NET

Durante este articulo se verá cómo es posible modificar los ensamblados en .NET de modo que se pueda inyectar tanto código .NET o código no manejado en este tipo de aplicaciones, pudiendo dotarlas de nuevas características, tales como plugins (o malware) sin que la aplicación original disponga de soporte para ello.

Para realizar éste ejemplo es necesario un decompilador de .NET (Reflector), un plugin con el que inyectar código IL (Reflexil) y un mínimo de conocimientos del lenguaje .NET y IL.

Antes de comenzar, se debe instalar el plugin ‘Reflexil’ para ‘Reflector’. Para agregarlo, basta con ir a ‘View -> Add-ins -> Add’ y cargar la librería ‘reflexil.dll’. Una vez cargado, es posible acceder a su menú haciendo clic en ‘Tools -> Reflexil’.


Figura 1: Cargando plugin Reflexil

Como segundo paso se crea una pequeña librería en .NET que será la que la aplicación cargará, consiguiendo así la ejecución de código y accesibilidad a sus componentes internos a través de reflexión.

La Liberia, en esta caso es muy sencilla, únicamente cargará un formulario con una imagen y mostrará un mensaje.


Figura 2: Código que se cargará en la aplicación como DLL

Una vez hecha la librería, es necesaria la decompilación de la aplicación sobre la cual se quiere realizar la inyección de código. En éste caso se ha escogido, como ejemploNotepad.NET. Basta con arrastrar el ejecutable sobre el panel de ‘Reflector’, y se mostrará un árbol con todas sus métodos, propiedades, etc...


Figura 3: Código que se cargará en la aplicación como DLL

Para saber donde realizar la inclusión del código se debe localizar el punto de entrada de la aplicación, o el método en el que se desée que se ejecute el código. En este caso se va a realizar sobre la entrada a la aplicación, en Main(String[]).

Una vez llegado a éste punto, es hora de usar ‘Reflexil’ para la inclusión de código IL. Unicamente se deben inyectar las instrucciones necesarias para que realice la carga de forma dinámica de la librería que se ha creado anteriormente.

No os asustéis si no sois expertos en reversing, únicamente son cinco instrucciones. Una vez la aplicación esté parcheada no será necesaria volver a modificarlas. Basta con hacer clic derecho sobre el panel de ‘Instructions’ del plugin y clic sobre ‘Create new’ para agregar las siguientes instrucciones:

· LDSTR ‘c:\ruta\libreria.dll’

· CALL System.Reflection.Assembly::LoadFile(System.String)

· LDSTR ‘namespace.class’

· CALLVIRT System.Reflection.Assembly::CreateInstance(System.String)

· POP


Figura 4: LDSTR ‘c:\ruta\libreria.dll’


Figura 5: CALL System.Reflection.Assembly::LoadFile(System.String)


Figura 6: LDSTR ‘namespace.class’


Figura 7: CALLVIRT System.Reflection.Assembly::CreateInstance(System.String)


Figura 8:POP

Cuando se busque el método CreateInstance() o LoadFile() en las instrucciones CALLy CALLVIRT hay que tener en cuenta que éstas se encontrarán dentro del nodo‘mscorlib -> CommonLanguajeRuntimeLibrary -> System.Reflection -> Assembly’.


Figura 9: Ubicación método LoadFile()

Una vez finalizado, el método modificado debería quedar de forma similar a la siguiente captura de pantalla. En azul está el código inyectado que realiza la carga de la librería:


Figura 10: Código inyectado

Tras todo este proceso, basta con guardar el ensamblado modificado haciendo clic en el nodo del ensamblado en Reflector, y a continuación en ‘Save As’.


Figura 11: Guardando el ensamblado modificado

Si todo se ha realizado correctamente, al ejecutar la aplicación se cargará y ejecutará la nueva librería, consiguiendo así el objetivo de inyectar código en un compila .NET tal y como se puede ver en la siguiente captura de pantalla, donde, junto con la ejecución de la aplicación, también se ha ejecutado el formulario que desarrollado en la librería.


Figura 12: Ejecución de código inyectado

Si se hace uso de ProcessExplorer se puede observar como la aplicación tiene cargada en memoria la librería ‘dll.dll’.


Figura 13: dll.dll vista en Process Explorer

Éste ha sido un sencillo ejemplo de los pasos necesarios para la posibilidad de ejecución de código por una aplicación. Ésto, junto con conocimientos de reflexión en .NET abre un gran número de posibilidades, donde se puede obtener un gran control sobre la aplicación, ofreciendo la posibilidad de crear o agregar nuevas características a las mismas.

Por supuesto, en Black Hat Europe 2009 alguien pensó que estas posibilidades se podían utilizar para crear Rootkits directamente el .NET framework.

No hay comentarios:

Publicar un comentario