derekxmartin/sentinel-edr

GitHub: derekxmartin/sentinel-edr

一个教学级 Windows x64 EDR 原型,完整实现内核遥测、API Hook、YARA 扫描和多层检测引擎,用于深入学习和研究端点检测与响应系统的工作原理。

Stars: 1 | Forks: 0

# SentinelEDR

SentinelEDR Logo

一个针对 Windows x64 的概念验证端点检测与响应 (EDR) 代理,从零开始构建,具备内核模式遥测、用户模式 API Hook、YARA 扫描以及多层检测引擎。 架构设计源于 Matt Hand 所著 *Evading EDR* (No Starch Press, 2023) 中的传感器模型。 ## 什么是 EDR? **端点检测与响应** (EDR) 代理是一种运行在环境中每个端点(工作站、服务器、笔记本电脑)上的软件,用于持续监控系统活动、检测恶意行为,并为安全团队提供调查和响应威胁所需的数据。 ### 为什么 EDR 很重要 传统的防病毒软件依赖于静态文件签名——它只能捕捉已知的内容。攻击者可以通过加壳、混淆和无文件技术轻松绕过这种防御。EDR 采取了截然不同的方法: - **深度可见性。** EDR 在每一层对操作系统进行检测——内核回调、API Hook、ETW 跟踪、脚本检查——以捕获主机上 *实际发生* 的事情,而不仅仅是磁盘上存在的文件。这种遥测涵盖了进程创建、内存操作、注册表更改、网络连接、DLL 加载等。 - **行为检测。** EDR 不匹配文件哈希,而是监控动作序列。单个 `VirtualAllocEx` 调用是正常的;但快速连续执行 `VirtualAllocEx(RW)` → `VirtualProtect(RX)` → `CreateRemoteThread` 则是经典的 shellcode 注入模式。EDR 实时关联这些事件。 - **入侵后调查。** 当事件发生时,EDR 的遥测日志成为取证记录。分析师可以重建完整的攻击链——初始访问、横向移动、持久化、数据暂存——而无需依赖攻击者留下痕迹。 - **威胁狩猎。** 安全从业者主动查询 EDR 遥测数据,以搜索自动规则未标记的技术和指标。遥测越丰富,狩猎就越有效。 ### 谁在使用 EDR | 角色 | 如何使用 EDR | |------|------------------| | **SOC 分析师** | 对警报进行分类,调查检测结果,确定入侵范围 | | **事件响应人员** | 从遥测数据重建攻击时间线,识别受影响的主机 | | **威胁猎人** | 查询历史遥测数据以查找全网的 TTP 和 IOC | | **检测工程师** | 基于 ATT&CK 技术编写和调整行为规则 | | **红队成员** | 研究 EDR 内部机制以了解防御覆盖范围和盲点 | ### 为什么要构建一个? 理解 EDR 在实现层面的工作原理——内核回调、内联 Hook、过滤驱动程序、ETW 管道——是理解防御者能看到什么以及攻击者试图逃避什么的最快途径。SentinelPOC 正是为这一目的而存在:一个完全透明、源码可用的 EDR,供安全从业者学习、修改和实验。 ## 功能特性 SentinelPOC 在每一层检测 Windows 系统——内核回调、内联 API Hook、ETW 跟踪、AMSI 集成和文件系统过滤——以收集安全遥测数据并实时检测对手技术。 **亮点:** - **内核模式驱动程序**,支持进程、线程、对象、映像加载、注册表、文件 I/O、网络和命名管道回调 - 通过内核 APC 向每个新进程 **自动注入 DLL**,以实现用户模式 API Hook 覆盖 - **13 个被 Hook 的 ntdll/kernel32 函数**,捕获内存分配、进程注入和线程创建 - **8 个 ETW 提供程序**,用于 .NET 程序集加载、PowerShell 脚本块、DNS 查询、Kerberos 认证、RPC 调用等 - **自定义 AMSI 提供程序**,根据 YARA 规则扫描 PowerShell/VBScript/JScript 内容 - 由 minifilter 文件事件触发的 **访问时 YARA 扫描**,具备基于哈希的缓存 - **内存扫描**,用于检测无主可执行区域(shellcode 注入检测) - **三层检测引擎**:单事件规则、时间有序序列规则和基于阈值的警报 - **14 条 YARA 规则**,检测 Cobalt Strike、Mimikatz、加壳二进制文件、可疑 PE 特征和 XLL shellcode - **基于 Git 的规则更新**,支持试运行验证和失败时自动回滚 - **CLI 管理工具**,用于实时状态、警报、进程检查、网络连接和配置查询 - **INI 样式配置文件**,具有运行时可调的路径、扫描器限制和阈值 - **JSON-lines 遥测日志**,自动轮转 ## 架构 ``` ┌─────────────────────────────────────────────────────────────────┐ │ KERNEL MODE │ │ │ │ sentinel-drv.sys │ │ ├── Process/Thread callbacks ─────┐ │ │ ├── Object callbacks (LSASS │ │ │ │ protection) │ Filter Communication │ │ ├── Image-load + KAPC injection ├──── Port ──────────┐ │ │ ├── Registry callbacks │ │ │ │ ├── Minifilter (file I/O + hash) │ │ │ │ ├── Named pipe monitoring │ │ │ │ └── WFP callout (network) ──────┘ │ │ └─────────────────────────────────────────────────────────│───────┘ │ ┌─────────────────────────────────────────────────────────│───────┐ │ USER MODE │ │ │ ▼ │ │ sentinel-agent.exe │ │ ├── Driver Port Receiver ◄────────────────────────────┘ │ │ ├── Pipe Server ◄──────────── sentinel-hook.dll (per-process) │ │ ├── ETW Consumer ◄─────────── 8 system providers │ │ ├── AMSI Provider ◄────────── PowerShell / script hosts │ │ │ │ │ ├── Event Queue ──► Processing Thread │ │ │ ├── Process table enrichment │ │ │ ├── On-access YARA scanner │ │ │ ├── Memory scanner (unbacked regions) │ │ │ ├── Single-event rule engine │ │ │ ├── Sequence rule engine │ │ │ ├── Threshold rule engine │ │ │ └── JSON log writer (auto-rotate) │ │ │ │ │ ├── Command Handler ◄──────── sentinel-cli.exe (named pipe) │ │ └── Config Loader ◄──────── sentinel.conf (INI-style) │ └─────────────────────────────────────────────────────────────────┘ ``` ## 组件 | 组件 | 语言 | 描述 | |-----------|----------|-------------| | **sentinel-drv** | C17 (WDK) | 内核模式 WDM 驱动程序,包含 8 种回调类型、minifilter、WFP callout 和 KAPC 注入 | | **sentinel-hook** | C17 | 通过内核 APC 注入的用户模式 Hook DLL。对 13 个 ntdll/kernel32 函数进行内联 Hook | | **sentinel-agent** | C++20 | Windows 服务:事件聚合、规则引擎、ETW 消费者、AMSI 提供程序、YARA 扫描器、配置加载器 | | **sentinel-amsi** | C++20 | 注册到 Windows 的 AMSI 提供程序 DLL,用于脚本内容扫描 | | **sentinel-cli** | C++20 | 控制台管理工具:状态、警报、扫描、进程/连接检查、配置查询 | ## CLI 命令 ``` sentinel-cli [args] [--json] ``` | 命令 | 描述 | |---------|-------------| | `status` | 代理健康状态、驱动状态、运行时间、规则计数、队列深度 | | `alerts [N]` | 显示最近 N 条警报,包含严重性、规则名称、触发器和 PID(默认:20) | | `scan ` | 对文件触发按需 YARA 扫描 | | `rules reload` | 从磁盘热重载行为和 YARA 规则 | | `rules update` | Git pull 最新规则,验证并热重载(失败时回滚) | | `rules update --init` | 首次设置时克隆规则仓库(需要 `--rules-repo` 和 `--yara-repo`) | | `connections` | 网络连接表:远程 IP、端口、协议、命中计数、PID | | `processes` | 被跟踪的进程,包含 PPID、完整性级别、提权状态 | | `hooks` | 每个被跟踪进程的 Hook DLL 注入状态 | | `config` | 显示当前代理配置(路径、扫描器限制、阈值) | 对任何命令添加 `--json` 以获取适合脚本和 SIEM 接收的原始 JSON 输出。 ### 规则更新工作流 `rules update` 命令提供了一个安全的一键式签名更新工作流: ``` # 首次设置:克隆 rule repositories sentinel-cli rules update --init --rules-repo https://github.com/org/rules.git --yara-repo https://github.com/org/yara-rules.git # 后续更新:pull、validate、reload sentinel-cli rules update ``` 更新过程: 1. 保存当前 HEAD SHA 以便回滚 2. 在两个规则目录上运行 `git pull --ff-only` 3. 向代理发送验证并重载命令 4. 代理试运行解析所有规则(检测 + YARA)而不激活 5. 成功:将规则热重载到运行中的代理 6. 失败:CLI 通过 `git reset --hard` 回滚——旧规则保持活动状态 使用不支持模块(例如 `cuckoo`、`androguard`)的 YARA 文件在编译期间会自动跳过,从而允许与 [Yara-Rules](https://github.com/Yara-Rules/rules) 等社区规则集兼容。 ## 配置 代理在启动时读取 INI 样式的配置文件。默认位置:`C:\SentinelPOC\sentinel.conf`。使用 `--config ` 覆盖。 缺少键或文件时,会平滑回退到编译时的默认值。 ``` [paths] log_path = C:\SentinelPOC\agent_events.jsonl amsi_dll = C:\SentinelPOC\sentinel-amsi.dll rules_dir = C:\SentinelPOC\rules yara_rules_dir = C:\SentinelPOC\yara-rules [scanner] max_file_size_mb = 50 # Max file size for on-access YARA scan max_region_size_mb = 10 # Max memory region size for memory scanner cache_ttl_sec = 300 # Scan result cache lifetime (seconds) [logging] max_log_size_mb = 100 # Log rotation threshold [network] max_events_per_sec = 100 # Per-PID network event rate limit [git] # rules_repo_url = https://github.com/org/sentinel-rules.git # yara_rules_repo_url = https://github.com/org/sentinel-yara-rules.git ``` 使用 `sentinel-cli config` 查询运行中代理的活动配置。 ## 遥测源 | 来源 | 起源 | 捕获内容 | |--------|--------|------------------| | Process | 驱动回调 | 进程创建/终止、映像路径、命令行、SID、完整性级别 | | Thread | 驱动回调 | 线程创建/终止、远程线程检测 | | Object | 驱动回调 | 对受保护进程的句柄操作 | | ImageLoad | 驱动回调 | DLL/EXE 加载及签名验证 | | Registry | 驱动回调 | 键创建/打开、值设置/删除(经噪声过滤) | | File | Minifilter | 文件创建/写入/重命名/删除及 SHA-256 哈希 | | Network | WFP callout | 入站/出站连接,按 PID 限速 | | Pipe | Minifilter | 命名管道创建及可疑管道检测 | | HookDll | 内联 Hook | 13 个 API 调用:内存操作、线程操作、进程打开、管道创建 | | ETW | 8 个提供程序 | .NET 程序集、PowerShell 脚本、DNS、Kerberos、RPC、服务、内核进程 | | AMSI | COM 提供程序 | 由 PowerShell/VBScript/JScript 主机扫描的脚本内容 | | Scanner | YARA 引擎 | 访问时文件扫描和内存区域扫描结果及规则匹配详情 | ## 检测能力 ### YARA 规则(5 个文件中的 14 条规则) | 文件 | 规则 | 检测内容 | |------|-------|---------| | `cobaltstrike_beacon.yar` | 3 | Beacon 配置块、shellcode stager、默认管道名 | | `mimikatz.yar` | 3 | 二进制构建、PowerShell 移植版、内核驱动 | | `suspicious_pe.yar` | 4 | RWX 节、注入导入、加壳节名、高熵节 | | `upx_packed.yar` | 2 | 标准和修改过的 UPX 加壳 | | `xll_shellcode.yar` | 2 | 带有 shellcode stager 或注入导入的 Excel XLL 加载项 | ### 行为检测规则(5 条规则,3 种类型) | 规则 | 类型 | ATT&CK | 触发条件 | |------|------|--------|---------| | 可疑 RWX 分配 | Single | T1055 | 跨进程 `NtAllocateVirtualMemory` 且权限为 `PAGE_EXECUTE_READWRITE` | | 远程线程创建 | Single | T1055.003 | `NtCreateThreadEx` 目标为不同进程 | | Excel 生成 cmd.exe | Single | T1059.003 | `cmd.exe` 为 `excel.exe` 的子进程 | | Shellcode 运行器模式 | Sequence | T1055 | 5 秒内 Alloc(RW) → Protect(RX) → CreateThread | | 快速内存分配 | Threshold | — | 单个进程在 10 秒内 ≥500 次 `NtAllocateVirtualMemory` 调用 | ## 被 Hook 的函数 Hook DLL 通过内联 Hook 拦截 13 个 ntdll/kernel32 函数: | 类别 | 函数 | |----------|-----------| | **Memory** | `NtAllocateVirtualMemory`, `NtProtectVirtualMemory`, `NtWriteVirtualMemory`, `NtReadVirtualMemory`, `NtMapViewOfSection`, `NtUnmapViewOfSection`, `NtCreateSection` | | **Thread** | `NtCreateThreadEx`, `NtQueueApcThread`, `NtSuspendThread`, `NtResumeThread` | | **Process** | `NtOpenProcess` | | **Pipe** | `NtCreateNamedPipeFile` | ## 构建 ### 前置条件 - **Visual Studio 2022** 及 C++ 桌面开发工作负载 - **CMake 3.20+** - **Windows Driver Kit (WDK)** — 内核驱动必需;没有它也可以构建用户模式组件 ### 配置与构建 ``` cmake -B build -G "Visual Studio 17 2022" -A x64 cmake --build build --config Release ``` 如果未安装 WDK,`sentinel-drv` 会自动跳过。所有其他组件正常构建。 输出二进制文件位于 `build/bin/Release/`: - `sentinel-agent.exe` — 主代理服务 - `sentinel-cli.exe` — 管理 CLI - `sentinel-drv.sys` — 内核驱动(需要 WDK) - `sentinel-hook.dll` — Hook DLL(由驱动注入) - `sentinel-amsi.dll` — AMSI 提供程序(由代理注册) ### 测试签名(驱动部署必需) ``` # 在 VM 上启用 test signing(需要重启) .\scripts\setup-testsigning.ps1 # 对 driver 进行签名 .\scripts\sign-driver.ps1 ``` ## 部署 ### 1. 准备部署目录 ``` # 创建部署目录 New-Item -ItemType Directory -Force -Path C:\SentinelPOC # 复制二进制文件 Copy-Item build\bin\Release\sentinel-agent.exe C:\SentinelPOC\ Copy-Item build\bin\Release\sentinel-cli.exe C:\SentinelPOC\ Copy-Item build\bin\Release\sentinel-hook.dll C:\SentinelPOC\ Copy-Item build\bin\Release\sentinel-amsi.dll C:\SentinelPOC\ # 复制配置 Copy-Item sentinel.conf C:\SentinelPOC\ # 复制 rules Copy-Item -Recurse rules\ C:\SentinelPOC\rules\ Copy-Item -Recurse yara-rules\ C:\SentinelPOC\yara-rules\ ``` ### 2. 安装并启动内核驱动 ``` # 复制已签名的 driver Copy-Item build\bin\Release\sentinel-drv.sys C:\SentinelPOC\ # 创建 driver service sc.exe create SentinelDrv type=kernel binPath="C:\SentinelPOC\sentinel-drv.sys" # 启动 driver sc.exe start SentinelDrv ``` ### 3. 运行代理 **控制台模式**(推荐用于测试): ``` # 以提升的命令提示符运行 C:\SentinelPOC\sentinel-agent.exe --console ``` 使用自定义配置文件: ``` C:\SentinelPOC\sentinel-agent.exe --console --config C:\SentinelPOC\sentinel.conf ``` 代理将: 1. 从 `sentinel.conf` 加载配置(或使用默认值) 2. 从配置的规则目录加载 YAML 测规则 3. 从配置的 YARA 规则目录编译 YARA 规则 4. 连接到内核驱动的过滤通信端口 5. 启动 Hook DLL 遥测的命名管道服务器 6. 初始化 8 个系统提供程序的 ETW 消费者 7. 注册自定义 AMSI 提供程序 8. 开始处理事件并写入 JSON 日志 按 **Ctrl+C** 干净地停止。 **服务模式**(用于持久部署): ``` sc.exe create SentinelAgent binPath="C:\SentinelPOC\sentinel-agent.exe" start=auto sc.exe start SentinelAgent ``` ### 4. 验证操作 代理运行后,打开第二个终端: ``` # 检查 agent 健康状况 C:\SentinelPOC\sentinel-cli.exe status # 查看活动配置 C:\SentinelPOC\sentinel-cli.exe config # 列出 tracked processes C:\SentinelPOC\sentinel-cli.exe processes # 查看网络连接 C:\SentinelPOC\sentinel-cli.exe connections # 检查近期 alerts C:\SentinelPOC\sentinel-cli.exe alerts ``` ## 测试访问时扫描 要验证 YARA 访问时扫描是否正常工作: ``` :: From an elevated cmd.exe (not PowerShell — AMSI will block the strings) echo sekurlsa:: kerberos:: lsadump:: privilege:: logonPasswords > C:\Users\%USERNAME%\Desktop\evil.txt ``` 几秒钟内,代理控制台应显示: ``` [NNN] source=Scanner type=OnAccess path=C:\Users\...\evil.txt match=YES rule=Mimikatz_Binary ``` minifilter 检测到文件创建,计算 SHA-256 哈希,访问时扫描器对文件运行 YARA 规则。结果被缓存(可通过 `cache_ttl_sec` 配置)以避免重复扫描。 ## 项目结构 ``` claude-edr/ ├── CMakeLists.txt Top-level build configuration ├── sentinel.conf Default agent configuration file ├── common/ Shared headers │ ├── telemetry.h Event schema (SENTINEL_EVENT union) │ ├── constants.h System-wide constants │ ├── ipc.h Named pipe protocol + command types │ └── ipc_serialize.h Binary serialization helpers ├── sentinel-drv/ Kernel-mode driver │ ├── main.c DriverEntry, cleanup, unload │ ├── callbacks_process.c PsSetCreateProcessNotifyRoutineEx │ ├── callbacks_thread.c PsSetCreateThreadNotifyRoutineEx │ ├── callbacks_object.c ObRegisterCallbacks │ ├── callbacks_image.c PsSetLoadImageNotifyRoutineEx │ ├── callbacks_registry.c CmRegisterCallbackEx │ ├── minifilter.c FltRegisterFilter (file I/O) │ ├── minifilter_pipes.c Named pipe creation monitoring │ ├── wfp_callout.c WFP network callout │ ├── kapc_inject.c Kernel APC DLL injection │ └── file_hash.c SHA-256 file hashing ├── sentinel-hook/ User-mode hooking DLL │ ├── main.c DllMain, hook installation │ ├── hook_engine.c Inline hook framework │ ├── hooks_memory.c Memory operation hooks │ ├── hooks_thread.c Thread operation hooks │ ├── hooks_process.c Process operation hooks │ └── pipe_client.c Named pipe telemetry sender ├── sentinel-agent/ Agent service │ ├── main.cpp Entry point (--console, --config) │ ├── service.cpp SCM handler + console mode │ ├── config.cpp INI config parser + serializer │ ├── config.h SentinelConfig struct + API │ ├── pipeline.cpp Event queue + receiver threads │ ├── event_processor.cpp Event routing + enrichment │ ├── cmd_handler.cpp CLI command dispatch (9 commands) │ ├── json_writer.cpp JSON-lines log output + rotation │ ├── network_table.cpp Connection tracking table │ ├── scanner/ │ │ ├── yara_scanner.cpp libyara integration │ │ ├── onaccess_scanner.cpp File event → YARA scan │ │ └── memory_scanner.cpp Unbacked region detection │ ├── rules/ │ │ ├── rule_engine.cpp Single-event rule evaluation │ │ ├── sequence_engine.cpp Time-ordered sequence detection │ │ ├── threshold_engine.cpp Count-based alerting │ │ ├── rule_parser.cpp YAML rule loading │ │ └── rule_validator.cpp Dry-run rule validation │ ├── etw/ │ │ └── etw_consumer.cpp ETW trace session + 8 providers │ └── amsi/ │ └── amsi_provider.cpp Custom AMSI COM provider ├── sentinel-amsi/ AMSI provider DLL host ├── sentinel-cli/ CLI management tool │ └── main.cpp 9 commands + git operations + pretty-printers ├── yara-rules/ YARA detection rules (14 rules) ├── rules/ YAML behavioral rules (5 rules) ├── tests/ Integration tests ├── scripts/ Setup and signing scripts ├── deps/ External dependencies (libyara) ├── cmake/ CMake modules (FindWdk) └── certs/ Test signing certificates ``` ## 实现阶段 | 阶段 | 描述 | 状态 | |-------|-------------|--------| | P0 | 项目脚手架、构建系统、共享头文件 | Done | | P1 | 进程和线程内核回调 | Done | | P2 | 对象、映像加载和注册表回调 + KAPC 注入 | Done | | P3 | 具有 13 个内联 Hook 的用户模式 Hooking DLL | Done | | P4 | 具有事件管道和三层规则引擎的代理服务 | Done | | P5 | Minifilter、文件哈希和命名管道监控 | Done | | P6 | WFP 网络 callout 和连接表 | Done | | P7 | ETW 消费者(8 个提供程序)和自定义 AMSI 提供程序 | Done | | P8 | YARA 扫描器集成、访问时扫描、内存扫描 | Done | | P9 | CLI 管理工具、检查命令、配置文件 | Done | | P10 | 集成测试(端到端攻击链) | Pending | | P11 | 加固和自我保护(逃避检测) | Pending | 完整的实现路线图请参阅 `REQUIREMENTS.md`。 ## 许可证 MIT 许可证。详见 [LICENSE](LICENSE)。 ## 免责声明 这是一个用于学习和研究目的的教育性概念验证。它 **不是** 生产级安全软件。仅在经授权的隔离测试环境中部署。 ## 致谢 - *Evading EDR* 作者 Matt Hand (No Starch Press, 2023) — 本项目的架构参考 - [YARA](https://virustotal.github.io/yara/) — 模式匹配引擎 - [MITRE ATT&CK](https://attack.mitre.org/) — 检测规则的技术参考
标签:API Hooking, asyncio, ATT&CK 框架, Bash脚本, C++, DAST, EDR, Homebrew安装, IP 地址批量处理, PE 加载器, PoC, RFI远程文件包含, TCP/UDP协议, Windows 安全, x64, YARA 扫描, 内核遥测, 威胁情报, 客户端加密, 开发者工具, 恶意软件分析, 数字取证, 数据擦除, 暴力破解, 注入检测, 端点检测与响应, 网络安全监控, 脆弱性评估, 脱壳工具, 自动化脚本, 行为检测, 计算机防御, 驱动开发