beelzebub-labs/azazel
GitHub: beelzebub-labs/azazel
基于 eBPF 的容器运行时静默监控工具,零开销地实时捕获进程、文件、网络事件,专用于恶意软件分析沙箱和 AI 代理行为审计。
Stars: 80 | Forks: 9

# Azazel
*基于 eBPF 的容器化运行时静默观察器,专为恶意软件分析沙箱和 Agentic AI 监控而构建。*
Azazel 可以附加到任何正在运行的 Docker 容器,并实时捕获每一个 syscall、文件访问、网络连接和进程事件——对目标零开销。无需代码注入。容器内无代理。无需重启。
**一个工具,两种用途:**
- **恶意软件分析**:将样本投放进隔离容器,让 Azazel 监控其一举一动,获取完整的取证报告
- **Agentic AI 监控**:附加到任何 AI 代理容器,观察它在运行时*实际*做了什么,而不是它声称做了什么:触摸了哪些文件,派生了哪些进程,调用了哪些端点
## 在这两种情况下,目标都不知道自己正在被观察。
## 架构

## 捕获内容
| 类别 | 事件 | 详情 |
|----------|--------|---------|
| **Process** | `process_exec`, `process_exit`, `process_clone` | 完整进程树:filename, argv, exit codes, clone flags, parent PID |
| **File** | `file_open`, `file_write`, `file_read`, `file_unlink`, `file_rename` | Pathnames, flags, byte counts |
| **Network** | `net_connect`, `net_bind`, `net_listen`, `net_accept`, `net_sendto`, `net_dns` | IPv4/IPv6 地址,端口,通过 `udp_sendmsg` 上的 kprobe 检测 DNS |
| **Security** | `mmap_exec`, `ptrace`, `module_load` | W+X 内存映射,进程注入尝试,内核模块加载 |
syscall 入口共有 **19 个 hook 点** total tracepoints,以及用于 DNS 检测的 kprobe。
## 为什么选择 Azazel?
无论您是在分析恶意软件还是 AI 代理,问题都是一样的:*这个东西在那个容器里到底在做什么?*
- **Attach-first** — 通过基于 cgroup 的过滤挂载到运行中的容器,无需重启,目标内部无需插桩
- **Zero footprint** — 单个静态 Go 二进制文件在容器外运行;目标从不知道自己正在被观察
- **CO-RE** — 通过 BTF 和 `vmlinux.h` 实现“一次编译,到处运行”,无需重新编译即可跨内核版本工作
- **JSON-native** — NDJSON 输出(每行一个事件)可直接用于 `jq`、Elasticsearch、Splunk 或您自己的 pipeline
- **Built-in heuristics** — 自动警报:从 `/tmp` 执行、敏感文件访问(`/etc/shadow`, `/proc/self/mem`)、ptrace、W+X mmap 以及内核模块加载
## 快速开始
### 前置条件
- Linux kernel **5.8+** 且启用 `CONFIG_DEBUG_INFO_BTF=y`
- Docker (用于开发容器和沙箱)
- 就这些
验证您的内核:
```
# BTF 支持(必需)
ls /sys/kernel/btf/vmlinux
# Kernel 版本
uname -r
```
### 使用 Docker 构建 (推荐)
```
# Clone
git clone https://github.com/beelzebub-labs/azazel.git
cd azazel
# 构建 dev container
make docker-dev
# 进入它(特权模式,带有 host PID/cgroup namespace)
make docker-dev-run
# 在 container 内部:
make vmlinux # Generate kernel type definitions
make generate # Compile BPF C → Go bindings
make build # Build the binary
```
### 运行
```
# 追踪所有内容,输出到 stdout
sudo ./bin/azazel
# 追踪所有内容,以 pretty JSON 保存到文件
sudo ./bin/azazel --output events.json --pretty
# 仅追踪特定 container
sudo ./bin/azazel --container
--output events.json
# 列出运行中的 container
sudo ./bin/azazel list-containers
```
### 运行测试套件
```
# 在 dev container 内部
make test
```
这将构建二进制文件,启动 tracer,运行恶意软件行为模拟器,然后验证是否捕获了所有预期的事件类型。
## 用例
### 恶意软件分析沙箱
将样本放入隔离容器中,获得其行为的完整内核级可见性:它触摸了哪些文件,派生了哪些进程,连接到哪里,是否尝试注入或权限提升。
```
# 启动 sandbox
docker compose up -d
# 将 sample 复制到 sandbox container
docker cp ./samples/malware.elf sandbox:/tmp/sample
# 将 Azazel 附加到 sandbox
sudo ./bin/azazel --container sandbox --output events.json
# 执行 sample
docker exec sandbox /tmp/sample
# 检查 trace
cat output/events.json | jq .
```
### Agentic AI 监控
AI 代理日益自主化——它们调用工具、派生子进程、读取文件、访问外部 API。Azazel 在内核级别为您提供基本事实的可观察性,独立于代理记录或报告的内容。
```
# 附加到你正在运行的 AI agent container
sudo ./bin/azazel --container --output agent_trace.json --pretty
# 实时流式传输 events 并按类型过滤
sudo ./bin/azazel --container --stdout | jq 'select(.event_type == "net_connect")'
```
您可以实时过滤以回答如下问题:
- 代理正在连接哪些外部主机?
- 它是否正在读取其预期工作目录之外的文件?
- 它是否正在派生意外的子进程?
- 是否有任何访问敏感系统路径的尝试?
## 输出格式
每个事件都是一行 JSON (NDJSON):
```
{
"timestamp": "2025-01-15T14:30:22.123456789Z",
"event_type": "process_exec",
"pid": 12345,
"tgid": 12345,
"ppid": 12300,
"uid": 0,
"gid": 0,
"comm": "bash",
"cgroup_id": 6789,
"container_id": "a1b2c3d4e5f6",
"filename": "/tmp/suspicious_binary",
"args": "/tmp/suspicious_binary"
}
```
```
{
"timestamp": "2025-01-15T14:30:22.234567890Z",
"event_type": "net_connect",
"pid": 12345,
"tgid": 12345,
"ppid": 12300,
"uid": 0,
"gid": 0,
"comm": "curl",
"cgroup_id": 6789,
"container_id": "a1b2c3d4e5f6",
"sa_family": "AF_INET",
"dst_addr": "93.184.216.34",
"dst_port": 443
}
```
当 tracer 关闭时 (Ctrl+C 或 SIGTERM),它会向 stderr 打印摘要:
```
========================================
Azazel Summary
========================================
Total events: 1847
Event counts:
file_open 892
file_write 312
process_exec 47
net_connect 23
...
Security Alerts (3):
[MEDIUM] execution from suspicious path: /tmp/suspicious_binary (pid=12345 comm=bash)
[MEDIUM] sensitive file access: /etc/shadow (pid=12346 comm=cat)
[CRITICAL] memory mapped as WRITE+EXEC (possible code injection/unpacking) (pid=12347 comm=malware)
========================================
```
## 使用 Docker Compose 设置沙箱
包含的 `docker-compose.yml` 设置了一个完整的分析环境:

