
简介AWD攻防赛脚本集合是面向AWD对抗赛参赛者及安全运维人员的实用工具包聚焦漏洞利用、权限维持、日志清理与应急响应等核心环节能够帮助选手快速提升攻防效率。压缩包共33个文件涵盖Python自动化脚本、PHP类webshell及防护脚本、可执行程序、pyc编译模块和说明文档等整体大小约3.14MB结构清晰便于按需调用。脚本集按攻击与防御两个方向组织攻击侧支持批量传shell、自动获取Flag、不死马生成与免杀变形防御侧提供WAF规则、文件与日志监控以及不死马查杀方案并附带Web日志安全分析工具基本覆盖AWD赛前准备和实战对抗的主要场景。已有408人学习下载适合正处于备赛阶段的中高级CTF选手也可作为企业内部攻防演练的参考脚本库。各模块均可直接部署或二次改造能够有效缩短脚本编写时间是一份即取即用的攻防武器库。1. AWD攻防赛脚本集合先想清楚拿分逻辑再动手AWDAttack With Defense攻防赛里脚本集合.7z这类压缩包几乎是每支队伍工具箱里的标配。它解决的核心问题不是“帮你打下一个靶标”而是把攻防两端的重复劳动变成可复用的轮子攻击侧批量提交flag、批量打同一个漏洞点防御侧盯文件完整性、出事快速回滚。适合两类人一类是刚打完一两场AWD、觉得手忙脚乱的新手另一类是准备从CTF单兵模式转向团队攻防的从业者。先说句反直觉的结论脚本集合本身赢不了比赛真正决定胜负的是你拿到压缩包后怎么编排、怎么调度、怎么应对赛场上的突发状态。2. 搭好运行环境.7z解压、Python版本与依赖先让脚本能跑2.1 Linux下解压7z文件先装p7zip再动手拿到“AWD攻防赛脚本集合.7z”的第一件事不是看代码而是把它解出来。很多选手在赛场上一紧张直接在服务器上敲tar -xzf结果报错gzip: stdin: not in gzip format这是因为7z和tar.gz根本不是同一种封装格式。常见做法是装p7zip工具集然后用7z命令解压# Ubuntu/Debian 系 apt-get install -y p7zip-full # CentOS/RHEL 系用 EPEL yum install -y p7zip p7zip-plugins # 解压到当前目录 7z x AWD攻防赛脚本集合.7z -o./awd_scripts命令说明7z x是解压并保留目录结构-o指定输出目录注意-o后面没有空格这是p7zip的参数习惯写成-o ./awd_scripts反而会报错。解压完后先看目录结构再动手。一个典型的AWD脚本集合通常包含这几类内容一是submit_flag.py或类似的flag提交脚本二是针对常见CMS的批量利用exp三是文件监控脚本四是备份恢复脚本五是辅助的shell脚本。如果解出来发现只有孤零零的两个py文件说明作者没有做整理你需要自己补上调度层。2.2 Python依赖与虚拟环境别把赛场上的系统环境搞坏AWD赛场的靶机往往是公用的你把依赖装到系统全局万一和其他工具冲突整个环境就废了。我的习惯是每个脚本集合都建独立虚拟环境cd awd_scripts # 创建虚拟环境python3 -m venv 是标准做法 python3 -m venv venv # 激活环境 source venv/bin/activate # 安装依赖requirements.txt 不是每个包里都有没有就手动装 pip install requests paramiko关于依赖这里有个普遍踩坑点脚本集合里如果带了paramiko说明作者大概率写了SSH批量操作的逻辑如果带了requests那就是HTTP交互为主。实际比赛里很多flag服务是HTTP接口requests基本是刚需。如果requirements.txt存在直接pip install -r requirements.txt就行。但注意安装源的问题赛场内网可能访问不了公网PyPI提前准备一个本地镜像或wheel包目录比临时配源靠谱得多。2.3 先跑通一个最小用例把脚本从“能看”变成“能用”环境搭好后不要急着把所有脚本都跑一遍先挑一个最简单的、不依赖外部服务的脚本做冒烟测试。比如flag提交脚本通常只需要一个靶标地址和一个token先本地起一个测试HTTP服务验证逻辑。# 方式一用 python 自带模块起个临时服务 python3 -m http.server 8080 # 方式二如果脚本是requests写的用nc快速模拟一个提交接口 nc -lvnp 8080这两种方式都能让你在无风险环境里验证脚本行为。python3 -m http.server适合验证GET逻辑nc -lvnp 8080能看到脚本发出的完整HTTP报文适合调试POST提交内容。跑通之后再把靶标地址换成真实的AWD靶机。3. 攻击侧脚本从flag批量提交到自动化漏洞利用3.1 flag批量提交把正则提取和HTTP上报串成一条线AWD比赛里拿flag只是第一步把flag提交到裁判系统换成得分才是目的。手动提交一两台机器还行几十台靶机同时出flag时手速完全跟不上。批量提交脚本的逻辑其实很简单从指定路径或标准输出读取内容用正则把flag格式匹配出来再向裁判系统的提交接口发HTTP请求。#!/usr/bin/env python3 import re import requests import sys # 比赛组织方给的提交接口地址和token一般在比赛文档里 SUBMIT_URL http://flag.example.com/submit TOKEN your_team_token_here # 常见flag格式flag{...}、FLAG{...}、CTF{...}按比赛规则调整 FLAG_PATTERN r[A-Za-z]{[^}]} def extract_and_submit(file_path): with open(file_path, r, encodingutf-8, errorsignore) as f: content f.read() flags re.findall(FLAG_PATTERN, content) if not flags: print([-] 未匹配到flag) return for flag in flags: payload {token: TOKEN, flag: flag} try: # 提交接口一般要求POSTdata用表单格式 resp requests.post(SUBMIT_URL, datapayload, timeout10) if resp.status_code 200: print(f[] 提交成功: {flag} - {resp.text.strip()}) else: print(f[!] 提交失败: {flag} - HTTP {resp.status_code}) except requests.exceptions.RequestException as e: print(f[-] 网络异常: {flag} - {e}) if __name__ __main__: if len(sys.argv) ! 2: print(f用法: {sys.argv[0]} 文件路径) sys.exit(1) extract_and_submit(sys.argv[1])这段代码的关键逻辑有两点一是用re.findall一次把所有匹配到的flag全拎出来而不是只取第一个二是提交时把token放在data里而不是URL参数中避免token出现在访问日志里。timeout10是必须加的没有超时限制的requests在靶机掉线时会卡很久批量跑几十台就是灾难。实际比赛里提交接口的字段名未必是token和flag有的是team_token有的是value。拿到脚本后先改这一个配置再跑不然全部提交失败。3.2 批量打点把单个exp改装成可横向利用的pipeline脚本AWD最理想的得分方式是找到一个漏洞点然后对全场所有同网段目标批量利用。这个场景用pipeline脚本语法描述非常合适——从资产枚举到漏洞利用再到flag提取每一步的输出作为下一步的输入。#!/bin/bash # 批量打点pipeline先扫存活再打exp最后收集flag # 用法: ./pipeline.sh 目标段 TARGET_NET$1 # 第一步用nc快速探测80/8080端口的存活主机 # -z 只扫描不发送数据-w 1是每个端口超时1秒 for ip in $(seq 1 254); do nc -z -w 1 ${TARGET_NET}.${ip} 80 2/dev/null echo ${TARGET_NET}.${ip}:80 alive_http.txt nc -z -w 1 ${TARGET_NET}.${ip} 8080 2/dev/null echo ${TARGET_NET}.${ip}:8080 alive_http.txt done # 第二步对存活主机跑批量利用输出保存到exp_out目录 # 这里假设你的exp脚本是 exploit.py接收 -t 目标参数 while read line; do ip$(echo $line | cut -d: -f1) python3 exploit.py -t $ip --output ./exp_out/$ip.txt done alive_http.txt # 第三步把所有exp输出合并交给flag提交脚本 cat ./exp_out/*.txt all_flags.txt python3 submit_flag.py all_flags.txt这个脚本的关键是稳而不是快。nc -z -w 1把单个目标的探测超时控制在1秒整个C段扫描能在几分钟内完成不会因为个别主机不响应而卡住。批量跑exp时输出按IP隔离到独立文件方便赛后回溯哪个目标打成了、哪个没打成。这里要提醒一句写批量利用脚本时一定要在exp内部处理异常。如果exploit.py遇到无漏洞目标直接抛出异常退出pipeline会中断后面的目标全遭殃。让exp捕获异常后写一个空文件继续跑比用bash的set -e强制中断靠谱得多。3.3 定时调度用crontab和nohup把脚本挂成常驻轮子AWD的漏洞利用时机很重要同一个小洞别人也在打洞被补上你就没机会了。常见做法是把攻击脚本做成循环挂到后台定时执行。# 循环跑攻击脚本每次间隔60秒日志写到 attack.log nohup python3 attack_loop.py --interval 60 attack.log 21 # 更细粒度用crontab每分钟执行一次扫描 crontab -e # 追加一行注意crontab环境变量和交互shell不同用绝对路径 * * * * * /usr/bin/python3 /root/awd_scripts/sweep_and_exp.py /root/awd_scripts/cron.log 21nohup的是追加写日志21把标准错误合并到标准输出这样exp里的print和traceback都能落到同一个文件。crontab里频繁踩坑的是环境变量问题直接用python3可能找不到因为crontab的PATH不包含/usr/local/bin用绝对路径是止损手段。4. 防御侧脚本文件监控与备份回滚是保分的关键4.1 文件完整性监控用哈希轮询盯住web目录AWD的防守本质是“别让对方把你的服务搞挂”。攻击方拿到权限后最常见的动作是改你web目录下的文件——要么植入后门要么删掉你的业务功能。文件监控脚本就是干这个的先对受保护目录做一次基线快照之后周期性比对发现异常立刻告警。#!/usr/bin/env python3 import hashlib import os import pickle import time WATCH_DIR /var/www/html BASELINE_FILE ./baseline.db # 排除目录session文件改动频繁不纳入监控干扰项 SKIP_DIRS {./tmp, ./cache, /var/www/html/session} def file_hash(path): # 分块读取避免大文件一次性载入内存 h hashlib.sha256() with open(path, rb) as f: for chunk in iter(lambda: f.read(4096), b): h.update(chunk) return h.hexdigest() def build_baseline(): baseline {} for root, dirs, files in os.walk(WATCH_DIR): # 就地修改dirs列表剪枝跳过目录 dirs[:] [d for d in dirs if os.path.join(root, d) not in SKIP_DIRS] for name in files: full os.path.join(root, name) if any(skip in full for skip in SKIP_DIRS): continue baseline[full] file_hash(full) return baseline def check(): # 首次运行需要 -i 参数生成基线这里用pickle落盘 if not os.path.exists(BASELINE_FILE): print([-] 基线不存在先运行 build 模式) return with open(BASELINE_FILE, rb) as f: baseline pickle.load(f) current build_baseline() for path, digest in baseline.items(): if path not in current: print(f[!] 文件被删除: {path}) elif current[path] ! digest: print(f[!] 文件被修改: {path}) if __name__ __main__: import sys if len(sys.argv) 1 and sys.argv[1] build: with open(BASELINE_FILE, wb) as f: pickle.dump(build_baseline(), f) print(f[] 基线已保存到 {BASELINE_FILE}) else: check()这里有两个细节值得展开。一是用os.walk时dirs[:] [...]的写法能剪枝跳过session目录避免大量误报——很多不熟悉walk机制的人直接在循环里continue结果目录还是被递归进去了。二是哈希算法用sha256而不是md5虽然慢一点但防护级别完全不同AWD赛场上对手用哈希碰撞伪造文件虽然不多见但值得防一手。监控脚本用crontab或supervisor挂起来每30秒跑一次。告警只输出到日志还不够最好配合一个简单动作一旦发现关键文件被改立即执行备份恢复脚本。4.2 备份与回滚给被打穿的站点留后悔药文件监控只能发现问题真正能保住分数的是回滚能力。AWD比赛里站点被打穿业务功能被恶作剧替换成乱码页面这个时候你需要的是一张“后悔药”——赛前做好的完整备份。备份脚本用rsync或tar都行我习惯用tar打时间戳包。#!/bin/bash # 备份web目录到 /backup保留最近5份 BACKUP_DIR/backup WEB_ROOT/var/www/html TIMESTAMP$(date %Y%m%d_%H%M%S) FILENAMEweb_${TIMESTAMP}.tar.gz # 打包时排除日志和session这两个目录恢复过去反而是累赘 tar czf ${BACKUP_DIR}/${FILENAME} \ --exclude${WEB_ROOT}/logs \ --exclude${WEB_ROOT}/session \ -C /var/www \ html # 清理30天前的旧备份 find ${BACKUP_DIR} -name web_*.tar.gz -mtime 30 -delete echo [*] 备份完成: ${BACKUP_DIR}/${FILENAME}回滚动作要设计成一键式的比赛时没有时间让你解压、比对、再手动复制。常见的回滚方式是把备份解压到一个临时目录然后整个替换web目录#!/bin/bash LATEST$(ls -t /backup/web_*.tar.gz | head -1) tar xzf ${LATEST} -C /tmp/web_restore # 用rsync做增量同步--delete删除目标端多余文件 rsync -a --delete /tmp/web_restore/html/ /var/www/html/rsync -a --delete是回滚的关键--delete会删掉目标目录里源端没有的文件这意味着攻击者植入的后门文件会被一并清掉。如果只用cp覆盖后门会原封不动留在那儿。4.3 权限维持与对抗理解对手才能守住阵地AWD的防御不只是被动监控还要主动理解攻击者的手法。最常见的攻击方脚本穿插在web目录里通过混淆代码隐藏自身。防守方要做的是一旦发现可疑文件立刻查它的内容、看它的连接目标、断开它的外联通道。常见的可疑文件特征包括文件名和正常业务难以区分比如wp-admin.php混在WordPress目录里、文件内容里出现eval、base64_decode、system等危险函数、文件修改时间集中在比赛开场时段。我一般会写一个快速扫描命令把最近10分钟内新增和修改的文件全列出来# 找出最近10分钟内被修改的php文件按时间倒序 find /var/www/html -name *.php -mmin -10 -exec ls -lt {} # 直接查看文件头部内容判断是否被插入了恶意代码 head -c 500 /var/www/html/wp-admin.php这两个命令在比赛里救人无数第一条能让你在攻击后门刚开始生效时就发现它第二条能让你快速判断这个文件是正常业务还是被改过的“木马”。脚本集合里的监控工具再强也替代不了人工对这个过程的判断。5. AWD脚本常见翻车与避坑从弹shell失败到flag提交4435.1 现象脚本在本地跑得好好的赛场上批量执行全部超时本地复现没问题、一上靶场就超时是AWD脚本最常见翻车现场。原因几乎都是网络环境差异本地是直连赛场上靶机之间有防火墙策略或者目标服务本身限速。你批量跑50台每台等5秒超时一轮下来就是4分钟比赛节奏完全被打乱。解决思路是给所有网络操作压到极短超时并增加失败快速跳过逻辑。requests里timeout2socket连接用settimeout(1)。另外并发一定要做——用线程池把本来串行的请求改成最多10个并发整体耗时能压到原来的十分之一。5.2 现象flag提交返回403服务端拒绝接收提交接口返回403最常见的原因是token没带对或者带了多余的空格。我自己踩过从比赛文档里复制token时末尾粘了个看不见的换行符服务端直接拒收。另一个隐蔽原因是赛方提交接口要求header里带User-Agent而脚本的默认UA被WAF拦了。每次跑批量提交前先用curl手动提交一条做验证确认通了再上全量脚本。5.3 现象文件监控脚本疯狂误报把垃圾信息刷满日志监控脚本上线第一天就刷了上千条告警仔细看全是session文件或者缓存文件在变动。原因很简单基线建立的时候没有排除动态目录。session文件每次用户访问都会更新把这类高频变化文件纳入hash比对误报率直接拉满。解决办法是重建基线时把SKIP_DIRS列表写完整缓存、临时文件、日志目录、session目录全部排除然后让脚本静默跑10分钟观察误报是否清零。5.4 现象手写正则把flag截断了批量提交全部失败赛场上的flag格式不统一有的带横杠、有的带下划线、有的flag内容里本身就有}。我用过[A-Za-z]{[^}]}这种正则结果遇到flag内容里含}时直接截断把后半截漏掉。这是正则贪婪匹配导致的。安全的做法是用非贪婪匹配[A-Za-z]{.*?}同时加上re.DOTALL让.能匹配换行。如果比赛方公布了flag格式优先用精确正则别用通配。5.5 现象crontab里脚本不执行但手动跑没问题这个坑和Windows下pycharm配置脚本环境变量、或者“无法将某命令识别为cmdlet”之类的报错本质上是同一个问题非交互环境的PATH和交互shell不一样。crontab默认PATH很精简python3都不一定找得到。解决方式写在crontab里用绝对路径、在脚本开头export PATH。另外crontab的任务执行结果默认通过邮件发到root邮箱根本没日志一定要手动重定向到文件。crontab里不写 xxx.log 21等于让脚本在黑匣子里跑出了事只能靠猜。这个坑赛场上经常让人白丢分。5.6 现象不死马互杀自己把自己后门删了防守脚本里带了查杀功能结果把队友故意放的后门也删了。这不是技术问题是协作问题。AWD是团队赛攻防双方的动作必须同步谁负责植入、谁负责防守、哪些路径是“友军”绝对不能碰的赛前要写在作战手册里。防御脚本可以加白名单机制把队友的后门路径加进去不然监控发现一个删一个队友辛苦打下的据点全被自己人端了。6. 把脚本集合改造成自己的AWD工具箱三个值得做的事第一件事是把所有脚本的配置项外置。AWD脚本集合最怕写死IP、token、提交地址、监控目录全硬编码在代码里换一场比赛就要改一堆地方。把配置抽到一个config.py或.env文件脚本只读配置不写配置比赛时你只需要改一个文件就能适配新赛制。第二件事是给脚本加统一日志和退出码。写pipeline脚本时每个子脚本的退出码决定了整条流水线能不能继续跑。返回0表示成功返回1表示业务失败比如没找到flag返回2表示环境错误比如依赖缺失bash侧通过判断退出码决定要不要中断。加了这一层整个工具链从“能跑”变成“可靠”。我见过有人在pipeline里用set -e让任何非零退出码都中断结果一个exp对无漏洞目标报错后面的批量任务全停了这是典型的因为没设计退出码而导致的整条线翻车。第三件事是在本地搭一台模拟靶标做演练。AWD脚本集合不是拿回来就能上战场的你至少要有一台自己的仿真环境起一个Web服务放几个假flag、故意留一个漏洞、跑一遍攻击脚本、再跑一遍监控和回滚脚本验证整个流程闭环。这个模拟不需要多复杂一台虚拟机跑LNMP就够了关键是验证脚本之间衔接对不对。第一人称的教训是我曾经比赛前只测了攻击脚本没测回滚脚本结果真到防守时发现备份恢复的动作比预期慢了三倍原因是tar包里有大量session文件恢复时要先删旧文件再同步现场操作花了十分钟——比赛早结束了。从那以后我的工具箱规则是任何脚本没在模拟靶标上跑通三遍就不允许带进赛场。希望帮到你。本文还有配套的精品资源点击获取