no-carve-only-pizza/edr-agent
GitHub: no-carve-only-pizza/edr-agent
基于 Linux eBPF 技术的轻量级端点检测与响应代理,通过实时系统事件监控与多维度关联分析检测 28 类已知及未知攻击模式。
Stars: 0 | Forks: 0
# EDR Agent (eBPF)
适用于 Linux 的轻量级 EDR(端点检测与响应)代理。
利用 eBPF tracepoint 实时监控进程、文件、网络、内存、DNS 和 namespace 事件,
并通过单一事件规则 + 事件关联分析 + 威胁情报源 + EWMA 行为异常检测来检测 **28 种攻击模式**。
## 项目背景
这是校内安全社团 ASC 4 人团队项目 `GhostRelay` 的成果。
团队最初是对已报告在停产 支持的 ipTIME N2V 路由器上的 UPnP Relay Command Injection
漏洞(CVE-2025-55423)进行逆向工程开始的。在实践过程中,我们感觉到“虽然可以
重现攻击命令,但很难解释清楚系统内部实际上连续发生了哪些进程、文件和网络事件”,
因此随后将团队目标转向从蓝队视角自行开发检测工具。这个仓库就是由此
诞生的基于 eBPF 的 Linux 端点传感器。
### 团队构成与职责
| 担任 | 角色 | 备注 |
|---|---|---|
| 朴道贤(本人) | Agent 开发 / 系统总负责 / 队长 | 本仓库 实现 |
| 团员 A | 攻击场景设计 / 检测验证 | 演示场景,MITRE ATT&CK 映射 |
| 团员 B | 后端 / API | 事件收集、存储、查询 API(独立仓库) |
| 团员 C | 前端 / 仪表板 UX | 事件可视化仪表板(独立仓库) |
本仓库是 `Agent → Backend → Dashboard` 整个流水线中的 Agent 部分。
Backend/Dashboard 由团队成员在各自的仓库中管理。
## 架构
```
BPF 커널 프로그램 (6개) 유저스페이스
────────────────────────────────────────────────────────────────
process_monitor.bpf.c RuleConfig::load() ← --rules rules.yaml
sched_process_exec ─┐ init_rules(cfg)
sched_process_exit │
sys_enter_execve │ ring_buffer match_rules() stdout (표)
file_monitor.bpf.c ──┤ (mmap) ─▶ dedup_alerts() ─▶ NDJSON 파일
openat/unlinkat │ to_json() HTTP POST
renameat2 │ │
network_monitor.bpf.c ─┤ CorrelationEngine → [CORRL] 상관 패턴
connect/bind │ .feed(pid,evt,ts)
memory_monitor.bpf.c ──┤
mmap/mprotect │ │
memfd_create │ FeedManager (백그라운드)
dns_monitor.bpf.c ──┤ QNAME 파싱 ├─ Feodo Tracker IP → R-025
ns_monitor.bpf.c ──┘ unshare() ├─ URLhaus domain → R-026
└─ HashChecker (SHA-256) → R-027
BehaviorProfiler (EWMA) → R-028
```
## 检测规则 (R-001 ~ R-028)
### 单一事件规则
| ID | 名称 | 严重性 |
|---|---|---|
| R-001 | 系统路径文件修改 (`/etc/`, `/bin/` 等) | high |
| R-002 | 删除日志文件(销毁证据) | high |
| R-003 | `/tmp` 路径执行(疑似 dropper) | high |
| R-004 | 执行反弹 shell/扫描工具(`nc`, `socat`, `nmap` 等) | critical |
| R-005 | 执行脚本解释器 | medium |
| R-006 | 非标准端口出站连接 | medium |
| R-007 | 未知进程绑定服务器端口 | low |
| R-008 | root 权限执行解释器 | critical |
| R-009 | `/tmp` 重命名为系统路径(疑似 TOCTOU) | critical |
| R-010 | 解释器 `-c`/`-e` 内联 payload(无文件) | high |
| R-011 | Web 服务器子进程执行 shell(`nginx`/`apache` → `bash`) | critical |
| R-012 | DB 服务器子进程执行 shell(`mysqld`/`postgres` → `bash`) | critical |
| R-013 | LD_PRELOAD 环境变量注入 | high |
| R-014 | ptrace ATTACH — 疑似进程跟踪/注入 | high |
| R-015 | 执行意外的 setuid 二进制文件 | critical |
| R-016 | RWX 内存分配(JIT spray/shellcode) | high |
| R-017 | `memfd_create` 无文件攻击模式 | critical/high |
| R-018a | DNS 隧道(标签 > 50 字符) | critical |
| R-018b | 疑似 DGA 域名(随机子域名,元音比例 < 0.15) | high |
| R-018c | 访问被滥用的 TLD(`.tk`/`.ml`/`.ga`/`.cf`/`.gq` 等) | medium |
| R-024 | 容器逃逸尝试(unshare + PID ns 比较) | critical/high |
### 威胁情报规则 (R-025~R-027)
| ID | 名称 | 严重性 | 源 |
|---|---|---|---|
| R-025 | 连接已知 C2 服务器 IP | critical | Feodo Tracker(自动更新) |
| R-026 | 恶意域名 DNS 查询 | critical | URLhaus(自动更新) |
| R-027 | 执行已知恶意文件哈希 | critical | MalwareBazaar (config/known_hashes.txt) |
### EWMA 行为异常检测 (R-028)
| ID | 指标 | 检测条件 | 严重性 |
|---|---|---|---|
| R-028 | net_connect / file_write / exec (60s 窗口) | Z 分数 ≥ 3.0,学习窗口 ≥ 3 | high |
### 事件关联分析规则 (R-019~R-023)
通过滑动窗口(30~60 秒)追踪同一 PID 的事件,以检测多阶段攻击链。
| ID | 模式 | 窗口 | 严重性 |
|---|---|---|---|
| R-019 | ptrace ↔ memfd_create | 30s | critical |
| R-020 | /tmp 执行 ↔ 出站连接 | 60s | critical |
| R-021 | /tmp 写入 → /tmp 执行 | 60s | critical |
| R-022 | RWX 内存 ↔ 出站连接 | 30s | critical |
| R-023 | 可疑 DNS 查询 ↔ 出站连接 | 30s | high |
## 主要功能
- **6 个 BPF 程序**:同时监控进程/文件/网络/内存/DNS/namespace
- **execve argv 捕获**:通过 `sys_enter_execve` 钩子收集参数,检测 R-010 内联 payload
- **进程树缓存**:通过扫描 `/proc` 预注册现有 daemon,即时激活 R-011/R-012
- **DNS BPF 解析**:在 BPF 内部直接解析 QNAME 线缆格式(通过 AND 掩码通过 Verifier)
- **容器检测**:利用 CO-RE 读取 PID ns inum,并与 init ns inum(`/proc/1/ns/pid`)进行比较
- **事件关联分析**:基于 PID 的 deque 滑动窗口,检测 5 种多阶段攻击模式
- **威胁情报源**:定期自动更新 Feodo Tracker IP + URLhaus 域名(后台线程)
- **文件哈希检测**:SHA-256 纯头文件实现 + 比对 MalwareBazaar 哈希数据库 (R-027)
- **EWMA 行为异常检测**:基于进程的连接/文件/exec 频率的 Z 分数异常检测 (R-028)
- **YAML 规则外部化**:通过 `--rules rules.yaml` 无需重新编译即可替换白名单/黑名单/端口/情报源 URL
- **白名单 FP 抑制**:过滤正常进程(sshd, apt, dockerd, gdb 等)产生的噪声
- **告警去重**:以 (rule_id, comm) 为键,抑制 3 秒窗口内的重复触发
- **主动响应**:通过 Unix domain socket 接收实时 kill 命令 (`demo/edr-ctl.sh`)
- **Agent 自我保护**:`PR_SET_DUMPABLE=0` + 检测到 ptrace 时立即终止跟踪者
- **NDJSON + HTTP POST**:使用 libcurl 将事件发送到后端 endpoint,采用 Bearer token 认证
- **会话统计**:在 Ctrl+C 时输出事件数量和各规则触发次数摘要
- **systemd 服务**:通过 `config/edr-agent.service` 进行生产环境部署
## 要求
- Linux 5.8+ (BPF ringbuf),支持 BTF 的内核(存在 `/sys/kernel/btf/vmlinux`)
- 基于 Ubuntu 22.04+
```
sudo apt install -y clang llvm libbpf-dev libelf-dev zlib1g-dev \
libcurl4-openssl-dev linux-tools-$(uname -r) cmake pkg-config
```
## 构建
```
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
```
## 运行
```
# 基本 (终端输出,使用内置默认规则)
sudo ./build/edr-agent
# 完整选项
sudo ./build/edr-agent \
--rules config/rules.yaml \ # YAML 룰 파일 (없으면 기본값)
--endpoint http://backend:8888/ingest \
--token YOUR_TOKEN \
--log /var/log/edr/events.ndjson \
--socket /run/edr-agent.sock \ # 명령 수신 소켓 (기본값)
--alerts-only # alert 있는 이벤트만 HTTP 전송
```
## 主动响应
在 Agent 运行期间,使用 `demo/edr-ctl.sh` 发送实时命令。
```
chmod +x demo/edr-ctl.sh
# 确认 Agent 响应
./demo/edr-ctl.sh ping
# → {"ok":true,"msg":"pong"}
# 查询事件统计
./demo/edr-ctl.sh status
# → {"ok":true,"procs":532,"files":1823,"net":940,...}
# 立即终止可疑进程 (SIGKILL)
./demo/edr-ctl.sh kill 1234
# → {"ok":true,"msg":"sent sig 9 to pid 1234"}
# 发送 SIGTERM
./demo/edr-ctl.sh kill 1234 15
```
## 部署
```
# 安装 binary 及配置文件
sudo cp build/edr-agent /usr/local/bin/
sudo mkdir -p /etc/edr-agent
sudo cp config/rules.yaml /etc/edr-agent/
sudo cp config/known_hashes.txt /etc/edr-agent/
# 注册 systemd 服务
sudo cp config/edr-agent.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now edr-agent
# 检查状态
sudo systemctl status edr-agent
sudo journalctl -u edr-agent -f
```
## 输出示例
```
+----------------------------------------------------------------------+
| EDR Agent · Process + File + Network (eBPF) |
| Ctrl+C 로 종료 |
+----------------------------------------------------------------------+
TYPE TIME(s) PID USER COMM PATH / DEST
------------------------------------------------------------------------
[EXEC ] 1234.567s PID=1234 PPID=999 root evil /tmp/evil
[ALERT] R-003 | /tmp 경로 실행 (드로퍼 의심)
[CONN ] 1234.590s PID=1234 root evil → 1.2.3.4:4444
[ALERT] R-006 | 비표준 포트 아웃바운드 연결
[CORRL] 1234.590s PID=1234 evil ▶ 상관 패턴 탐지
[ALERT] R-020 | 드로퍼 C2 체인: /tmp 실행 후 아웃바운드 연결
[UNSHR] 1235.000s PID=2000 root attacker ns=[user mnt] [IN CONTAINER]
[ALERT] R-024 | 컨테이너 탈출 시도: 컨테이너 내 사용자 네임스페이스 분리
[DNS ] 1236.000s PID=3000 user curl AAAA...base64.c2.evil.tk
[ALERT] R-018c | 남용 TLD 접속 (.tk/.ml/.ga 등)
=== 세션 통계 ===
총 이벤트: 4821 (EXEC=532 FILE=1823 NET=940 MEM=312 DNS=1200 NS=14)
룰 발화 횟수
----------------------------
R-006 28 회
R-003 5 회
R-020 3 회
R-024 1 회
```
NDJSON 格式:
```
{"type":"exec","ts":1234.567,"pid":1234,"uid":0,"comm":"evil","path":"/tmp/evil","argv":["evil"],"alerts":[{"id":"R-003","name":"/tmp 경로 실행 (드로퍼 의심)","sev":"high"}]}
{"type":"correlation","ts":1234.590,"pid":1234,"comm":"evil","alerts":[{"id":"R-020","name":"드로퍼 C2 체인: /tmp 실행 후 아웃바운드 연결","sev":"critical"}]}
{"type":"ns_unshare","ts":1235.000,"pid":2000,"uid":0,"comm":"attacker","ns_inum":4026532217,"flags":"0x10020000","in_container":true,"alerts":[{"id":"R-024","name":"컨테이너 탈출 시도: 컨테이너 내 사용자 네임스페이스 분리","sev":"critical"}]}
```
## YAML 规则配置
通过 `config/rules.yaml` 无需重新编译即可修改检测规则。
```
# 根据组织环境进行修改
shell_tools:
- nc
- socat
- custom-backdoor # 추가
bind_whitelist:
- sshd
- my-internal-daemon # 추가
common_ports:
- 22
- 443
- 8443
- 9999 # 내부 서비스 포트 추가
```
## 项目结构
```
edr-agent/
├── CMakeLists.txt
├── config/
│ ├── rules.yaml # 외부 YAML 룰 설정
│ ├── known_hashes.txt # 알려진 악성 파일 SHA-256 해시 DB
│ └── edr-agent.service # systemd 서비스 유닛 파일
├── include/
│ └── common.h # BPF ↔ 유저스페이스 공유 구조체
├── bpf/
│ ├── process_monitor.bpf.c # exec/exit/ptrace/envp 훅
│ ├── file_monitor.bpf.c # 파일시스템 syscall 훅
│ ├── network_monitor.bpf.c # connect/bind 훅
│ ├── memory_monitor.bpf.c # mmap/mprotect/memfd 훅
│ ├── dns_monitor.bpf.c # sendto UDP:53 + QNAME 파싱
│ └── ns_monitor.bpf.c # unshare + PID ns 비교
├── src/
│ ├── main.cpp # 오케스트레이터 (BPF 로드·폴 루프)
│ ├── proc_tree.cpp/h # 프로세스 트리 캐시
│ ├── rules/
│ │ ├── rule_engine.cpp/h # 탐지 룰 매칭 로직
│ │ └── rule_config.cpp/h # YAML 파서 + RuleConfig 구조체
│ ├── correlation/
│ │ └── correlator.cpp/h # 슬라이딩 윈도우 상관 분석 엔진
│ ├── threat_intel/
│ │ ├── sha256.h # SHA-256 헤더 전용 구현 (외부 의존성 없음)
│ │ ├── feed_manager.cpp/h # Feodo Tracker IP + URLhaus 도메인 피드
│ │ └── hash_checker.cpp/h # SHA-256 해시 DB 조회 (R-027)
│ ├── anomaly/
│ │ └── behavior_profiler.cpp/h # EWMA + Z-점수 행동 이상 탐지 (R-028)
│ ├── action/
│ │ └── action_server.cpp/h # Unix 소켓 능동 대응 수신부
│ └── output/
│ ├── json_fmt.cpp/h # NDJSON 직렬화
│ └── http_reporter.cpp/h # libcurl HTTP POST 리포터
└── demo/
├── run_demo.sh # 전체 데모 시나리오 실행
├── 01_ldpreload.sh # R-013 LD_PRELOAD 시연
├── 02_fileless.sh # R-017/R-022 파일리스 시연
├── 03_backdoor.sh # R-004/R-006/R-007 시연
├── 04_ptrace.sh # R-014/R-019 ptrace 시연
├── 05_dns_tunnel.sh # R-018 DNS 터널링 시연
├── edr-ctl.sh # 능동 대응 제어 클라이언트
└── stress_test.sh # 스트레스 테스트 (ring_buffer 부하)
```
*源代码:https://github.com/no-carve-only-pizza/edr-agent*
标签:Bash脚本, Docker镜像, FOFA, 客户端加密