
Herramienta de análisis forense de memoria y caza de amenazas para Windows que escanea la memoria de procesos en vivo en busca de patrones maliciosos, técnicas de inyección y ensamblados .NET cargados de forma reflectiva, utilizando un modelo de confianza multicapa para reducir los falsos positivos.

versión : 0.9 (versión estable)
Aether es una herramienta de análisis forense de memoria y caza de amenazas para Windows que escanea la memoria de procesos en vivo en busca de patrones maliciosos, detecta técnicas de inyección, firmas de implantes y ensamblados .NET cargados de forma reflectiva. Funciona con un modelo de confianza multicapa que reduce drásticamente la tasa de falsos positivos y caza comportamientos maliciosos. Aether tiene buenas capacidades para detectar técnicas de Hollowing, APC y secuestro de hilos. Los analistas de seguridad pueden utilizarla para escanear, cazar y capturar instantáneas (snapshots) de regiones sospechosas para su análisis sin conexión.
Documentación: https://0xsp.com/docs/aether-getting-started/
Artículos de investigación:
Explicaciones rápidas de las características principales de Aether; puedes leer el artículo técnico completo para obtener más información:
"msxsl:script" se convierte en 6D 00 73 00 78 00 ...)rules/ sin recompilarMEM_PRIVATE: marca ensamblados .NET cargados de forma reflectiva (metadatos MZ + PE + BSJB)Aether aplica cinco filtros sobre la señal bruta del conjunto de trabajo (working set), de modo que un hallazgo requiere múltiples indicadores coincidentes antes de notificarse con el filtrado de FP:
Otras comprobaciones estructurales:
MEM_IMAGE que no están en la lista de módulos del PEB (DLL hollowing / module stomping)K32QueryWorkingSetEx, agrupado con una llamada al sistema por región en lugar de una por página de 4 KB (≈ 50-100× más rápido que el bucle ingenuo)MEM_PRIVATE + PAGE_EXECUTE_* (produce resultados FP) (shellcode, JIT spray, asignaciones de stubs de código dinámicos)E9 ?? ?? ?? ?? — JMP rel32FF 25 ?? ?? ?? ?? — JMP [rip+disp32]68 ?? ?? ?? ?? C3 — PUSH imm32 ; RET48 B8 ?? ?? ?? ?? ?? ?? ?? ?? FF E0 — MOV RAX, imm64 ; JMP RAXAether comprueba los hilos con una clasificación más estricta y una correlación cruzada con los hallazgos L1–L5. Para cada hilo creado en el proceso objetivo, Aether lee su Win32StartAddress mediante NtQueryInformationThread y, cuando los permisos lo permiten, también el Rip / Eip en vivo mediante GetThreadContext / Wow64GetThreadContext. Cada dirección se clasifica según la siguiente tabla; para más detalles, lee el artículo del blog:
Lo que hace que esto sea más sólido que la comprobación básica de "la dirección de inicio está en algún módulo":
VirtualQueryEx: cada dirección se consulta por Type / Protect / AllocationBase en una sola llamada O(1) en lugar de un escaneo lineal sobre la lista de módulosTSAV_MODIFIED_HOSTWin32StartAddress es escribible desde el proceso mediante NtSetInformationThread y es el campo suplantable; el Rip en vivo de un hilo suspendido es el que un cargador no puede reescribir fácilmente. Comparamos ambos y marcamos cualquier discrepancia que resuelva a una región sospechosaWow64GetThreadContext y lee Eip para hilos de 32 bits dentro de un proceso de 64 bitsLa resolución dinámica de API es una técnica que el malware utiliza con frecuencia. El mecanismo de detección de Aether identifica este comportamiento escaneando el heap en busca de direcciones y punteros de módulos válidos, y correlacionando los resultados con los criterios de filtrado descritos a continuación:
Cada filtro elimina una clase específica de FP observada en telemetría real:
Por ahora, Aether admite la detección de patrones XOR a nivel de stub y adopta el algoritmo de entropía de Shannon para comprobar la aleatoriedad de los valores de bytes en una región de memoria; marca todo lo que supera un umbral. Para abordar la alta cantidad de FP, Aether utiliza múltiples indicadores.
GetExtendedTcpTable para un PID objetivoMODIFIED_CODE_* incluye private_pages y region_pages para que el triaje tenga los números realesAether.exe --scan --pid <PID> [OPTIONS]
Aether.exe --scan --lookup "ProcessName.exe"
Aether.exe --hunt <PID> SLEEP_MS PERIOD
Aether.exe --scan-all [OPTIONS]
git clone https://github.com/0xsp-SRD/aether
cd aether
# Debug build (safety checks enabled)
zig build
# Release build (smaller, faster binary)
zig build -Doptimize=ReleaseSafe
# or
zig build -Doptimize=ReleaseFast
El ejecutable compilado se encuentra en zig-out/bin/Aether.exe.
Copia zig-out/bin/Aether.exe y el directorio rules/ a la máquina Windows de destino si quieres realizar un escaneo de firmas adicional. Si el proceso objetivo requiere privilegios administrativos, debes ejecutar Aether.exe con privilegios de Administrador.
Win32StartAddress en un hilo ya en ejecución solo puede detectarse si el hilo está detenido en una espera cuando se sondea (misma limitación que Moneta)Aether Community está licenciado bajo GNU GPL v3.0. Las licencias comerciales solo están disponibles a través del autor para uso propietario o comercial.
| Capa | Filtro | Propósito |
|---|
| L1 | Estructural | Solo se consideran subregiones IMAGE ejecutables (elimina el ruido COW de .data / .rdata) |
| L2 | Cuantitativo | Clasifica según el recuento de private_pages y private_ratio (bajo / medio / alto) |
| L3 | Corroboración | Promueve solo si una señal independiente coincide en la misma base de asignación: coincidencia de firma, missing_peb_entry, private_rwx, prólogo de hook o diff en disco |
| L4 | Consciente de CLR | Supresión por módulo para objetivos ngen / R2R / JIT por niveles (*.ni.dll, mscor*, clr*, coreclr, system.private.corelib*) en lugar de omitirlo todo cuando el CLR está cargado |
| L5 | Diff en disco | Asigna el archivo del módulo con CreateFileMappingW(SEC_IMAGE_NO_EXECUTE); compara los primeros 16 bytes de cada página ejecutable privada con la misma RVA en disco. Cualquier divergencia es un IOC de modificación real |
49 BB ?? ?? ?? ?? ?? ?? ?? ?? 41 FF E3 — estilo Detours MOV R11, imm64 ; JMP R11Cor_Private_IPCBlock_v4_<PID> y el v2 Cor_Private_IPCBlock_<PID> (.NET 2/3 heredado / mscorwks), de modo que los grupos de aplicaciones ruidosos que ejecutan runtimes antiguos no se clasifiquen erróneamente| Veredicto | Severidad | Condición |
|---|
TSAV_SHELLCODE_PRIVATE | CRÍTICA | La dirección se encuentra en una región MEM_PRIVATE + PAGE_EXECUTE_* — shellcode clásico de CreateRemoteThread |
TSAV_SUSPENDED_RIP | CRÍTICA | El Rip del hilo suspendido no coincide con Win32StartAddress y resuelve a una región sospechosa: detecta la suplantación de Win32StartAddress (trucos EarlyBird / APC) y los secuestros de SetThreadContext |
TSAV_HOLLOWED_HOST | ALTA | Dirección dentro de una asignación MEM_IMAGE que no está en la lista de módulos del PEB (DLL hollowing / module stomping) |
TSAV_MODIFIED_HOST | ALTA | Dirección dentro de una asignación MEM_IMAGE que el pipeline L1–L5 ya marcó como MODIFIED_CODE_*, MISSING_PEB, PRIVATE_RWX, DISK_MEM_DIFF o HOOK_PROLOGUE |
TSAV_STAGED_PRIVATE_RW | ALTA | MEM_PRIVATE + PAGE_READWRITE — preparación (staging) de shellcode previa a VirtualProtect |
TSAV_MAPPED_NONPE | MEDIA | MEM_MAPPED (sección respaldada por el archivo de paginación) sin cabecera PE — cargador reflectivo sRDI / pagefile |
TSAV_SPOOF_TRAMPOLINE | MEDIA | La dirección coincide con un trampolín en lista de denegados (LoadLibraryA/W/ExA/W, WinExec, CreateProcessA/W, VirtualAlloc[Ex], RtlExitUserThread, RtlExitUserProcess, NtTerminateProcess, ShellExecuteA/W) |
QUERY_INFORMATION | GET_CONTEXTQUERY_INFORMATIONQUERY_LIMITED_INFORMATION| Filtro | Regla | Clase de FP que elimina |
|---|
| F1 | count >= 5 | datos aleatorios con forma de puntero, NULL, HMODULES |
| F2 | rechaza series que apuntan solo al EXE anfitrión | vtables C++ de clase aplicación |
| F3 | distinct_modules >= 2 | vtables de frameworks de una sola DLL (Qt, MFC, wxWidgets) |
| F4 | capability_modules >= 2 | vtables de navegador / CRT que tocan una sola DLL del sistema operativo (p. ej. iertutil + ucrtbase + shlwapi) |
| F5 (L10) | >= 80% de los punteros comprobables caen en RVAs exportadas | tablas de despacho Winsock LSP, matrices de callbacks de plugins, vtables que apuntan a métodos internos (no exportados) |
| Indicador | Descripción |
|---|
--pid, -p <PID> | ID del proceso objetivo a escanear |
--lookup, -l <name> | Encuentra todos los PID que coinciden con un nombre de proceso |
--json, -j | Muestra los resultados como JSON (para integración con SIEM) |
--verbose, -v | Muestra los detalles del escaneo por región |
--scan-all, -a | Escanea todos los procesos |
--hunt, -b <PID> [ms] [hits] | Monitoriza conexiones: consulta cada ms (por defecto 2000), marca endpoints con ≥ hits ocurrencias |
--networking | Modo de monitorización de red |
--rules, -r <dir> | Directorio de reglas (por defecto: rules/) |
--config, -c <file> | Archivo de reglas único (formato heredado) |
--dump, `` | Vuelca una región de memoria específica con tamaño personalizado |
--read, `` | Lee el contenido de la región de memoria en vivo en la terminal |
--help, -h | Muestra la ayuda |