
Windowsメモリフォレンジックスおよび脅威ハンティングツールで、ライブプロセスメモリをスキャンして悪意のあるパターン、インジェクション技術、リフレクティブにロードされた.NETアセンブリを検出します。多層信頼度モデルを使用して誤検知を低減します。

バージョン : 0.9 (安定版リリース)
Aether は、Windows メモリフォレンジックスおよび脅威ハンティングツールです。実行中のプロセスメモリをスキャンして悪意のあるパターンを探し、インジェクション手法、インプラントシグネチャ、リフレクティブロードされた .NET アセンブリを検出します。多層信頼度モデルを採用しており、誤検知率を大幅に削減し、悪意のある動作をハンティングします。Aether は、ホローイング、APC、スレッドハイジャック手法の検出に優れた能力を備えています。セキュリティアナリストは、これを使用して不審な領域をスキャン、ハンティング、スナップショットし、オフライン解析に利用できます。
Docs: https://0xsp.com/docs/aether-getting-started/
研究記事:
Aether のコア機能に関する簡単な説明です。詳細については、技術ブログ記事全文をお読みください:
"msxsl:script" が 6D 00 73 00 78 00 ... になる場合など)rules/ に新しいシグネチャを追加できますMEM_PRIVATE 領域内の PE ヘッダー検出 — リフレクティブロードされた .NET アセンブリ (MZ + PE + BSJB メタデータ) をフラグ付けしますAether は、生のワーキングセットシグナルの上に 5つのフィルター を重ねます。これにより、1つの検出結果が報告される(FPフィルタリング付きで)前に、複数の一致する指標が必要になります。
その他の構造チェック:
MEM_IMAGE アロケーション(DLLホローイング / モジュールストンピング)K32QueryWorkingSetEx による変更コードページの検出。4 KB ページごとではなくリージョンごとに1回の syscall で バッチ処理 されます(ナイーブなループより約 50〜100倍高速)MEM_PRIVATE + PAGE_EXECUTE_*(FP結果を生成します)アロケーションをフラグ付けします(シェルコード、JITスプレー、動的コードスタブアロケーション)E9 ?? ?? ?? ?? — JMP rel32FF 25 ?? ?? ?? ?? — JMP [rip+disp32]68 ?? ?? ?? ?? C3 — PUSH imm32 ; RET48 B8 ?? ?? ?? ?? ?? ?? ?? ?? FF E0 — MOV RAX, imm64 ; JMP RAX49 BB ?? ?? ?? ?? ?? ?? ?? ?? 41 FF E3 — Detours スタイルの
Aether は、スレッドをより厳格な分類でチェックし、L1〜L5 の検出結果と相互相関させます。対象プロセス内のすべての生成済みスレッドについて、NtQueryInformationThread を介して Win32StartAddress を読み取り、アクセスが許可される場合は GetThreadContext / Wow64GetThreadContext を介してライブの Rip / Eip も読み取ります。各アドレスは次の表のように評価されます。詳細はブログ記事をご覧ください:
これが「start_address が任意のモジュール内にあるか」という基本的なチェックよりも強力な理由:
VirtualQueryEx クロスチェック — すべてのアドレスは、モジュールリストの線形スキャンではなく、単一の O(1) 呼び出しで Type / Protect / AllocationBase を照会されますTSAV_MODIFIED_HOST に引き上げられますWin32StartAddress は NtSetInformationThread を介してプロセスから書き込み可能であり、スプーフィング可能なフィールドです。サスペンドされたスレッドのライブ Rip は、ローダーが簡単に書き換えられない値です。この2つを比較し、不審な領域に解決される不一致をフラグ付けしますWow64GetThreadContext に切り替えて Eip を読み取りますQUERY_INFORMATION | GET_CONTEXT → QUERY_INFORMATION → へとフォールバックするため、部分的なアクセスしかないシナリオでも有用な分類を生成できますランタイムAPI解決は、マルウェアが頻繁に使用する手法です。Aether の検出メカニズムは、ヒープをスキャンして有効なモジュールアドレスとポインターを探し、その結果を以下に示すフィルタリング基準と相関させることで、この動作を特定します:
各フィルターは、実際のテレメトリで観測された特定の FP クラスを除去します:
Aether は現時点ではスタブレベルでの XOR 検出パターンをサポートし、シャノンエントロピーアルゴリズムを採用してメモリ領域内のバイト値のランダム性をチェックし、しきい値を超えるすべてをフラグ付けします。大量の FP に対処するため、Aether は複数の指標を使用します。
GetExtendedTcpTable をポーリングしますMODIFIED_CODE_* 検出には private_pages と region_pages が含まれ、トリアージで実際の数値を確認できますAether.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
ビルドされた実行可能ファイルは zig-out/bin/Aether.exe に生成されます。
追加のシグネチャスキャンを実行する場合は、zig-out/bin/Aether.exe と rules/ ディレクトリをターゲットの Windows マシンにコピーします。対象プロセスに管理者権限が必要な場合は、Aether.exe を Administrator 権限で実行する必要があります。
Win32StartAddress の書き換えは、プローブ時にそのスレッドがたまたま待機状態にある場合にのみ検出できます(Moneta と同じ制約)Aether Community は GNU GPL v3.0 の下でライセンスされています。商用ライセンスは、プロプライエタリまたは商用利用の場合にのみ作者から入手できます。
| レイヤー | フィルター | 目的 |
|---|
| L1 | 構造 | 実行可能な IMAGE サブリージョンのみが対象(.data / .rdata の COW ノイズを排除) |
| L2 | 定量的 | private_pages 数と private_ratio で評価(低 / 中 / 高) |
| L3 | 裏付け | 独立した シグナルが同じアロケーションベースで一致した場合にのみ格上げ — シグネチャヒット、missing_peb_entry、private_rwx、フックプロローグ、またはディスク差分 |
| L4 | CLR対応 | CLR がロードされているときに一律にスキップするのではなく、ngen / R2R / tiered-JIT ターゲット (*.ni.dll, mscor*, clr*, coreclr, system.private.corelib*) に対してモジュール単位で抑制 |
| L5 | ディスク差分 | CreateFileMappingW(SEC_IMAGE_NO_EXECUTE) でモジュールファイルをマッピングし、各プライベート実行可能ページの最初の16バイトをディスク上の同じ RVA と比較します。差異があれば実際の改ざん IOC です |
MOV R11, imm64 ; JMP R11Cor_Private_IPCBlock_v4_<PID> および v2 の Cor_Private_IPCBlock_<PID>(レガシー .NET 2/3 / mscorwks)のセクションオブジェクトプローブ。古いランタイムを実行しているノイズの多いアプリプールが誤分類されないようにします| 判定 | 深刻度 | 条件 |
|---|
TSAV_SHELLCODE_PRIVATE | 重大 | アドレスが MEM_PRIVATE + PAGE_EXECUTE_* 領域内にある — 古典的な CreateRemoteThread シェルコード |
TSAV_SUSPENDED_RIP | 重大 | サスペンドされたスレッドの Rip が Win32StartAddress と一致せず、不審な領域に解決される場合 — Win32StartAddress のスプーフィング(EarlyBird / APC トリック)や SetThreadContext ハイジャックを捕捉します |
TSAV_HOLLOWED_HOST | 高 | PEBモジュールリストにない MEM_IMAGE アロケーション内のアドレス(DLLホローイング / モジュールストンピング) |
TSAV_MODIFIED_HOST | 高 | L1〜L5 パイプラインが既に MODIFIED_CODE_*、MISSING_PEB、PRIVATE_RWX、DISK_MEM_DIFF、または HOOK_PROLOGUE としてフラグ付けした MEM_IMAGE アロケーション内のアドレス |
TSAV_STAGED_PRIVATE_RW | 高 | MEM_PRIVATE + PAGE_READWRITE — VirtualProtect 前のシェルコードステージング |
TSAV_MAPPED_NONPE | 中 | PEヘッダーがない MEM_MAPPED(ページファイルバッキングセクション)— sRDI / ページファイルリフレクティブローダー |
TSAV_SPOOF_TRAMPOLINE | 中 | アドレスが拒否リストに登録されたトランポリンと一致(LoadLibraryA/W/ExA/W、WinExec、CreateProcessA/W、VirtualAlloc[Ex]、RtlExitUserThread、RtlExitUserProcess、NtTerminateProcess、ShellExecuteA/W) |
QUERY_LIMITED_INFORMATION| フィルター | ルール | 除去するFPクラス |
|---|
| F1 | count >= 5 | ランダムなポインター形状データ、NULL、HMODULES |
| F2 | ホストEXEのみを指すランを拒否 | アプリケーションクラスのC++ vtable |
| F3 | distinct_modules >= 2 | 単一DLLフレームワークのvtable (Qt, MFC, wxWidgets) |
| F4 | capability_modules >= 2 | 単一のOS DLLに触れるブラウザ/CRT vtable(例: iertutil + ucrtbase + shlwapi) |
| F5 (L10) | チェック可能なポインターの >= 80% が エクスポートされた RVA 上にある | Winsock LSP ディスパッチテーブル、プラグインコールバック配列、内部(非エクスポート)メソッドを指す vtable |
| フラグ | 説明 |
|---|
--pid, -p <PID> | スキャン対象のプロセスID |
--lookup, -l <name> | プロセス名に一致するすべてのPIDを検索 |
--json, -j | 結果をJSONとして出力(SIEM統合用) |
--verbose, -v | リージョンごとのスキャン詳細を表示 |
--scan-all, -a | すべてのプロセスをスキャン |
--hunt, -b <PID> [ms] [hits] | 接続を監視 — ms ごとにポーリング(デフォルト2000)、hits 回以上出現するエンドポイントをフラグ付け |
--networking | ネットワーク監視モード |
--rules, -r <dir> | ルールディレクトリ(デフォルト: rules/) |
--config, -c <file> | 単一のルールファイル(レガシー形式) |
--dump, `` | 指定サイズで特定のメモリ領域をダンプ |
--read, `` | メモリ領域の内容をターミナル上でライブ表示 |
--help, -h | ヘルプを表示 |