
Outil de forensique mémoire et de chasse aux menaces pour Windows qui analyse la mémoire des processus en direct à la recherche de motifs malveillants, de techniques d'injection et d'assemblages .NET chargés de manière réflexive, en utilisant un modèle de confiance multicouche pour réduire les faux positifs.

version : 0.9 (version stable)
Aether est un outil de forensique mémoire et de chasse aux menaces sous Windows qui analyse la mémoire des processus en direct à la recherche de motifs malveillants, détecte les techniques d'injection, les signatures d'implant, les assemblages .NET chargés de manière réfléchie. Il fonctionne avec un modèle de confiance multicouche qui réduit considérablement le taux de faux positifs et chasse les comportements malveillants. Aether possède de bonnes capacités de détection des techniques de Hollowing, d'APC et de détournement de threads. Les analystes de sécurité peuvent l'utiliser pour scanner, chasser et capturer des régions suspectes pour une analyse hors ligne.
Documentation : https://0xsp.com/docs/aether-getting-started/
Articles de recherche :
Explications rapides des fonctionnalités principales d'Aether, vous pouvez lire l'article technique complet pour plus de détails :
"msxsl:script" devient 6D 00 73 00 78 00 ...)rules/
sans recompilationMEM_PRIVATE — signale les assemblages .NET chargés de manière réfléchie
(métadonnées MZ + PE + BSJB)Aether superpose cinq filtres au signal brut de l'ensemble de travail, de sorte qu'une constatation nécessite plusieurs indicateurs concordants avant d'être signalée avec un filtrage FP :
Autres vérifications structurelles :
MEM_IMAGE qui ne sont pas dans
la liste des modules du PEB (DLL hollowing / module stomping)K32QueryWorkingSetEx, regroupée avec un seul appel système par région au lieu
d'un par page de 4 Ko (environ 50 à 100 fois plus rapide que la boucle naïve)MEM_PRIVATE + PAGE_EXECUTE_* (cela produit des résultats FP)
(shellcode, JIT spray, allocations de stubs de code dynamique)E9 ?? ?? ?? ?? — JMP rel32FF 25 ?? ?? ?? ?? — JMP [rip+disp32]68 ?? ?? ?? ?? C3 — PUSH imm32 ; RET48 B8 ?? ?? ?? ?? ?? ?? ?? ?? FF E0 — Aether vérifie les threads avec une classification plus stricte et une
corrélation croisée avec les résultats L1–L5. Pour chaque thread créé dans le
processus cible, Aether lit son Win32StartAddress via NtQueryInformationThread
et, lorsque les permissions le permettent, également le Rip / Eip en direct via
GetThreadContext / Wow64GetThreadContext.
Chaque adresse est ensuite évaluée selon le tableau suivant, pour plus de détails lisez l'article de blog :
Ce qui rend cette vérification plus forte que la vérification de base "l'adresse de démarrage est-elle dans un module" :
VirtualQueryEx — chaque adresse est interrogée pour Type /
Protect / AllocationBase en un seul appel O(1) au lieu d'un balayage linéaire
de la liste des modulesTSAV_MODIFIED_HOSTWin32StartAddress est accessible en écriture via
NtSetInformationThread et est le champ usurpable ; le Rip en direct d'un
thread suspendu est celui qu'un chargeur ne peut pas facilement réécrire. Nous comparons
les deux et signalons toute divergence pointant vers une région suspecteWow64GetThreadContext et
lit Eip pour les threads 32 bits dans un processus 64 bitsLa résolution d'API à l'exécution est une technique fréquemment utilisée par les logiciels malveillants. Le mécanisme de détection d'Aether identifie ce comportement en analysant le tas à la recherche d'adresses et de pointeurs de module valides, et en corrélant les résultats avec les critères de filtrage décrits ci-dessous :
Chaque filtre élimine une classe FP spécifique observée dans la télémétrie réelle :
Aether prend en charge la détection de motifs XOR au niveau du stub pour l'instant et adopte l'algorithme d'entropie de Shannon pour vérifier le caractère aléatoire des valeurs d'octets dans une région mémoire, il signale tout ce qui dépasse un seuil. Pour faire face au nombre élevé de FP, Aether utilise plusieurs indicateurs.
GetExtendedTcpTable pour un PID cibleMODIFIED_CODE_* comporte
private_pages et region_pages afin que le triage dispose des chiffres réelsAether.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
# Construction Debug (contrôles de sécurité activés)
zig build
# Construction Release (binaire plus petit, plus rapide)
zig build -Doptimize=ReleaseSafe
# ou
zig build -Doptimize=ReleaseFast
L'exécutable construit se trouve dans zig-out/bin/Aether.exe.
Copiez zig-out/bin/Aether.exe et le répertoire rules/ sur la machine
Windows cible si vous souhaitez effectuer une analyse de signature supplémentaire. Si le processus cible nécessite des privilèges Administrateur, vous devez exécuter Aether.exe avec les privilèges Administrateur.
Win32StartAddress
sur un thread déjà en cours d'exécution ne peut être détectée que si le thread
se trouve en attente au moment de la sonde (même contrainte que Moneta)Aether Community est sous licence GNU GPL v3.0. Des licences commerciales sont disponibles uniquement auprès de l'auteur pour une utilisation propriétaire ou commerciale.
| Couche | Filtre | Objectif |
|---|
| L1 | Structurel | Seules les sous-régions IMAGE exécutables sont considérées (élimine le bruit COW de .data / .rdata) |
| L2 | Quantitatif | Évaluation par le nombre de private_pages et le private_ratio (faible / moyen / élevé) |
| L3 | Corroboration | Promu seulement si un signal indépendant s'accorde sur la même base d'allocation — hit de signature, missing_peb_entry, private_rwx, prologue de hook, ou diff sur disque |
| L4 | Sensible au CLR | Suppression par module pour les cibles ngen / R2R / tiered-JIT (*.ni.dll, mscor*, clr*, coreclr, system.private.corelib*) au lieu d'un saut global lorsque le CLR est chargé |
| L5 | Diff sur disque | Mappe le fichier module avec CreateFileMappingW(SEC_IMAGE_NO_EXECUTE) ; compare les 16 premiers octets de chaque page privée exécutable avec la même RVA sur disque. Toute divergence est un IOC de modification réelle |
MOV RAX, imm64 ; JMP RAX49 BB ?? ?? ?? ?? ?? ?? ?? ?? 41 FF E3 — style Detours
MOV R11, imm64 ; JMP R11Cor_Private_IPCBlock_v4_<PID>
et la v2 Cor_Private_IPCBlock_<PID> (héritage .NET 2/3 / mscorwks),
de sorte que les pools d'applications bruyants exécutant d'anciens runtimes ne soient pas mal classifiés| Verdict | Sévérité | Condition |
|---|
TSAV_SHELLCODE_PRIVATE | CRITIQUE | L'adresse se trouve dans une région MEM_PRIVATE + PAGE_EXECUTE_* — shellcode CreateRemoteThread classique |
TSAV_SUSPENDED_RIP | CRITIQUE | Le Rip du thread suspendu diffère de Win32StartAddress et pointe vers une région suspecte — détecte l'usurpation de Win32StartAddress (astuces EarlyBird / APC) et les détournements SetThreadContext |
TSAV_HOLLOWED_HOST | ÉLEVÉ | Adresse dans une allocation MEM_IMAGE qui n'est pas dans la liste des modules du PEB (DLL hollowing / module stomping) |
TSAV_MODIFIED_HOST | ÉLEVÉ | Adresse dans une allocation MEM_IMAGE que le pipeline L1–L5 a déjà signalée comme MODIFIED_CODE_*, MISSING_PEB, PRIVATE_RWX, DISK_MEM_DIFF, ou HOOK_PROLOGUE |
TSAV_STAGED_PRIVATE_RW | ÉLEVÉ | MEM_PRIVATE + PAGE_READWRITE — préparation de shellcode avant VirtualProtect |
TSAV_MAPPED_NONPE | MOYEN | MEM_MAPPED (section basée sur le fichier d'échange) sans en-tête PE — chargeur réfléchi sRDI / pagefile |
TSAV_SPOOF_TRAMPOLINE | MOYEN | L'adresse correspond à un trampoline en liste de blocage (LoadLibraryA/W/ExA/W, WinExec, CreateProcessA/W, VirtualAlloc[Ex], RtlExitUserThread, RtlExitUserProcess, NtTerminateProcess, ShellExecuteA/W) |
QUERY_INFORMATION | GET_CONTEXTQUERY_INFORMATIONQUERY_LIMITED_INFORMATION| Filtre | Règle | Classe FP qu'il supprime |
|---|
| F1 | count >= 5 | données en forme de pointeur aléatoire, NULL, HMODULES |
| F2 | rejeter les séquences pointant uniquement vers l'EXE hôte | vtables de classe d'application C++ |
| F3 | distinct_modules >= 2 | vtables de framework à DLL unique (Qt, MFC, wxWidgets) |
| F4 | capability_modules >= 2 | vtables de navigateur / CRT touchant une seule DLL OS (ex. iertutil + ucrtbase + shlwapi) |
| F5 (L10) | >= 80% des pointeurs vérifiables atterrissent sur des RVA exportés | tables de distribution Winsock LSP, tableaux de rappels de plugins, vtables pointant vers des méthodes internes (non exportées) |
| Drapeau | Description |
|---|
--pid, -p <PID> | ID du processus cible à analyser |
--lookup, -l <name> | Trouver tous les PID correspondant à un nom de processus |
--json, -j | Sortie des résultats au format JSON (pour intégration SIEM) |
--verbose, -v | Afficher les détails d'analyse par région |
--scan-all, -a | Analyser tous les processus |
--hunt, -b <PID> [ms] [hits] | Surveiller les connexions — interroger toutes les ms (défaut 2000), signaler les points de terminaison avec ≥ hits occurrences |
--networking | Mode de surveillance réseau |
--rules, -r <dir> | Répertoire des règles (défaut : rules/) |
--config, -c <file> | Fichier de règle unique (format hérité) |
--dump, `` | Vider une région mémoire spécifique avec une taille personnalisée |
--read, `` | Lire le contenu d'une région mémoire en direct sur le terminal |
--help, -h | Afficher l'aide |