```
# 启动 sandbox
docker compose up -d
# 将 sample 复制到 sandbox
docker cp ./samples/malware.elf sandbox:/tmp/sample
# 执行它
docker exec sandbox /tmp/sample
# Events 被写入 ./output/events.json
cat output/events.json | jq .
```
### 自动化分析
```
# 端到端分析 sample:hash → trace → 报告
sudo ./analyze.sh ./samples/malware.elf 30
```
这会产生:
- `output/events_.json` — 原始事件流
- `output/report_.md` — Markdown 报告,包含哈希、事件摘要、网络连接和安全警报
## CLI 参考
```
Usage:
azazel [flags]
azazel [command]
Commands:
list-containers List running containers
version Print version
Flags:
-c, --container strings Container ID(s) to filter (can specify multiple)
-o, --output string Output file path (default: stdout)
--pretty Pretty-print JSON output
--stdout Also print to stdout when --output is set
-v, --verbose Verbose logging
--no-summary Disable summary on exit
-h, --help Help
```
## 启发式警报
Azazel 自动标记可疑行为:
| 警报 | 严重程度 | 触发条件 |
|-------|----------|---------|
| Suspicious exec path | Medium | 从 `/tmp/`, `/dev/shm/`, `/var/tmp/` 执行 |
| Suspicious tool | Medium | `wget`, `curl`, `nc`, `python`, `base64`, `memfd:` |
| Sensitive file access | Medium | `/etc/passwd`, `/etc/shadow`, `/etc/sudoers`, `/etc/ssh/`, `/proc/self/maps`, `/proc/self/mem`, `/etc/ld.so.preload` |
| Ptrace | High | 任何 `ptrace` syscall (进程注入 / 调试) |
| Kernel module load | High | 任何 `finit_module` syscall |
| W+X mmap | Critical | 内存同时映射为 WRITE+EXEC (代码注入, 解包) |
## 开发
### 开发容器
所有内容都在单个 Docker 容器内构建和运行,包含 Go, clang, libbpf 和 bpftool:
```
make docker-dev # Build the dev image
make docker-dev-run # Enter it (privileged + host namespaces)
```
### 构建工作流
```
# 在 dev container 内部:
make vmlinux # Generate vmlinux.h from host kernel BTF
make generate # bpf2go: compile BPF C → Go bindings
make build # Build the Go binary
make test # Full test cycle
```
### 检查内核兼容性
```
make check-kernel
```
## 故障排除
| 问题 | 解决方案 |
|---------|----------|
| 加载 BPF 时 `operation not permitted` | 容器必须以 `--privileged --pid=host --cgroupns=host` 运行 |
| `vmlinux.h: No such file` | 运行 `make vmlinux` (需要 `/sys/kernel/btf/vmlinux`) |
| `kernel doesn't support BTF` | 宿主内核需要 `CONFIG_DEBUG_INFO_BTF=y` — 检查 `ls /sys/kernel/btf/vmlinux` |
| Ring buffer map 创建失败 | 内核必须是 5.8+,用 `uname -r` 检查 |
| `failed to attach tracepoint` | 某些 tracepoint 并非在所有内核上都存在 — tracer 会记录警告并继续 |
| 未捕获到事件 | 验证 tracer 是否正在运行 (`ps aux \| grep azazel`),检查测试活动是否发生在 tracer 启动*之后* |
## 技术栈
| 组件 | 技术 |
|-----------|-----------|
| Language | Go 1.24+ |
| eBPF library | [cilium/ebpf](https://github.com/cilium/ebpf) v0.17+ |
| BPF code gen | `bpf2go` (CO-RE, BTF-based) |
| BPF programs | C,使用 clang 编译,使用 `vmlinux.h` |
| CLI | [cobra](https://github.com/spf13/cobra) |
| Output | NDJSON (每行一个 JSON 对象) |
| Container | Docker,使用 docker-compose 进行沙箱编排 |
## 贡献
欢迎贡献。请先开一个 issue 讨论您想更改的内容。
```
# Fork、clone,然后:
make docker-dev
make docker-dev-run
# hack hack hack
make test
```
## 许可证
GPL-2.0 — 详情见 [LICENSE](LICENSE)。
BPF 程序根据 GPL-2.0 授权(eBPF helper 访问所需)。用户空间 Go 代码也是 GPL-2.0。标签:Agent AI 监控, API集成, CIDR输入, DAST, DNS 解析, Docker 安全, Docker镜像, Go 语言, HTTP/HTTPS抓包, HTTP工具, IP 地址批量处理, Linux 内核, syscall 监控, Web截图, 反作弊, 可观测性, 安全渗透, 客户端加密, 容器安全, 态势感知, 恶意软件分析, 日志审计, 沙箱, 结构化查询, 网络安全审计, 网络流量分析, 自动化安全, 请求拦截, 进程审计, 零侵入