
Strumento di memory forensics e threat hunting per Windows che analizza la memoria dei processi in esecuzione alla ricerca di pattern dannosi, tecniche di injection e assembly .NET caricati in modo riflessivo, utilizzando un modello di confidenza a più livelli per ridurre i falsi positivi.

versione : 0.9 (versione stabile)
Aether è uno strumento di memory forensics e threat hunting per Windows che scansiona la memoria dei processi in esecuzione alla ricerca di pattern dannosi, rileva tecniche di injection, firme di implant e assembly .NET caricati in modo riflesso. Funziona con un modello di confidenza multistrato che riduce drasticamente il tasso di falsi positivi e dà la caccia a comportamenti dannosi. Aether ha buone capacità nel rilevare tecniche di Hollowing, APC e thread hijacking. Gli analisti di sicurezza possono usarlo per scansionare, cacciare e creare snapshot di regioni sospette per l'analisi offline.
Docs: https://0xsp.com/docs/aether-getting-started/
Articoli di ricerca:
Brevi spiegazioni delle funzionalità principali di Aether; puoi leggere il post tecnico completo per maggiori approfondimenti:
"msxsl:script" diventa 6D 00 73 00 78 00 ...)rules/ senza ricompilareMEM_PRIVATE — segnala assembly .NET caricati in modo riflesso (metadati MZ + PE + BSJB)Aether applica cinque filtri sopra il segnale grezzo del working set, così un riscontro richiede più indicatori concordanti prima di essere segnalato con il filtraggio dei falsi positivi:
Altri controlli strutturali:
MEM_IMAGE che non sono nella lista dei moduli del PEB (DLL hollowing / module stomping)K32QueryWorkingSetEx, in batch con una sola syscall per regione invece di una per pagina da 4 KB (≈ 50-100× più veloce del loop semplice)MEM_PRIVATE + PAGE_EXECUTE_* (produce risultati FP) (shellcode, JIT spray, allocazioni di stub di codice dinamici)E9 ?? ?? ?? ?? — JMP rel32FF 25 ?? ?? ?? ?? — JMP [rip+disp32]68 ?? ?? ?? ?? C3 — PUSH imm32 ; RET48 B8 ?? ?? ?? ?? ?? ?? ?? ?? FF E0 — MOV RAX, imm64 ; JMP RAXAether controlla i thread con una classificazione più rigorosa e una correlazione incrociata con i risultati L1–L5. Per ogni thread creato nel processo target, Aether legge il suo Win32StartAddress tramite NtQueryInformationThread e, quando i permessi lo consentono, anche il Rip / Eip live tramite GetThreadContext / Wow64GetThreadContext. Ogni indirizzo viene poi classificato come nella tabella seguente; per maggiori dettagli leggi il blog post:
Cosa rende questo più forte del semplice controllo "l'indirizzo di inizio è in un modulo":
VirtualQueryEx — ogni indirizzo viene interrogato per Type / Protect / AllocationBase in una singola chiamata O(1) invece di una scansione lineare dell'elenco dei moduliTSAV_MODIFIED_HOSTWin32StartAddress è scrivibile dal processo tramite NtSetInformationThread ed è il campo spoofabile; il Rip live di un thread sospeso è quello che un loader non può riscrivere facilmente. Confrontiamo i due e segnaliamo qualsiasi discordanza che risolva in una regione sospettaWow64GetThreadContext e legge Eip per i thread a 32 bit all'interno di un processo a 64 bitLa risoluzione runtime delle API è una tecnica usata frequentemente dal malware. Il meccanismo di rilevamento di Aether identifica questo comportamento scansionando l'heap alla ricerca di indirizzi e puntatori validi di moduli e correlando i risultati con i criteri di filtraggio descritti di seguito:
Ogni filtro elimina una specifica classe di falsi positivi osservata nella telemetria reale:
Aether supporta al momento il rilevamento di pattern XOR a livello di stub e adotta l'algoritmo dell'entropia di Shannon per verificare la casualità dei valori dei byte nelle regioni di memoria; segnala tutto ciò che supera una soglia. Per gestire l'elevato numero di falsi positivi, Aether utilizza più indicatori.
GetExtendedTcpTable per un PID targetMODIFIED_CODE_* include private_pages e region_pages, così il triage ha i numeri realiAether.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
L'eseguibile compilato si trova in zig-out/bin/Aether.exe.
Copia zig-out/bin/Aether.exe e la directory rules/ sulla macchina Windows target se vuoi eseguire ulteriori scansioni di firme. Se il processo target richiede privilegi amministrativi, devi eseguire Aether.exe con privilegi di amministratore.
Win32StartAddress su un thread già in esecuzione può essere rilevata solo se il thread si trova in uno stato di attesa quando viene sondato (stesso vincolo di Moneta)Aether Community è concesso in licenza sotto GNU GPL v3.0. Licenze commerciali disponibili solo dall'autore per uso proprietario o commerciale.
| Livello | Filtro | Scopo |
|---|
| L1 | Strutturale | Vengono considerate solo le sotto-regioni IMAGE eseguibili (elimina il rumore COW di .data / .rdata) |
| L2 | Quantitativo | Classifica in base al conteggio di private_pages e al private_ratio (basso / medio / alto) |
| L3 | Corroborazione | Promuove solo se un segnale indipendente concorda sulla stessa base di allocazione — hit di firma, missing_peb_entry, private_rwx, prologo di hook o diff su disco |
| L4 | Consapevole del CLR | Soppressione per-modulo per target ngen / R2R / tiered-JIT (*.ni.dll, mscor*, clr*, coreclr, system.private.corelib*) invece di saltare tutto quando il CLR è caricato |
| L5 | Diff su disco | Mappa il file del modulo con CreateFileMappingW(SEC_IMAGE_NO_EXECUTE); confronta i primi 16 byte di ogni pagina eseguibile privata con lo stesso RVA su disco. Qualsiasi divergenza è un IOC di modifica reale |
49 BB ?? ?? ?? ?? ?? ?? ?? ?? 41 FF E3 — stile Detours
MOV R11, imm64 ; JMP R11Cor_Private_IPCBlock_v4_<PID> e per la v2 Cor_Private_IPCBlock_<PID> (legacy .NET 2/3 / mscorwks), così gli application pool rumorosi che eseguono runtime vecchi non vengono classificati erroneamente| Verdetto | Severità | Condizione |
|---|
TSAV_SHELLCODE_PRIVATE | CRITICAL | L'indirizzo si trova in una regione MEM_PRIVATE + PAGE_EXECUTE_* — classico shellcode CreateRemoteThread |
TSAV_SUSPENDED_RIP | CRITICAL | Il Rip del thread sospeso non corrisponde a Win32StartAddress e risolve in una regione sospetta — intercetta lo spoofing di Win32StartAddress (trucchi EarlyBird / APC) e gli hijack di SetThreadContext |
TSAV_HOLLOWED_HOST | HIGH | Indirizzo all'interno di un'allocazione MEM_IMAGE che non è nella lista dei moduli del PEB (DLL hollowing / module stomping) |
TSAV_MODIFIED_HOST | HIGH | Indirizzo all'interno di un'allocazione MEM_IMAGE che il pipeline L1–L5 ha già segnalato come MODIFIED_CODE_*, MISSING_PEB, PRIVATE_RWX, DISK_MEM_DIFF o HOOK_PROLOGUE |
TSAV_STAGED_PRIVATE_RW | HIGH | MEM_PRIVATE + PAGE_READWRITE — staging di shellcode pre-VirtualProtect |
TSAV_MAPPED_NONPE | MEDIUM | MEM_MAPPED (sezione supportata da pagefile) senza header PE — loader riflessivo sRDI / pagefile |
TSAV_SPOOF_TRAMPOLINE | MEDIUM | L'indirizzo corrisponde a un trampoline in denylist (LoadLibraryA/W/ExA/W, WinExec, CreateProcessA/W, VirtualAlloc[Ex], RtlExitUserThread, RtlExitUserProcess, NtTerminateProcess, ShellExecuteA/W) |
QUERY_INFORMATION | GET_CONTEXTQUERY_INFORMATIONQUERY_LIMITED_INFORMATION| Filtro | Regola | Classe di FP che rimuove |
|---|
| F1 | count >= 5 | dati casuali a forma di puntatore, NULL, HMODULES |
| F2 | rifiuta sequenze che puntano solo all'EXE host | vtable C++ della classe applicazione |
| F3 | distinct_modules >= 2 | vtable di framework a DLL singola (Qt, MFC, wxWidgets) |
| F4 | capability_modules >= 2 | vtable di browser / CRT che toccano una singola DLL di sistema (es. iertutil + ucrtbase + shlwapi) |
| F5 (L10) | >= 80% dei puntatori controllabili ricade su RVA esportate | tabelle dispatch LSP di Winsock, array di callback di plugin, vtable che puntano a metodi interni (non esportati) |
| Flag | Descrizione |
|---|
--pid, -p <PID> | ID del processo target da scansionare |
--lookup, -l <name> | Trova tutti i PID che corrispondono a un nome di processo |
--json, -j | Restituisce i risultati in JSON (per l'integrazione con SIEM) |
--verbose, -v | Mostra i dettagli di scansione per regione |
--scan-all, -a | Scansiona tutti i processi |
--hunt, -b <PID> [ms] [hits] | Monitora le connessioni — interroga ogni ms (default 2000), segnala gli endpoint con ≥ hits occorrenze |
--networking | Modalità di monitoraggio della rete |
--rules, -r <dir> | Directory delle regole (default: rules/) |
--config, -c <file> | File di regole singolo (formato legacy) |
--dump, `` | Dump di una specifica regione di memoria con dimensione personalizzata |
--read, `` | Legge il contenuto di una regione di memoria in tempo reale sul terminale |
--help, -h | Mostra l'aiuto |