Memoria y datos volátiles · Lección 3 de 4
Conexiones de red, identificadores e inyección de código
12 min de lectura
Una lista de procesos indica qué se estaba ejecutando. Esta lección responde a las siguientes preguntas: con qué se comunicaba cada proceso en la red, qué archivos, claves del registro y mutex mantenía abiertos, y si en su interior se ejecutaba código que ningún archivo del disco explica. Estas tres vistas permiten que el análisis de memoria detecte actividad que una imagen de disco no puede mostrar, como un implante sin archivos dentro de un proceso legítimo. Se utilizan nombres de complementos de Volatility 3 como ejemplos; la lección 5.2 abordó la ejecución de Volatility 3 y los complementos de procesos, por lo que no se repiten aquí.
Artefactos de red en Windows
Windows mantiene una estructura del kernel por cada extremo TCP, socket TCP en escucha y extremo UDP, asignada por el controlador TCP/IP (tcpip.sys) en la memoria del pool del kernel. Dos complementos las leen de formas distintas:
- windows.netscan busca estas estructuras en la memoria mediante sus firmas de pool (por ejemplo, la etiqueta
TcpEpara los extremos TCP). Como encuentra las estructuras por patrones en lugar de recorrer listas, también recupera conexiones que se cerraron y liberaron, pero que aún no se han sobrescrito. Sus columnas son Offset, Proto, LocalAddr, LocalPort, ForeignAddr, ForeignPort, State, PID, Owner y Created. - windows.netstat recorre las listas de extremos activos del propio controlador, como
netstat.exeen un sistema en ejecución. Solo muestra lo que estaba activo y depende de la información de símbolos detcpip.sys, por lo que puede fallar en algunas compilaciones.
Una entrada presente en netscan, pero ausente en netstat, es una conexión antigua y cerrada o una estructura desvinculada para ocultarla. Determine cuál de las dos es a partir del estado y la marca de tiempo. Proto es TCPv4, TCPv6, UDPv4 o UDPv6. UDP no está orientado a conexiones, por lo que las filas UDP no tienen estado y, por lo general, tampoco dirección remota. Created es la hora de creación del socket, mostrada en UTC. El escaneo también puede devolver fragmentos de memoria liberada con puertos o PID imposibles; ignore las filas que no tengan sentido.
| Estado | Significado | Qué sugiere |
|---|---|---|
| LISTENING | Socket en espera de conexiones entrantes | Un servicio o una puerta trasera que acepta conexiones en LocalPort |
| SYN_SENT | Intento de conexión saliente aún sin respuesta | Intentos periódicos de comunicación con un servidor inactivo o bloqueado |
| ESTABLISHED | Conexión abierta; los datos pueden circular en ambos sentidos | Comunicación activa en el momento de la captura |
| CLOSE_WAIT | El extremo remoto ha cerrado; la aplicación local aún no | El interlocutor cerró la sesión; el proceso aún mantiene el socket |
| TIME_WAIT | El extremo local cerró primero; el sistema conserva la tupla brevemente | Una conexión reciente y finalizada; a menudo no se muestra el propietario |
De una conexión a una línea de comandos
La columna PID vincula un socket con un proceso. Confirme el PID en windows.pslist o windows.pstree y compruebe que la hora de creación del proceso sea anterior a la hora Created del socket, porque los PID se reutilizan después de que un proceso termina. A continuación, ejecute windows.cmdline para ese PID: la línea de comandos suele indicar por qué el proceso se comunicaba con la red, o mostrar que no tiene una razón válida para hacerlo.
Sockets y archivos abiertos en Linux
En Linux, linux.sockstat enumera todos los sockets que mantiene cada proceso, con el PID, el descriptor de archivo, la familia (AF_INET, AF_INET6, AF_UNIX, AF_NETLINK), el protocolo, las direcciones y los puertos de origen y destino, y el estado TCP. Filtre por AF_INET y AF_INET6 para excluir los numerosos sockets de dominio UNIX y netlink. Volatility 3 no tiene un complemento linux.netstat; linux.sockstat cumple esa función para los sockets mantenidos por procesos en ejecución y, desde la versión 2.28.0, linux.sockscan también busca estructuras de sockets en la memoria, de forma similar a windows.netscan. linux.lsof enumera los descriptores de archivo abiertos de cada proceso: archivos regulares con sus rutas y sockets como socket:[inode]. Juntos responden a la pregunta «¿qué proceso tenía esta conexión y qué archivos tenía abiertos?».
Identificadores y archivos en caché
Un identificador es la referencia de un proceso a un objeto del kernel. windows.handles, que normalmente se ejecuta con --pid, enumera Type, GrantedAccess y Name de cada identificador. Los tipos útiles son File (archivos y dispositivos abiertos), Key (claves del registro), Mutant (un mutex), Process y Thread (identificadores de otros procesos y subprocesos, como los que necesita un inyector), Event y Section (memoria compartida). Muchas familias de malware crean un mutex con nombre para que solo se ejecute una copia, y ese nombre es un indicador publicado. Un identificador Key abierto muestra acceso a una clave, no que se haya escrito un valor.
windows.filescan busca estructuras FILE_OBJECT y enumera sus rutas, incluidos archivos que ya no están abiertos. windows.dumpfiles recupera el contenido en caché de un archivo desde su sección de datos (la caché de archivos), su sección de imagen (un ejecutable mapeado para su ejecución) o el mapa de caché compartida. El resultado suele estar incompleto: las páginas que no estaban residentes faltan o se rellenan con ceros. Un ejecutable recuperado de su sección de imagen tiene la distribución que tenía en memoria, por lo que su hash no coincidirá con el del archivo en disco. En Linux, linux.lsof proporciona la lista equivalente de archivos abiertos.
Inyección de código y árbol VAD
La inyección de código consiste en colocar código en otro proceso y ejecutarlo allí, de modo que herede el nombre, los privilegios y la confianza de ese proceso. Tres formas habituales:
- Inyección clásica mediante un subproceso remoto: abrir el proceso de destino, asignar memoria en él (
VirtualAllocEx), escribir código (WriteProcessMemory) e iniciarlo (CreateRemoteThread). - Vaciado de procesos: iniciar un ejecutable legítimo en estado suspendido, desmapear su imagen, escribir una imagen maliciosa en su lugar, redirigir la dirección de inicio del subproceso y reanudarlo.
- Carga reflectiva de DLL: una DLL se mapea y reubica a sí misma desde la memoria con su propio cargador, por lo que el cargador de Windows nunca la registra en las listas de módulos.
El kernel describe el espacio de direcciones de cada proceso mediante un árbol de descriptores de direcciones virtuales (VAD). Cada nodo VAD abarca un rango y registra si se trata de memoria privada o de un archivo mapeado (con el nombre del archivo), su etiqueta (VadS para las asignaciones privadas habituales) y la protección solicitada cuando se asignó el rango. Las imágenes ejecutables y las DLL se mapean desde archivos con PAGE_EXECUTE_WRITECOPY; los montículos y las pilas son privados y tienen PAGE_READWRITE. windows.vadinfo enumera todos los VAD de un proceso.
Detección de código inyectado con malfind
windows.malware.malfind señala regiones VAD cuya protección permite tanto escritura como ejecución, principalmente regiones privadas (sin respaldo en un archivo) PAGE_EXECUTE_READWRITE, además de, en las versiones actuales, regiones ejecutables que contienen páginas modificadas (sucias); omite las regiones cuyas páginas están vacías, por lo que informa de contenido confirmado. Para cada coincidencia, muestra un volcado hexadecimal y un desensamblado del inicio de la región. Examine los primeros bytes:
4D 5A("MZ") significa que hay un archivo PE en memoria privada, algo que el cargador de Windows nunca produce. Al desensamblarse, una cabecera genera instrucciones sin sentido comodec ebp; pop edx(32 bits) opop r10(64 bits).- Los bytes que se desensamblan en código plausible, como el prólogo de una función o una secuencia call/pop, sugieren la presencia de shellcode.
- Una cabecera puesta a cero oculta "MZ"; busque más adelante
PE\0\0o "This program cannot be run in DOS mode".
Hay dos limitaciones importantes. En primer lugar, el VAD registra la protección original; el código asignado como RW y cambiado posteriormente a RX con VirtualProtect no aparecerá como RWX. En segundo lugar, el software legítimo produce coincidencias: los compiladores justo a tiempo (JIT) del entorno de ejecución de .NET y de los motores de JavaScript escriben y ejecutan código en memoria privada, y algunos productos de seguridad inyectan su propio código. Confirme una coincidencia mediante un volcado (--dump) y un análisis con reglas YARA, ya sea con windows.vadyarascan sobre los VAD de los procesos (un PID o todos) o con yarascan sobre la memoria del kernel.
Indicadores de vaciado de procesos
El vaciado deja una discrepancia entre lo que el proceso declara ser y lo que está mapeado. La ruta de la imagen del PEB, mostrada por cmdline y dlllist, apunta a un ejecutable legítimo, pero el VAD situado en la base de la imagen no está respaldado por ese archivo. windows.malware.ldrmodules compara los VAD mapeados con las tres listas de módulos del PEB (InLoad, InInit, InMem); una imagen principal desvinculada, o una región base sin ruta mapeada, es sospechosa. El ejecutable normalmente muestra False en InInit, por lo que eso por sí solo no es un indicador. Una coincidencia de malfind en la base de la imagen completa el panorama.
Servicios, registro y comprobaciones de rootkits en Linux
windows.svcscan lee registros de servicios de la memoria de services.exe, incluidos el nombre, el estado, el tipo de inicio y la ruta del binario, y puede mostrar un servicio añadido para mantener la persistencia. windows.registry.hivelist enumera las secciones del registro cargadas y windows.registry.printkey lee una clave de la memoria, como una clave Run, incluidos los cambios que aún no se han volcado al disco. En Linux, linux.malware.malfind señala mapeos de memoria con permisos de escritura y ejecución o mapeos ejecutables anónimos; linux.lsmod enumera los módulos del kernel cargados, linux.malware.check_modules compara esa lista con sysfs para encontrar módulos ocultos y linux.malware.check_syscall informa de entradas de la tabla de llamadas al sistema que apuntan fuera del kernel. Desde 2025, Volatility 3 incluye malfind, ldrmodules y los complementos de comprobación de Linux bajo windows.malware. y linux.malware. (por ejemplo, windows.malware.malfind); las guías antiguas utilizan nombres cortos, como windows.malfind o linux.check_syscall, que son alias obsoletos cuya eliminación está prevista, por lo que debe utilizar los nombres completos.
Ejemplo resuelto: rundll32.exe sin argumentos
Se analiza una imagen de memoria de Windows. Columnas seleccionadas de netscan:
| Protocolo | Dirección local:puerto | Dirección remota:puerto | Estado | PID | Propietario | Creación |
|---|---|---|---|---|---|---|
| TCPv4 | 0.0.0.0:135 | 0.0.0.0:0 | LISTENING | 1012 | svchost.exe | 2026-03-14T08:01:44Z |
| TCPv4 | 192.0.2.15:49823 | 203.0.113.50:443 | ESTABLISHED | 7344 | rundll32.exe | 2026-03-14T14:22:09Z |
| TCPv4 | 192.0.2.15:49790 | 198.51.100.24:443 | CLOSE_WAIT | 5128 | msedge.exe | 2026-03-14T14:05:31Z |
rundll32.exe sirve para ejecutar una función exportada de una DLL, por lo que su línea de comandos normalmente especifica una (rundll32.exe file.dll,Export). windows.cmdline para el PID 7344 muestra únicamente C:\Windows\System32\rundll32.exe, sin argumentos. Ese patrón es típico de un proceso de sacrificio iniciado por un marco de posexplotación para alojar código inyectado. windows.malware.malfind --pid 7344:
| VPN inicial | VPN final | Etiqueta | Protección | CommitCharge | PrivateMemory | Primeros bytes |
|---|---|---|---|---|---|---|
| 0x1e0000 | 0x20afff | VadS | PAGE_EXECUTE_READWRITE | 43 | 1 | 4D 5A 90 00 |
Tamaño = Fin − Inicio + 1 = 0x20afff − 0x1e0000 + 1 = 0x2b000 = 176.128 bytes = 176.128 / 4.096 = 43 páginas, lo que coincide con CommitCharge 43, por lo que toda la región está confirmada. windows.handles --pid 7344 muestra un Mutant llamado qz7k2m_upd_0451, que un informe de amenazas identifica como propio de una familia conocida.
La conclusión prudente: la evidencia es compatible con una imagen PE inyectada en rundll32.exe con PID 7344, que mantenía una conexión establecida con 203.0.113.50:443 creada a las 2026-03-14T14:22:09Z. No muestra qué datos se enviaron ni cómo llegó el código. Siguientes pasos de recopilación: volcar la región con malfind --dump y registrar su SHA-256 (el hash de un PE con distribución de memoria no coincidirá con el de una muestra en disco); analizarla con YARA; comprobar el proceso padre en windows.pstree; buscar otros procesos que se comuniquen con 203.0.113.50; y revisar el disco en busca de persistencia y del mecanismo de entrega (claves Run, servicios, tareas programadas, Prefetch y la cronología del sistema de archivos del módulo 3).
Indicadores y sus falsos positivos
| Indicador | Complemento | Por qué es sospechoso | Falso positivo habitual |
|---|---|---|---|
Región RWX privada que comienza con MZ | windows.malware.malfind | PE no cargado por el cargador de Windows | Empaquetadores y software que se desempaqueta a sí mismo |
| Región RWX privada con bytes que parecen código | windows.malware.malfind | Posible shellcode | Compiladores JIT de .NET y JavaScript |
| Conexión saliente de un proceso que rara vez utiliza la red | windows.netscan | Binario del sistema con código inyectado o utilizado de forma abusiva | Una DLL legítima alojada por rundll32 |
| Socket LISTENING en un puerto inusual | windows.netscan, linux.sockstat | Puerta trasera que acepta conexiones | Herramientas de desarrollo, software entre pares |
| Nombre de mutex conocido | windows.handles | Marcador de infección específico de una familia | Nombres cortos y genéricos que coinciden |
| Base de la imagen sin respaldo en su archivo | windows.malware.ldrmodules, windows.vadinfo | Vaciado de procesos | InInit False es normal para la imagen principal |
| Entrada de llamada al sistema fuera del kernel | linux.malware.check_syscall | Intercepción de un rootkit | Módulos de seguridad o de seguimiento |
Enfoque del examen: Espere preguntas sobre qué complemento recupera conexiones cerradas (netscan, no netstat), qué significa un estado TCP, qué tipo de identificador es un mutex (Mutant) o por qué malfind señala una región y cuándo esa señal es un falso positivo. Prepárese para calcular el tamaño de una región a partir de Start y End VPN. Para Linux, prepárese para leer un PID, una dirección remota o la ruta de un archivo abierto en la salida de linux.sockstat y linux.lsof.
Puntos clave
- windows.netscan encuentra estructuras de extremos mediante escaneo e incluye conexiones cerradas; windows.netstat recorre únicamente las listas activas.
- Vincule un socket con su proceso mediante el PID, compare la hora de creación del proceso con Created y, después, lea la línea de comandos.
- windows.handles muestra archivos, claves y mutex abiertos; un nombre de mutex conocido es un indicador sólido, y los archivos volcados pueden estar incompletos.
- windows.malware.malfind señala regiones VAD privadas, confirmadas, ejecutables y con permisos de escritura; "MZ" al inicio es una señal de alerta y los compiladores JIT son el falso positivo clásico.
- El vaciado se manifiesta como una ruta de imagen que no coincide con el VAD en la base de la imagen, una imagen principal desvinculada en ldrmodules y una coincidencia de malfind en esa base.
- En Linux, utilice linux.sockstat para las conexiones, linux.lsof para los archivos abiertos y linux.lsmod, linux.malware.check_modules y linux.malware.check_syscall para las comprobaciones de rootkits.