Hola...

Aunque la programación no es lo mio, voy a ir poniendo en esta sección, tutoriales y/o códigos que voy encontrando por la red... Pues siempre estoy buscando, cosas que me llamen la atención y que puedan servir.

Antes de empezar, quiero dejar claro que estos textos y códigos no son míos. Tan solo, son traducciones que hago desinteresadamente, por si hay gente que al igual que a mi, el ingles no se le da muy bien que digamos.

Esta serie de posts, van a ir desgranando diferentes técnicas, usadas para DLL Injection o Inyección de DLL. Al finalizar la serie, pondré los enlaces a la web original y su autor, que es quien tiene todo el merito.

[Enlace externo eliminado para invitados] (DLL) son módulos de código, que contienen conjuntos de funciones que otros ejecutables pueden llamar. A diferencia de las [Enlace externo eliminado para invitados], que pasan a formar parte de un ejecutable durante el proceso de compilación, las DLL pueden vivir solas fuera de la aplicación que las utiliza. Hay dos formas de realizar la vinculación con archivos DLL: [Enlace externo eliminado para invitados] o [Enlace externo eliminado para invitados]. En la vinculación implícita, durante la fase de compilación, la aplicación se vincula con un archivo de biblioteca de importación proporcionado por el desarrollador de la DLL. Cuando se carga la aplicación, el cargador de Windows identificará que hay una referencia vinculada dinámicamente y cargará la DLL en el espacio de direcciones de la aplicación. Por otro lado, la vinculación explícita implica que la aplicación cargue la DLL manualmente con el uso de la función [Enlace externo eliminado para invitados] y resuelva punteros a funciones que le gustaría llamar llamando a [Enlace externo eliminado para invitados]. A los efectos de demostrar la inyección de DLL, solo se utilizarán enlaces explícitos. Las DLL sirven como un excelente punto de entrada para comprender cómo se comporta un proceso, ya que la DLL se cargará en el espacio de direcciones del proceso. La mejor manera de realizar manipulación de procesos complejos, es decir, enlazar funciones, modificar el estado de la memoria, cambiar el flujo de control, etc., es escribir una DLL con su funcionalidad e inyectarla en el proceso de destino. Esta serie de publicaciones cubrirá las diversas técnicas mediante las cuales esto se puede lograr.Antes de poder inyectar una DLL, deberá crear una. Al igual que la función main de una aplicación de consola, las DLL tienen su propio punto de entrada llamado [Enlace externo eliminado para invitados].

Código: Seleccionar todo

// hinstDLL will contain the address that the
// DLL was loaded at.

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
     LPVOID lpvReserved) {

     switch (fdwReason) {

// DLL is being mapped into another processes address space.

  case DLL_PROCESS_ATTACH:
       break;

// A thread in the process is being created

  case DLL_THREAD_ATTACH:
       break;

// A thread in the process is terminating

  case DLL_THREAD_DETACH:
       break;

// DLL is being unmapped from the process address space.

  case DLL_PROCESS_DETACH:
       break;
  }
  return TRUE;
}
Una función DllMain que no hace nada.

Esta función se llama inicialmente cuando se carga la DLL, pero también se puede volver a llamar varias veces después. Cuando se llama a DllMain, el segundo parámetro que se le pasa contendrá un código de motivo que indica qué condición está provocando la llamada.

El código de motivo será uno de los cuatro valores posibles, cuyo propósito se describe en el código anterior. La razón principal de estas diferentes llamadas, es permitir a los desarrolladores realizar cualquier inicialización por proceso o por subproceso y lógica de limpieza. Como desarrollador, no es necesario que maneje los cuatro estados posibles; escriba código solo para los casos que le interesen*.* En realidad, no necesita definir una función DllMain en absoluto si su DLL es una DLL de solo recursos. Sin embargo, ese no será el caso de ninguno de los ejemplos presentados en esta serie.Los procesos de Windows tienen espacios de direcciones aislados entre sí. Si bien puede romper este aislamiento y efectuar cambios en el espacio de direcciones de otros procesos con la ayuda de funciones como [Enlace externo eliminado para invitados][Enlace externo eliminado para invitados][Enlace externo eliminado para invitados][Enlace externo eliminado para invitados], y similar, sería muy tedioso y propenso a errores escribir una aplicación que cambie externamente una gran cantidad de estado de memoria en otro proceso, especialmente si ese segundo proceso no lo espera. Ahí es donde entra en juego la inyección de DLL; Esta técnica le permite ejecutar funciones que ha escrito en una DLL en otro espacio de direcciones de procesos. Hay muchas formas de realizar la inyección de DLL, que se cubrirán en el resto de esta serie. A menos que se indique explícitamente, la DLL que se está inyectando tendrá el mismo código que el código mostrado arriba, pero con una pequeña modificación: mostrará un cuadro de mensaje en DLL_PROCESS_ATTACH.

