En programación de computadoras , la inyección de DLL es una técnica utilizada para ejecutar código dentro del espacio de direcciones de otro proceso forzándolo a cargar una biblioteca de vínculos dinámicos . [1] La inyección de DLL es a menudo utilizada por programas externos para influir en el comportamiento de otro programa de una manera que sus autores no anticiparon ni pretendieron. [1] [2] [3] Por ejemplo, el código inyectado podría enganchar llamadas a funciones del sistema, [4] [5] o leer el contenido de los cuadros de texto de las contraseñas , lo que no se puede hacer de la forma habitual. [6]Un programa utilizado para inyectar código arbitrario en procesos arbitrarios se llama inyector de DLL .
Enfoques en Microsoft Windows
Hay varias formas en Microsoft Windows para forzar que un proceso cargue y ejecute código en una DLL que los autores no pretendían:
- Los archivos DLL enumerados en la entrada del registro
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs
se cargan en cada proceso que carga User32.dll durante la llamada inicial de ese archivo DLL. [7] [8] [9] A partir de Windows Vista , las AppInit_DLL están deshabilitadas de forma predeterminada. [10] A partir de Windows 7, la infraestructura AppInit_DLL admite la firma de código . A partir de Windows 8 , toda la funcionalidad AppInit_DLL está deshabilitada cuando el Arranque seguro está habilitado, independientemente de la firma de código o la configuración del registro. [11] - Los archivos DLL enumerados bajo la clave de registro
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs
se cargan en cada proceso que llama a las funciones de la API de Win32 CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW, CreateProcessWithTokenW y WinExec. Esa es la forma correcta de utilizar la inyección de DLL legal en la versión actual de Windows: Windows 10. DLL debe estar firmado por un certificado válido. - Las funciones de manipulación de procesos como CreateRemoteThread o técnicas de inyección de código como AtomBombing, [12] pueden usarse para inyectar una DLL en un programa después de que se haya iniciado. [5] [6] [13] [14] [15] [16]
- Abra un asa para el proceso de destino. Esto se puede hacer generando el proceso [17] [18] o eliminando algo creado por ese proceso que se sabe que existe, por ejemplo, una ventana con un título predecible, [19] u obteniendo una lista de procesos en ejecución. [20] y escaneando el nombre de archivo del ejecutable de destino. [21]
- Asigne algo de memoria en el proceso de destino, [22] y se escribe en él el nombre de la DLL que se inyectará. [13] [23]
- Este paso se puede omitir si un nombre de DLL adecuado ya está disponible en el proceso de destino. Por ejemplo, si un proceso se vincula a ' User32.dll ', ' GDI32.dll ', ' Kernel32.dll ' o cualquier otra biblioteca cuyo nombre termine en '32 .dll ', sería posible cargar una biblioteca llamada '32 .dll '. En el pasado, se ha demostrado que esta técnica es eficaz contra un método de protección de los procesos contra la inyección de DLL. [24]
- Cree un nuevo hilo en el proceso de destino [25] con la dirección de inicio del hilo establecida como la dirección de LoadLibrary y el argumento establecido en la dirección de la cadena recién cargada en el destino. [13] [26]
- En lugar de escribir el nombre de una DLL para cargar en el destino e iniciar el nuevo subproceso en LoadLibrary, se puede escribir el código que se ejecutará en el destino e iniciar el subproceso en ese código. [6]
- A continuación, el sistema operativo llama a la rutina de inicialización de la DLL inyectada. [13] [27]
- Tenga en cuenta que sin precauciones, este enfoque puede ser detectado por el proceso de destino debido a las notificaciones DLL_THREAD_ATTACH enviadas a cada módulo cargado cuando se inicia un hilo. [27]
- Llamadas de enlace de Windows como SetWindowsHookEx. [2] [5] [6] [28] [29] [30]
- Use la función SuspendThread o NtSuspendThread para suspender todos los subprocesos, y luego use la función SetThreadContext o NtSetContextThread para modificar el contexto de un subproceso existente en la aplicación para ejecutar código inyectado, que a su vez podría cargar una DLL. [4] [31] [32]
- Aproveche las limitaciones de diseño en Windows y las aplicaciones que llaman a la función LoadLibrary o LoadLibraryEx sin especificar una ruta completa a la DLL que se está cargando. [33] [34] [35]
- De funcionamiento a nivel de sistema cuñas .
- Sustituir una DLL específica de la aplicación con un reemplazo falso que implementa las mismas exportaciones de funciones que la original. [36]
Enfoques en sistemas similares a Unix
En sistemas operativos tipo Unix con el enlazador dinámico basado en ld.so (en BSD ) y ld-linux.so (en Linux ), las bibliotecas arbitrarias se pueden vincular a un nuevo proceso dando el nombre de ruta de la biblioteca en la variable de entorno LD PRELOAD , que se puede configurar global o individualmente para un solo proceso. [37]
Por ejemplo, en un sistema Linux, este comando lanza el comando "prog" con la biblioteca compartida del archivo "test.so" vinculado a él en el momento del lanzamiento:
LD_PRELOAD = "./test.so" prog
Esta biblioteca se puede crear de la misma forma que otros objetos compartidos . Con GCC , esto implica compilar el archivo fuente que contiene los nuevos globales que se vincularán, con -fpic o -fPIC opción, [38] y enlazando con la -opción compartida . [39] La biblioteca tiene acceso a los símbolos externos declarados en el programa como cualquier otra biblioteca.
En macOS , el siguiente comando inicia el comando "prog" con la biblioteca compartida del archivo "test.dylib" vinculado a él en el momento del lanzamiento: [40]
DYLD_INSERT_LIBRARIES = "./test.dylib" DYLD_FORCE_FLAT_NAMESPACE = 1 prog
También es posible utilizar técnicas basadas en depuradores en sistemas similares a Unix. [41]
Código de muestra
Usando la función de API LoadLibrary
La siguiente función de ejemplo utiliza un método de inyección de DLL que aprovecha el hecho de que kernel32.dll está asignado a la misma dirección en casi todos los procesos. Por lo tanto, LoadLibrary (que es una función de kernel32.dll) también se asigna a la misma dirección. LoadLibrary también se ajusta a la rutina de inicio del hilo requerida por CreateRemoteThread.
#include HANDLE inject_DLL ( const char * file_name , int PID ) { HANDLE h_process = OpenProcess ( PROCESS_ALL_ACCESS , FALSE , PID ); // recuperando un identificador para el proceso de destino char fullDLLPath [ _MAX_PATH ]; // obtener la ruta completa del archivo DLL GetFullPathName ( nombre_archivo , _MAX_PATH , fullDLLPath , NULL ); LPVOID DLLPath_addr = VirtualAllocEx ( h_process , NULL , _MAX_PATH , MEM_COMMIT | MEM_RESERVE , PAGE_READWRITE ); // asignando memoria en el proceso de destino WriteProcessMemory ( h_process , DLLPath_addr , fullDLLPath , strlen ( fullDLLPath ), NULL ); // escribiendo la ruta dll en esa memoria LPVOID LoadLib_addr = GetProcAddress ( GetModuleHandle ( "Kernel32" ), // obteniendo la dirección LoadLibraryA (la misma en "LoadLibraryA" ); // todos los procesos) para iniciar la ejecución en ella HANDLE h_rThread = CreateRemoteThread ( h_process , NULL , 0 , // iniciando un hilo de ejecución remota en LoadLibraryA ( LPTHREAD_START_ROUTINE ) LoadLib_addr , DLLPath_addr , 0 , NULL ); // y pasando la ruta dll como argumento WaitForSingleObject ( h_rThread , INFINITE ); // esperando a que se termine Código_salida DWORD ; GetExitCodeThread ( h_rThread , y exit_code ); // recuperando el valor de retorno, es decir, el módulo // manejador devuelto por LoadLibraryA CloseHandle ( h_rThread ); // liberando el identificador del hilo inyectado, VirtualFreeEx ( h_process , DLLPath_addr , 0 , MEM_RELEASE ); // ... y la memoria asignada para la ruta de la DLL, CloseHandle ( h_process ); // ... y el identificador del proceso de destino return ( MANIJA ) código_salida ; }
Referencias
- ↑ a b James Shewmaker (2006). "Analizando la inyección de DLL" (PDF) . Presentación GSM . Bluenotch. Archivado desde el original (PDF) el 3 de diciembre de 2008 . Consultado el 31 de agosto de 2008 .
- ^ a b Iczelion (agosto de 2002). "Tutorial 24: Ganchos de Windows" . Página de inicio del ensamblaje Win32 de Iczelion . Archivado desde el original el 1 de agosto de 2008 . Consultado el 31 de agosto de 2008 .
- ^ Rocky Pulley (19 de mayo de 2005). "Ampliación del Administrador de tareas con inyección de DLL" . CodeProject . CodeProject. Archivado desde el original el 6 de febrero de 2009 . Consultado el 1 de septiembre de 2008 .
- ^ a b Nasser R. Rowhani (23 de octubre de 2003). "Tutorial de inyección e interceptación de funciones de DLL" . CodeProject . CodeProject . Consultado el 31 de agosto de 2008 .
- ^ a b c Ivo Ivanov (2 de diciembre de 2002). "API de enganche revelado" . CodeProject . CodeProject . Consultado el 31 de agosto de 2008 .
- ^ a b c d Robert Kuster (20 de agosto de 2003). "Tres formas de inyectar su código en otro proceso" . CodeProject . CodeProject . Consultado el 31 de agosto de 2008 .
- ^ "Trabajar con el valor de registro AppInit_DLLs" . Ayuda y soporte técnico de Microsoft . Microsoft. 21 de noviembre de 2006 . Consultado el 31 de agosto de 2008 .
- ^ Raymond Chen (13 de diciembre de 2007). "AppInit_DLLs debería ser renombrado Deadlock_Or_Crash_Randomly_DLLs" . Lo viejo y nuevo . Microsoft . Consultado el 31 de agosto de 2008 .
- ^ "dllmain.c" . ReactOS . Fundación ReactOS. 8 de julio de 2008 . Consultado el 31 de agosto de 2008 .[ enlace muerto permanente ]
- ^ AppInit_DLLs en Windows 7 y Windows Server 2008 R2
- ^ "AppInit DLL y arranque seguro" . MSDN . Consultado el 29 de marzo de 2016 .
- ^ " ' AtomBombing' Microsoft Windows a través de inyección de código" . Lectura oscura . Consultado el 20 de abril de 2017 .
- ^ a b c d Trent Waddington. "InjectDLL" . Consultado el 31 de agosto de 2008 .
- ^ "Inyección Dll" . DreamInCode.net . MediaGroup1. 4 de mayo de 2006. Archivado desde el original el 2 de septiembre de 2008 . Consultado el 31 de agosto de 2008 .
- ^ Greg Jenkins (noviembre de 2007). "Marco de inyección de DLL" . Ring3 Circus . WordPress . Consultado el 31 de agosto de 2008 .
- ^ Drew Benton (17 de agosto de 2007). "Una solución de inyección de DLL más completa utilizando CreateRemoteThread" . CodeProject . CodeProject . Consultado el 1 de septiembre de 2008 .
- ^ "CreateProcess" . Platform SDK para Windows XP SP2 . Microsoft . Consultado el 31 de agosto de 2008 .
- ^ "INFORMACIÓN_PROCESO" . Platform SDK para Windows XP SP2 . Microsoft . Consultado el 31 de agosto de 2008 .
- ^ "Función GetWindowThreadProcessId" . Platform SDK para Windows XP SP2 . Microsoft . Consultado el 31 de agosto de 2008 .
- ^ "EnumProcesses" . Platform SDK para Windows XP SP2 . Microsoft . Consultado el 31 de agosto de 2008 .
- ^ "GetModuleBaseName" . Platform SDK para Windows XP SP2 . Microsoft . Consultado el 31 de agosto de 2008 .
- ^ "VirtualAllocEx" . Platform SDK para Windows XP SP2 . Microsoft . Consultado el 31 de agosto de 2008 .
- ^ "WriteProcessMemory" . Platform SDK para Windows XP SP2 . Microsoft . Consultado el 31 de agosto de 2008 .
- ^ "Outpost Bypassing Autoprotección a través de la inyección avanzada de DLL con la vulnerabilidad de robo de manijas" . Matousec . 1 de diciembre de 2006 . Consultado el 31 de agosto de 2008 .
- ^ "CreateRemoteThread" . Platform SDK para Windows XP SP2 . Microsoft . Consultado el 31 de agosto de 2008 .
- ^ "LoadLibrary" . Platform SDK para Windows XP SP2 . Microsoft . Consultado el 31 de agosto de 2008 .
- ^ a b "DllMain" . Platform SDK para Windows XP SP2 . Microsoft . Consultado el 31 de agosto de 2008 .
- ^ "Función SetWindowsHookEx" . Platform SDK para Windows XP SP2 . Microsoft . Consultado el 31 de agosto de 2008 .
- ^ "Valor de registro de AppInit_DLLs y Windows 95" . Ayuda y soporte técnico de Microsoft . Microsoft. 1 de marzo de 2005 . Consultado el 31 de agosto de 2008 .
- ^ "Inyección de Dll usando el método SetWindowsHookEx ()" . Reversión del juego . 3 de abril de 2008 . Consultado el 1 de septiembre de 2008 .
- ^ "Inyección de DLL SetThreadContext" . 16 de enero de 2007 . Consultado el 1 de septiembre de 2008 .
- ^ Ben Botto (6 de septiembre de 2008). "Inyector DLL" . Archivado desde el original el 7 de febrero de 2009 . Consultado el 1 de septiembre de 2008 .
- ^ "La carga insegura de la biblioteca podría permitir la ejecución remota de código" . Microsoft . 10 de junio de 2011 . Consultado el 20 de abril de 2016 .
- ^ "Carga segura de bibliotecas para evitar ataques de precarga de DLL" . Microsoft . 10 de junio de 2011 . Consultado el 8 de agosto de 2012 .
- ^ "Aviso de seguridad de Microsoft: la carga insegura de la biblioteca podría permitir la ejecución remota de código" . Microsoft . 10 de junio de 2011 . Consultado el 20 de abril de 2016 .
- ^ Nicolas Falliere (26 de septiembre de 2010). "Infección por Stuxnet de los proyectos del paso 7" . Symantec.
- ^ Linus Torvalds ; David Engel; Eric Youngdale; Peter MacDonald; Hongjiu Lu; Lars Wirzenius; Mitch D'Souza (14 de marzo de 1998). "ld.so/ld-linux.so - enlazador / cargador dinámico" . Páginas de manual de UNIX . Archivado desde el original el 6 de febrero de 2009 . Consultado el 31 de agosto de 2008 .
- ^ "Opciones de generación de código" . Usando la colección de compiladores GNU (GCC) . Fundación de Software Libre . Consultado el 31 de agosto de 2008 .
-fpic
Genere un código independiente de la posición (PIC) adecuado para su uso en una biblioteca compartida, si es compatible con la máquina de destino. sqq. - ^ "Opciones de enlace" . Usando la colección de compiladores GNU (GCC) . Fundación de Software Libre . Consultado el 31 de agosto de 2008 .
-shared
Produce un objeto compartido que luego se puede vincular con otros objetos para formar un ejecutable. sqq. - ^ "El truco LD_PRELOAD" . Peter Goldsborough . Consultado el 17 de mayo de 2017 .
- ^ Gregory Shpitalnik (12 de febrero de 2009). "Inyección de código en una aplicación Linux en ejecución" . Proyecto de código . Consultado el 18 de noviembre de 2010 .