基于 ptrace 的 syscall 追踪器 & TCP 代理,专为 AWD CTF 比赛设计。监控所有 ORW(Open/Read/Write)系统调用、网络活动和进程操作,以 hex + raw 格式记录全部数据流。可选阻断危险行为(shellcode、execve、反弹 shell)。
- Ptrace 模式:通过 ptrace 包裹目标程序,追踪 40+ 种系统调用并语义化解析参数
- Embed 模式:将题目二进制嵌入 WAF,通过
memfd_create从内存执行。适用于 chroot 环境、只能写入单个文件的靶机 - Proxy 模式:TCP 代理,双向抓取流量,输出 pcap 文件
- WAF 引擎:关键字黑名单、execve 拦截、反弹 shell 检测
- 日志格式:每次数据传输同时输出 hex dump 和 raw 表示
- Web 日志查看器:单文件 HTML,支持筛选、搜索、一键复制 payload
- 零依赖:静态编译,无配置文件,所有参数编译期确定
- 多进程追踪:自动跟踪 fork/clone/vfork 创建的子进程
# 编译(默认 ptrace 模式,追踪 /home/ctf/pwn)
make
# 指定目标程序
make ELF_PATH=/home/ctf/pwn
# 编译 proxy 模式
make MODE=proxy LISTEN_PORT=9999 FORWARD_PORT=10001
# Embed 模式:将二进制嵌入 WAF(适用于 chroot / 只能写一个文件的靶机)
make MODE=embed ELF_PATH=./original_pwn
cp pwn_waf /home/ctf/pwn # 直接替换原始二进制
# 启用 WAF 拦截
make ENABLE_WAF=1 BLOCK_EXECVE=1 BLOCK_REVERSE_SHELL=1
# 运行(零参数,直接追踪编译时指定的 ELF)
./pwn_waf
# 传递参数给目标程序
./pwn_waf arg1 arg2| 变量 | 默认值 | 说明 |
|---|---|---|
MODE |
ptrace |
工作模式:ptrace、embed 或 proxy |
ELF_PATH |
/home/ctf/pwn |
目标程序路径(ptrace 模式) |
ARCH |
64 |
架构:32 或 64 |
AUTO_RESTART |
0 |
目标退出后自动重启 |
LISTEN_PORT |
9999 |
代理监听端口 |
FORWARD_PORT |
10001 |
代理转发端口 |
FORWARD_HOST |
127.0.0.1 |
代理转发地址 |
SAVE_PCAP |
1 |
proxy 模式保存 pcap |
LOG_PATH |
/tmp/waf |
日志目录 |
TIMEOUT |
60 |
连接超时秒数(0=禁用) |
ENABLE_WAF |
0 |
启用 WAF 拦截 |
BLOCK_EXECVE |
0 |
拦截 execve/execveat |
BLOCK_REVERSE_SHELL |
0 |
拦截反弹 shell |
DEBUG |
0 |
调试输出到 stderr |
浏览器打开 viewer.html,拖入 .log 文件即可分析。
- 分类筛选:按类别过滤(ORW / 网络 / 进程 / 内存 / 文件操作)
- 单项筛选:按具体 syscall 名称过滤(如
read、openat),显示调用次数 - 一键复制:Hex 字节、Python
b'...'格式、Raw 文本 - 告警高亮:WAF 匹配项红色标记
- 全文搜索:跨所有 syscall 数据搜索
- 统计面板:syscall 次数、数据量、告警数
================================================================================
[14:32:05.123] [PID:1234] SESSION START (tracing /home/ctf/pwn)
================================================================================
--- SYSCALL #1 ----------------------------------------------------------------
[14:32:05.124] [PID:1234] read(fd=0 <stdin>, buf=0x7ffd1234, count=0x80)
[14:32:05.124] [PID:1234] DATA IN | fd=0 <stdin> | len=128 (0x80)
Hex:
00000000: 41 41 41 41 2f 62 69 6e 2f 73 68 00 ff ff ff ff |AAAA/bin/sh.....|
Raw:
AAAA/bin/sh\x00\xff\xff\xff\xff
*** ALERT: keyword_match "/bin/sh" ***
--- SYSCALL #2 ----------------------------------------------------------------
[14:32:05.125] [PID:1234] write(fd=1 <stdout>, buf=0x404000, count=0x08)
[14:32:05.125] [PID:1234] DATA OUT | fd=1 <stdout> | len=8 (0x08)
Hex:
00000000: 57 65 6c 63 6f 6d 65 0a |Welcome.|
Raw:
Welcome\n
================================================================================
[14:32:05.128] [PID:1234] SESSION END | status=0 | duration=0.005s
================================================================================
main.c — 入口,模式分发
tracer.c/.h — ptrace 引擎,多进程追踪
proxy.c/.h — TCP 代理,select() 循环
logger.c/.h — hex + raw 日志输出,会话管理
waf.c/.h — WAF 规则,关键字黑名单,syscall 拦截
utils.c/.h — 子进程内存读取,fd 描述,解码辅助
pcap_writer.c/.h — 轻量 pcap 写入(不依赖 libpcap)
syscall_table.h — x86_64 系统调用号映射表
viewer.html — Web 日志分析器
Makefile — 构建系统
demo.c — 测试程序
| 类别 | 系统调用 |
|---|---|
| ORW | read, write, open, openat, pread64, pwrite64, readv, writev, sendfile, splice, tee, copy_file_range |
| 网络 | socket, connect, bind, listen, accept, sendto, recvfrom, sendmsg, recvmsg |
| 进程 | execve, execveat, fork, vfork, clone, clone3 |
| 内存 | mmap, mprotect(PROT_EXEC 时告警) |
| 文件 | close, dup/dup2/dup3, lseek, unlink, rename, chmod, chown, mkdir, rmdir, symlink, link, readlink |
# 1. 编译(在本地或靶机上)
make ELF_PATH=/home/ctf/pwn ENABLE_WAF=1 BLOCK_EXECVE=1
# 2. 备份原始程序
cp /home/ctf/pwn /home/ctf/pwn.bak
# 3. 部署 waf(替换原程序或用 xinetd 指向 pwn_waf)
cp pwn_waf /home/ctf/
# 4. 查看日志
cat /tmp/waf/*.log适用场景:靶机目录只允许写入 pwn 一个文件,且运行环境是 chroot 的。
# 1. 先把题目原始二进制拉到本地
scp user@target:/home/ctf/pwn ./original_pwn
# 2. 编译 embed 模式 —— 将原始二进制嵌入 WAF
make MODE=embed ELF_PATH=./original_pwn ENABLE_WAF=1
# 3. 上传替换原始二进制(pwn_waf 就是新的 pwn)
scp pwn_waf user@target:/home/ctf/pwn
# 靶机上 xinetd/socat 执行 /home/ctf/pwn 时:
# → pwn_waf 通过 memfd_create 将嵌入的二进制写入内存
# → 通过 fexecve 从内存执行(不需要写磁盘,不需要 /proc)
# → ptrace 追踪所有 syscall 并记录日志原理:编译时用 hexdump 将目标二进制转为 C 字节数组嵌入 pwn_waf,运行时通过 memfd_create + fexecve 直接从内存执行,无需写入任何文件。
MIT