Código: Seleccionar todo

// DLL is being mapped into another processes address space.
case DLL_PROCESS_ATTACH:
    MessageBoxA(nullptr, "DLL Injected!", nullptr, 0);
break;
Depuración de DLL inyectadas

Si está escribiendo código, es probable que necesite depurarlo en algún momento. Esto se vuelve aún más cierto cuando escribe código que se inyectará en otro proceso. La depuración será aún más compleja ya que su código puede estar interactuando con el proceso de destino en un nivel muy bajo, es decir, sobrescribiendo directamente el código ejecutable, modificando estructuras en memoria, llamando a funciones internas y similares.

Si descubre que el proceso de destino falla después de haber inyectado su DLL, puede resultar difícil determinar dónde ocurrió el problema. Afortunadamente, puede depurar su DLL inyectada con Visual Studio. Antes de inyectar su DLL, adjunte al proceso de destino con el depurador de Visual Studio seleccionando Depurar -> Adjuntar al proceso… en la barra de menú. Una vez conectado el depurador, puede establecer puntos de interrupción en su código DLL y luego inyectarlo. Una vez que se inyecta la DLL, Visual Studio cargará la información del símbolo para la DLL y le permitirá depurar el código de ejecución como de costumbre.

Proxy DLL

La primera técnica presentada en realidad no realiza la inyección de DLL en el sentido tradicional. En cambio, el proxy de DLL implica reemplazar una DLL que el proceso de destino carga con la suya propia. Por ejemplo, si sabe que su proceso de destino carga GenericDll.dll, puede cambiar el nombre de GenericDll.dll a GenericDll2.dll y colocar su archivo DLL como GenericDll.dll en la ruta de la aplicación. Luego la aplicación cargará tu DLL, momento en el que podrás hacer lo que desees. La única advertencia con el proxy de DLL es que su DLL debe exportar las mismas funciones que la DLL original. La aplicación de destino está cargando la DLL por algún motivo; se espera que en algún momento la aplicación quiera llamar a funciones que proporciona la DLL. Si su DLL de reemplazo no los exporta, es muy probable que sucedan cosas malas, es decir, que la aplicación falle. Supongamos que GenericDll.dll es una DLL muy simple con el siguiente código fuente:

Código: Seleccionar todo

extern "C" {

__declspec(dllexport) void DisplayHelloWorld() {
    MessageBoxA(nullptr, "Hello World!", nullptr, 0);
} 

}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
    LPVOID lpvReserved) {
    return TRUE;
}
 
El código fuente de GenericDll.dll.

Creando la DLL Proxy

GenericDll.dll simplemente exporta una función llamada DisplayHelloWorld. Para que su DLL proxy funcione, cree una función DisplayHelloWorld, cargue la DLL original en ella, use GetProcAddress en el DisplayHelloWorld original para obtener la dirección de la función y realice la llamada en nombre del proceso de destino.

Esto funcionará, pero no escala bien. Las DLL pueden tener cientos de funciones y recrearlas (incluidos sus parámetros y tipos de retorno) requiere una gran cantidad de código repetitivo y es muy propenso a errores. La solución a esto es utilizar funciones de reenvío. Al crear una DLL, puede especificar una directiva de vinculación que creará una exportación para una función y reenviará la implementación real a otra DLL.

Código: Seleccionar todo

#pragma comment(linker, "/export:DisplayHelloWorld=GenericDll2.DisplayHelloWorld")
#include <windows.h>

[code=cpp]BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
    LPVOID lpvReserved) {

    switch (fdwReason) {
    case DLL_PROCESS_ATTACH:
        MessageBoxA(nullptr, "Proxy DLL Loaded!", nullptr, 0);
    }

    return TRUE;
} 
El código fuente de Proxy DLL con un reenviador de funciones.

La [Enlace externo eliminado para invitados] anterior, le dice al vinculador que una función llamada DisplayHelloWorld en realidad será implementado por otra función llamada DisplayHelloWorld en una DLL llamada GenericDll2.dll.

Bueno, pues esta es la primera parte, ire poniendo las demas hasta un total de 5, que forman el conjunto de esta serie, espero que le sirva a alguien.

Saludos a tod@s...

cLn



 [/code]
Imagen


Solo lo mejor es suficiente...
Este es un buen método para establecer persistencia en una dll o hacer un uac bypass (no demasiado silencioso), entre otros
Imagen
Responder

Volver a “Manuales”