La inyección de procesos es una de las técnicas más importantes en ciberseguridad. Esta técnica consiste en introducir código en el espacio de direcciones de otro proceso que ya se está ejecutando y ejecutar el código en ese espacio. Se trata de un verdadero desastre desde el punto de vista de la seguridad, ya que permite que el código se ejecute con los permisos del proceso de destino, lo que puede eludir los controles de seguridad utilizando la escalada de privilegios existente en el proceso de destino, los mecanismos de detección, etc.
La inyección de procesos es un vector de amenazas que ha dado lugar a muchas formas de malware que infestan Internet y amenazas persistentes avanzadas (APT). Aunque se trata de una técnica válida en un entorno de desarrollo de software para depurar o ampliar una aplicación, los actores maliciosos la utilizan a menudo para ejecutar código sin autorización, evadir la persistencia y permanecer sin ser detectados.
Este blog analiza los principios de la inyección de procesos, sus mecanismos básicos, las técnicas comunes, los métodos de detección y cómo prevenirla. También exploraremos algunos fundamentos, como las operaciones de memoria, las técnicas de inyección, los métodos de detección y ejemplos prácticos de ataques.
¿Qué es la inyección de procesos?
La inyección de procesos permite inyectar código en el espacio de memoria de otro proceso en curso. En esta técnica, el atacante obliga al proceso objetivo a ejecutar código arbitrario escribiendo su propio código en el espacio de direcciones de ese proceso. El código inyectado se ejecuta en el contexto y con los derechos del proceso vulnerable, por lo que hereda todos sus derechos de acceso y el nivel de confianza en el sistema.
La inyección de procesos consta de los siguientes componentes técnicos fundamentales: adquisición del identificador del proceso, asignación de memoria en el proceso objetivo, operaciones de escritura de código y mecanismos de activación de la ejecución. Utilizan funciones de la API de Windows como OpenProcess(), VirtualAllocEx(), WriteProcessMemory() y CreateRemoteThread() para ejecutar el proceso de inyección.
¿Por qué es peligrosa la inyección de procesos?
Hay varios aspectos técnicos que hacen que este tipo de ataque sea relativamente peligroso. El código ejecutado desde el subproceso inyectado tiene los mismos privilegios que el proceso de destino, lo que se traduce en un acceso elevado al sistema. Este método elude cualquier análisis de seguridad basado en archivos, ya que el código inseguro solo existe en la memoria.
También tiene un grave efecto en la estabilidad y la seguridad de los sistemas. Las operaciones de inyección pueden bloquearse por los procesos de destino e introducir inestabilidad en todo el sistema. Lo consiguen terminando los procesos de los productos de seguridad, robando datos de aplicaciones protegidas y estableciendo un acceso persistente al sistema que elude las técnicas de limpieza habituales.
Fundamentos de la memoria de procesos
La base técnica de las técnicas de inyección de procesos es la comprensión de las estructuras y operaciones de la memoria de los procesos. Existen características internas del modelo de gestión de memoria del sistema operativo Windows que permiten y también restringen las interacciones y el acceso a la memoria entre procesos. Estas alteran instantáneamente el funcionamiento de la inyección de procesos y la forma en que los defensores pueden detectarla y protegerse contra ella.
Memoria virtual y espacio de direcciones de procesos
Cada proceso de Windows tiene su propio espacio de direcciones virtuales, aislado de otros procesos que se ejecutan en el mismo sistema. El rango de este espacio de direcciones virtuales es de 0 a 0x7FFFFFFF para los procesos de 32 bits y de 0 a 0x7FFFFFFFFFF para los procesos de 64 bits. La asignación de direcciones virtuales a ubicaciones de memoria física se realiza con la ayuda de la técnica de paginación del Administrador de memoria de Windows.
El proceso tiene varias regiones en su espacio de direcciones, como el código ejecutable del proceso, las DLL cargadas, las asignaciones de montón y el espacio de pila. Estas regiones tienen funciones y tipos de datos específicos. Windows tiene tablas de páginas que describen dónde se encuentran las páginas de los marcos de memoria y si están en el espacio de direcciones virtuales.
Permisos y protección de la memoria
Existen permisos de acceso para las regiones de memoria, que describen cómo deben interactuar los procesos con ellas. Estos permisos incluyen:
- PAGE_EXECUTE: La memoria se puede ejecutar como código
- PAGE_READ: La memoria se puede leer
- PAGE_WRITE: Se puede escribir en la memoria
- PAGE_EXECUTE_READ: La memoria se puede ejecutar y leer
- PAGE_EXECUTE_READWRITE: La memoria se puede ejecutar, leer y escribir
Estos permisos son aplicados por el Administrador de memoria de Windows a nivel de página. Si una aplicación (o proceso) intenta acceder a la memoria de una forma no permitida, el sistema genera una violación de acceso.
API críticas de Windows para operaciones de memoria
Windows tiene algunas API importantes para la manipulación de la memoria. Estas API son los componentes básicos de la inyección de procesos. Las versiones "Ex" de estas funciones son para procesos externos, mientras que las sucesoras normales son para el espacio de memoria del proceso que realiza la llamada. Conocer estas API permite detectar posibles actividades de inyección y realizar un seguimiento.
- VirtualAlloc/VirtualAllocEx: Reserva y compromete memoria en un proceso
- VirtualProtect/VirtualProtectEx: Cambia los permisos de la región de memoria
- ReadProcessMemory: Lee datos del espacio de memoria de otro proceso
- WriteProcessMemory: Escribe datos en el espacio de memoria de otro proceso
- VirtualFree/VirtualFreeEx: Libera regiones de memoria asignadas
Tipos de técnicas de inyección de procesos
La inyección de procesos comprende una serie de técnicas diferentes que utilizan algún tipo de ejecución de código para los procesos de destino. Esta diferencia en las llamadas a la API de Windows y la manipulación de la memoria da lugar a patrones de funcionamiento y firmas de detección únicos para cada técnica.
El análisis de estas técnicas puede ser de gran ayuda para los equipos de seguridad a la hora de identificar y responder a métodos de inyección específicos.
1. Inyección de DLL
La inyección de DLL es el proceso de forzar a un proceso a cargar archivos DLL maliciosos. Utiliza un conjunto de funciones API: OpenProcess(), VirtualAllocEx() y CreateRemoteThread(). Comienza reservando memoria dentro del proceso de destino para almacenar la ruta de la DLL. A continuación, inicia un subproceso remoto que llama a LoadLibrary() con la ruta como parámetro para indicar al proceso de destino que cargue la DLL maliciosa.
Una DLL inyectada tiene acceso completo a las funciones/procesos del proceso de destino con direcciones de memoria de todo el espacio de memoria del proceso de destino y todos los demás módulos que el destino ha cargado en la memoria.
2. Inyección de código
La inyección de código es una forma de ataque que inyecta código malicioso en el espacio de memoria de un proceso, y el código se ejecuta en él. Esto simplemente escribe un código en la dirección del espacio de memoria de un proceso. Se trata de una técnica de varios pasos que incluye obtener un control sobre el proceso, utilizar VirtualAllocEx() para asignar memoria, WriteProcessMemory() para escribir el código y, finalmente, CreateRemoteThread() para ejecutarlo.
El código que se ejecuta tiene los permisos del proceso de destino en el que se está ejecutando, y se heredarán todos los privilegios de seguridad y derechos de acceso.
3. Secuestro de la ejecución de subprocesos
El secuestro de la ejecución de subprocesos suspende un subproceso en el proceso de destino, cambia su contexto de ejecución para que apunte al código del atacante y continúa la ejecución. En esta técnica, el atacante utiliza las API SuspendThread(), GetThreadContext(), SetThreadContext() y ResumeThread().
Dado que utiliza un hilo legítimo, es más difícil detectarlo, ya que el hilo secuestrado se ejecuta con sus privilegios existentes para ejecutar el código malicioso.
4. Inyección APC (llamada de procedimiento asíncrono)
La inyección APC pone en cola el código malicioso para que se ejecute cuando un subproceso entra en estado de alerta. Este método pone en cola el código en un subproceso utilizando QueueUserAPC(). El código inyectado en el subproceso se ejecuta cuando procesa su cola APC, lo que suele ocurrir durante determinadas llamadas al sistema u operaciones de espera. Este método es muy adecuado para subprocesos que visitan repetidamente estados mutables.
5. Inyección de DLL reflexiva
El método de inyección de DLL reflexiva carga una DLL con la ayuda de un cargador de Windows y no escribe un artefacto del sistema de archivos. Se trata de una DLL personalizada con instrucciones sobre cómo asignarla y direccionarla en la memoria. Este truco consiste en inyectar el código del cargador y la DLL en la memoria del proceso de destino y ejecutar el cargador para preparar la DLL. Evita la detección por parte de los mecanismos normales de carga de DLL y la supervisión.
6. Proceso de vaciado
El proceso de vaciado es una técnica de inyección sigilosa en la que los atacantes crean un proceso legítimo en estado suspendido (utilizando CreateProcess con CREATE_SUSPENDED), desasignan su espacio de memoria original (a través de NtUnmapViewOfSection/ZwUnmapViewOfSection), asignan nueva memoria (VirtualAllocEx), escriben código malicioso (WriteProcessMemory), corrigen el encabezado PE y las reubicaciones, actualizan el bloque de entorno del proceso (PEB) y, finalmente, redirigen el punto de entrada (SetThreadContext) antes de reanudar la ejecución (ResumeThread). Esto permite que el código malicioso se ejecute con la identidad y los privilegios de un proceso legítimo.
¿Cómo funciona la inyección de procesos?
Las inyecciones de procesos siguen una serie de pasos para intentar ejecutar código en un proceso de destino. Independientemente del método de inyección, la implementación técnica sigue ciertos pasos que manipulan la memoria del proceso y cambian la forma en que se ejecuta el flujo del proceso.
El primero es la identificación del proceso de destino y las operaciones de adquisición de acceso. El proceso malicioso utiliza OpenProcess() para obtener un control sobre el proceso de destino. Los derechos de acceso necesarios para este control son PROCESS_CREATE_THREAD, PROCESS_QUERY_INFORMATION, PROCESS_VM_OPERATION, PROCESS_VM_WRITE y PROCESS_VM_READ.
El segundo paso crucial es la asignación de memoria en el proceso objetivo. VirtualAllocEx() asigna espacio de memoria en el espacio de direcciones del proceso objetivo reservando y comprometiendo páginas de la memoria virtual.
El tercer paso es copiar el código shell al área de memoria asignada. WriteProcessMemory() copia los bytes de código del búfer de origen a la región de memoria del proceso de destino. Esta operación debe tener en cuenta los requisitos de alineación y tamaño.
El último paso de la activación de la ejecución representa los componentes centrales finales. Cada técnica emplea un mecanismo u otro:
- CreateRemoteThread() crea un nuevo subproceso para ejecutar el código inyectado
- QueueUserAPC() pone en cola la ejecución del código en un subproceso existente
- SetThreadContext() modifica el flujo de ejecución del subproceso existente
- Modificación directa de punteros de función o ganchos
Una vez que la ejecución está en marcha, el código inyectado se ejecuta dentro del contexto del proceso de destino, teniendo acceso a los recursos y al token de seguridad del proceso de destino. Este código puede entonces hacer lo que se diseñó para hacer, ejecutándose con los privilegios y el nivel de confianza del proceso de destino.
¿Cómo detectar los ataques de inyección de procesos?
La inyección de procesos es difícil de detectar porque implica varios componentes y comportamientos del sistema. Para identificar la actividad de inyección, los sistemas de seguridad deben supervisar los movimientos de la memoria, las llamadas a la API y todo el comportamiento del proceso.
Estos métodos de detección, en combinación, forman una estrategia de detección global.
Análisis de patrones de memoria
El análisis de la memoria se centra en la búsqueda de patrones populares en las regiones de memoria de los procesos. Esto se debe a que estas regiones de la memoria del proceso son escaneadas por herramientas de seguridad para comprobar la configuración de permisos de la memoria del proceso y el contenido esperado. Esto incluye la detección de regiones ejecutables anómalas y páginas que no se ajustan a sus firmas de contenido típicas dentro de los procesos, entre otras cosas.
Los escáneres de memoria buscan desviaciones de los binarios originales del proceso, ya sea supervisando los cambios en las estructuras de memoria del proceso normalmente estáticas o buscando segmentos de código dinámicos.
Supervisión de llamadas a la API
Las secuencias sospechosas de llamadas de manipulación de la memoria se detectan mediante la supervisión de la API de Windows. Las herramientas de seguridad supervisan OpenProcess() para el acceso a los procesos, VirtualAllocEx() para la asignación de memoria y WriteProcessMemory() para las escrituras en memoria. Si se crea o manipula un subproceso, por ejemplo, CreateRemoteThread(), esto será una clara señal de inyección.
También deben supervisarse los cambios en el estado de los procesos y subprocesos a través de API como SuspendThread() y SetThreadContext(), ya que suelen encontrarse en cadenas de inyección.
Indicadores de comportamiento
La supervisión del comportamiento de los procesos se realiza para identificar patrones de actividad inesperados que sugieran estos intentos de inyección. Los sistemas de detección de intrusiones vigilan los subprocesos en un proceso en ejecución relativamente estable y los cambios en el mapa de memoria del proceso para realizar un seguimiento de dichos procesos.
Estos comportamientos, junto con la modificación de las tablas de direcciones de importación y las operaciones de memoria entre procesos, son indicadores relevantes para la detección.
Herramientas de detección
La detección de la inyección de procesos requiere algunas herramientas de seguridad con capacidades de supervisión profunda. El análisis en tiempo real se realiza mediante supervisores de procesos que supervisan las llamadas a la API y las acciones del sistema, mientras que las herramientas de análisis de memoria realizan un análisis profundo de los espacios de memoria del proceso. Los analizadores de registros de eventos permiten a los equipos registrar el historial de eventos de seguridad dentro del sistema para que puedan obtener una perspectiva del pasado.
Las soluciones de detección y respuesta empresarial (EDR), como SentinelOne combina varias formas de supervisión con capacidades analíticas. Existen herramientas de administración del sistema, como el monitor de procesos y el explorador de procesos, que muestran los procesos en detalle, así como la asignación de memoria por proceso.
¿Cómo prevenir los ataques de inyección de procesos?
La prevención de la inyección de procesos no puede proporcionarse mediante un único control de seguridad, sino que implica controles a nivel del sistema, los procesos y el código. Estas medidas de mitigación se centran en limitar las capacidades de inyección de procesos, así como en dificultar la inyección en los procesos que podrían ser objeto de ataques.
Prevención a nivel del sistema
Las medidas preventivas a nivel del sistema comienzan con la gestión correcta del acceso y los privilegios. Los sistemas deben tener derechos de creación y manipulación de procesos configurados para restringir a los usuarios no administrativos, de modo que solo puedan abrir manejadores a procesos sensibles en los sistemas. Estas restricciones se aplican mediante el control de cuentas de usuario (UAC) y las políticas de AppLocker para gestionar qué procesos se pueden ejecutar y con qué nivel de privilegios.
Firma de código
Otra capa importante de prevención es la aplicación de la firma de código. Los módulos deben cargarse con sus firmas digitales verificadas, y los códigos firmados de forma inadecuada o sin firmar deben ser rechazados por los sistemas. Las políticas de Windows Defender Application Control (WDAC) aplican los requisitos de integridad del código y desactivan la carga de DLL y ejecutables sin firmar.
Protección de la memoria
Los mecanismos de protección de la memoria son una parte importante de la defensa. La prevención de ejecución de datos (DEP) protege contra la ejecución de código desde páginas de datos, mientras que la aleatorización del diseño del espacio de direcciones (ASLR) dificulta el acceso a una memoria específica.
Las mitigaciones de procesos protegidos medianas incluyen Control Flow Guard (CFG), que comprueba los objetivos en busca de llamadas indirectas, y Protected Process Light (PPL), que limita la capacidad de los procesos para abrir los existentes según los niveles de firma de los miembros.
Fortalecimiento de aplicaciones
Incluso para el endurecimiento de aplicaciones, el equipo de seguridad debe seguir prácticas de codificación seguras y opciones de compilador. Los desarrolladores deben configurar características de seguridad, como /DYNAMICBASE y /NXCOMPAT, implementar el manejo de excepciones y validar las operaciones de memoria dentro del proceso de depuración de la aplicación.
Ciberseguridad basada en IA
Mejore su postura de seguridad con detección en tiempo real, respuesta a velocidad de máquina y visibilidad total de todo su entorno digital.
DemostraciónConclusión
La inyección de procesos inyecta código malicioso en espacios de memoria junto con otros procesos en curso. El atacante obliga a los procesos objetivo a ejecutar código arbitrario y, además, escribe su propio código en los espacios de direcciones. La razón por la que es tan peligroso es que puede evadir las técnicas tradicionales de detección de amenazas. Es necesario utilizar soluciones de seguridad avanzadas y estrategias de prevención para detectarla.
Entre ellas se incluyen la protección de la memoria, los controles de comportamiento, los controles de acceso y otras medidas. Comprender el funcionamiento de las técnicas de inyección de procesos permite a las organizaciones reforzar sus sistemas de forma adecuada y desplegar controles de seguridad de manera más eficaz.
"Preguntas frecuentes sobre la inyección de procesos
La inyección de procesos es un ataque en el que el atacante copia y ejecuta un código en la memoria de un proceso. Esto le da al actor malicioso la capacidad de ejecutar su propio código en el proceso de destino, lo que le permite evadir las medidas de seguridad.
La inyección de procesos es una técnica que se utiliza principalmente para ocultar la actividad y la persistencia, así como para ejecutar código con privilegios más elevados. Si la DLL de Windows se inyecta en otro proceso a través de procesos normales, el código ejecutado realizará operaciones con el mismo nivel de confianza que el proceso de destino y tendrá los mismos derechos de acceso, lo que dificulta que las herramientas de seguridad detecten comportamientos maliciosos.
La detección de la inyección de procesos requiere la supervisión de la memoria, la API y los comportamientos de los procesos. Los analizadores de programas estáticos marcan estos intentos de inyección buscando patrones como asignaciones de memoria anómalas, creaciones de subprocesos y secuencias de API de manipulación de procesos anormales.
La inyección de procesos se utiliza principalmente en el malware, pero en algunos casos esta técnica puede utilizarse de forma legítima, por ejemplo, para la depuración, el análisis de malware, las técnicas de supervisión y para ampliar la funcionalidad de una aplicación.
En las campañas de estilo APT (amenaza persistente avanzada), la inyección de procesos desempeña un papel fundamental para lograr la persistencia y evitar la detección. Los actores de APT utilizan técnicas avanzadas de inyección para obtener acceso permanente a los sistemas infectados y garantizar que nunca serán descubiertos durante una operación prolongada.
