
版本:0.9(稳定版)
Aether 是一款 Windows 内存取证和威胁狩猎工具,可扫描活动进程内存中的恶意模式、检测注入技术、植入签名及反射加载的 .NET 程序集。它采用多层置信度模型,大幅降低误报率,并主动搜寻恶意行为。Aether 在检测进程镂空(Hollowing)、APC、线程劫持等技术方面具有良好的能力。安全分析师可使用它进行扫描、狩猎,并快照可疑区域以进行离线分析。
文档: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 在原始工作集信号之上叠加了五个过滤器,因此一个发现需要多个一致指标才被报告,并附带误报过滤:
其他结构性检查:
MEM_IMAGE 分配(DLL 镂空 / 模块踩踏)K32QueryWorkingSetEx 检测修改过的代码页,批处理方式,每次区域调用一次系统调用,而不是每 4 KB 页调用一次(比朴素循环快约 50-100 倍)MEM_PRIVATE + PAGE_EXECUTE_*(可能产生误报)分配(shellcode、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 发现结果的交叉关联来检查线程。对于目标进程中的每个已创建的线程,Aether 通过 NtQueryInformationThread 读取其 Win32StartAddress,并在权限允许时,还通过 GetThreadContext / Wow64GetThreadContext 读取实时的 Rip / Eip。每个地址随后按下表进行分级,更多细节请阅读博文:
相比简单的“起始地址是否在任何模块中”检查,此方法更强之处在于:
VirtualQueryEx 交叉检查——每个地址通过一次 O(1) 调用查询 Type / Protect / AllocationBase,而非线性扫描模块列表TSAV_MODIFIED_HOSTWin32StartAddress 可通过 NtSetInformationThread 由进程写入,是可欺骗的字段;挂起线程的实时 Rip 是加载器不易重写的字段。我们比较两者,并标记任何解析到可疑区域的不一致Wow64GetThreadContext 并读取 64 位进程中 32 位线程的 EipQUERY_INFORMATION | GET_CONTEXT → QUERY_INFORMATION → QUERY_LIMITED_INFORMATION,因此部分访问场景仍能产生有用的分类运行时 API 解析是恶意软件常用的技术。Aether 通过扫描堆中有效的模块地址和指针,并将结果与下面描述的过滤条件进行关联来识别此行为:
每个过滤器消除在实际遥测中观察到的一类特定误报:
Aether 目前支持存根级别的 XOR 检测模式,并采用 Shannon 熵算法检查内存区域中字节值的随机性,标记超过阈值的内容。为解决大量误报,Aether 使用多个指标。
GetExtendedTcpTable 获取目标 PIDMODIFIED_CODE_* 发现附带 private_pages 和 region_pages,以便分类时有实际数字Aether.exe --scan --pid <PID> [选项]
Aether.exe --scan --lookup "ProcessName.exe"
Aether.exe --hunt <PID> SLEEP_MS PERIOD
Aether.exe --scan-all [选项]
git clone https://github.com/0xsp-SRD/aether
cd aether
# 调试构建(启用安全检查)
zig build
# 发布构建(更小、更快的二进制文件)
zig build -Doptimize=ReleaseSafe
# 或
zig build -Doptimize=ReleaseFast
构建好的可执行文件位于 zig-out/bin/Aether.exe。
如果需要进行额外的签名扫描,请将 zig-out/bin/Aether.exe 和 rules/ 目录复制到目标 Windows 机器。如果目标进程需要管理员权限,则需要以管理员权限运行 Aether.exe。
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 感知 | 针对 ngen / R2R / 分层 JIT 目标(*.ni.dll、mscor*、clr*、coreclr、system.private.corelib*)进行逐模块抑制,而非在加载 CLR 时直接跳过整个进程 |
| 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 shellcode |
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 之前的 shellcode 暂存 |
TSAV_MAPPED_NONPE | 中 | MEM_MAPPED(页面文件支持的区域)且无 PE 头——sRDI / 页面文件反射加载器 |
TSAV_SPOOF_TRAMPOLINE | 中 | 地址匹配黑名单中的跳板(LoadLibraryA/W/ExA/W、WinExec、CreateProcessA/W、VirtualAlloc[Ex]、RtlExitUserThread、RtlExitUserProcess、NtTerminateProcess、ShellExecuteA/W) |
| 过滤器 | 规则 | 去除的误报类别 |
|---|
| F1 | count >= 5 | 随机指针形状的数据、NULL、HMODULE |
| F2 | 拒绝仅指向宿主 EXE 的运行 | 应用程序类 C++ vtable |
| F3 | distinct_modules >= 2 | 单个 DLL 框架 vtable(Qt、MFC、wxWidgets) |
| F4 | capability_modules >= 2 | 浏览器 / CRT vtable,仅触及一个操作系统 DLL(例如 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> [毫秒] [次数] | 监控连接——每 毫秒 轮询一次(默认 2000),标记出现次数 ≥ 次数 的端点 |
--networking | 网络监控模式 |
--rules, -r <目录> | 规则目录(默认:rules/) |
--config, -c <文件> | 单个规则文件(旧格式) |
--dump, `` | 以自定义大小转储特定内存区域 |
--read, `` | 在终端实时读取内存区域内容 |
--help, -h | 显示帮助 |