AI自动解CTF:从流水线搭建到实战翻车实录

发布时间:2026/10/20 21:20:43
AI自动解CTF:从流水线搭建到实战翻车实录
这两天我在练习平台上刷CTF脑子里突然冒出一个有点中二的想法如果我全程不用手把这些题丢给AI去解能做到什么程度当天我花了一个小时把常用的几个开源模型串成一条流水线又在本地靶场上挑了二十多道题跑了一遍。结果很有意思——有一半的题确实被AI“自动”搞定了但也有一堆让我哭笑不得的翻车现场。这篇文章就是那几天的完整记录包括流水线怎么搭、哪些题适合丢给AI、哪些坑我替你踩过了。如果你也在玩CTF或者对大模型做自动化分析感兴趣这篇东西应该能给你省不少时间。我先把最核心的结论放这儿纯无人值守、全自动拿高分的AI目前不存在。但把AI当成“一个聪明但经常胡说八道的新人选手”让它先做一遍你做审核和善后效率会提升得非常明显。1. 动手前先把逻辑理清AI在CTF里到底能干什么1.1 五类题型的能力匹配表CTF常见的题型大概分五类Web、Crypto、Reverse、Pwn和Misc。不同题型考察的点和AI的“体质”匹配度差别很大我刚开始是见题就丢给AI结果浪费了不少时间和API额度。跑了几轮之后我给自己做了一个能力匹配表现在翻出来给你们看看题型AI擅长的地方AI明显不擅长的地方自动化解题优先级Misc编码识别、隐写工具链调用、字符串分析、流量包常见套路需要人眼反复观察的视觉细节、复杂的空间想象最高Crypto已知算法模式识别、数学推导、脚本生成需要深度构造复杂攻击链的非常规题目高Web读源码找漏洞点、生成payload、接口探测对业务逻辑的整体理解、需要多步交互的复杂漏洞中Reverse阅读反编译代码、还原算法逻辑、生成等价脚本高强度混淆、VM保护类中低Pwn生成利用脚本的初稿、解释保护机制堆利用等需要精确内存布局的复杂利用低我实际跑下来的感觉是Misc和基础Crypto题AI的解法成功率远超我的预期。因为这些题本质上就是“信息提取加模式匹配”模型见过的样本实在太多了一眼就能认出这是base64嵌套还是RSA低加密指数。而Pwn这种需要对着寄存器状态反复调试的题AI基本属于“理论王者、实战青铜”。所以如果你也想搭一套自动解题工具我建议先从Misc和Crypto题入手不要一上来就挑战那些又难又偏的题否则挫败感会非常强。1.2 四段式流水线的设计思路我一开始想的是“端到端黑盒”——把题目直接丢给AI让它输出flag。试了几次就发现这条路走不通题目附件经常是二进制文件直接把整个文件塞给模型要么超出上下文窗口要么返回一堆乱码似的分析。后来我把思路改成了一条四段式流水线题目获取器从练习平台的接口自动拉取题目描述、附件下载地址、分值等信息。分析器把预处理后的题目信息打包给大模型要求它输出“解题思路可执行的Python脚本”。执行器在本地沙箱环境里运行AI生成的脚本捕获标准输出、错误信息和退出码。校验器从脚本输出中用正则匹配flag格式匹配到就自动提交答案匹配不到就记录日志。这个架构的核心思想是AI负责“想”代码负责“做”。AI的认知能力用来做题目分类、思路生成、代码初稿这些高层次的活而真正的脚本执行、结果校验、答题提交全部交给确定性代码来处理。这样即使AI说了一堆胡话只要代码框架够稳系统也不会崩最多是该题失败继续跑下一道。这里有个容易被忽略的细节**AI的输出永远不要直接用来做安全判断必须经过执行器验证和校验器提取之后再入库。**因为模型的输出再流畅也只是概率性的文字序列而flag校验是确定性的两者必须分离。2. 全自动解题环境搭建从拉取题目到执行脚本2.1 自动化拉题与附件预处理我的实验环境是本地搭建的CTF练习平台这类平台一般都会提供题目列表的接口方便做题者拉取题目数据。自动化拉题的过程本质上就是“模拟浏览器登录再调接口拿数据”。我用Python的requests库写了获取器核心逻辑很简单import requests from pathlib import Path s requests.Session() s.post(http://localhost:8000/api/login, json{ username: test_user, password: test_pass }) resp s.get(http://localhost:8000/api/tasks).json() for task in resp[data]: name task[name] attachment_url task.get(attachment_url) if attachment_url: r s.get(attachment_url) Path(fattachments/{name}).write_bytes(r.content)真正花时间的是附件预处理。刚开始我把下载下来的文件直接丢给AI结果模型分不清这是个压缩包还是图片分析质量非常差。后来我总结了一套固定流程先用file命令识别文件类型再用strings提取可读字符串片段最后把文件大小、哈希值、类型描述、字符串前若干条一起打包给AI。file flag.png # 输出flag.png: PNG image data, 600 x 400, 8-bit/color RGBA, non-interlaced strings flag.png | head -50这套后处理的价值在于AI本质上是一个文本模型它需要一个适合文本输入的“题目摘要”。题目的原始二进制是没法直接理解的但“PNG、600x400、RGBA通道、有异常字符串”这些描述AI却能展开丰富的联想告诉你“建议检查LSB通道”。这比把图片原始字节丢给它要有效得多。2.2 提示词模板与上下文管理提示词是整个流水线的灵魂。我试过好几个版本的模板最后稳定在这一套结构上你是一名CTF解题助手。现在给你一道题目的摘要信息请完成两个任务 1. 分析可能的解题方向用3-5句话说明思路。 2. 生成一段Python解题脚本脚本必须满足 - 使用requests/struct/re等常见库 - 自行判断输入文件路径通过sys.argv[1]接收 - 输出结果中如果包含flag请原样打印不要添加额外说明 题目名称{name} 题目描述{description} 附件信息{file_info}这个模板有两点很有讲究。第一要求AI通过sys.argv接收文件路径而不是让它硬编码文件名——这样执行器才能用统一的入口去调用不同题目的脚本。第二明确要求“不要添加额外说明”——模型太喜欢在答案里附上“我认为这是一个RSA问题”之类的废话这对后端的flag提取干扰极大。上下文管理上我也踩了坑。刚开始我设置成多轮对话AI每轮的答案都会带上前一轮的内容结果第二三轮之后模型经常把前面几道题的结论混到一起输出一些莫名其妙的东西。后来我改为每一道题完全独立的单轮对话只在系统提示词里固定角色设定题目信息只出现在用户消息里。这样不仅答案更干净还省了不少token开销。2.3 让AI输出“可执行”的结构化结果AI返回的内容如果是一大段自然语言脚本很难直接提取代码。我试过用正则去匹配代码块——效果还行但不够稳因为模型偶尔会忘记用markdown代码块或者在里面混入测试说明。后来我换成了结构化输出要求模型返回JSON固定两个字段analysis思路分析和codePython脚本。再用代码解析JSON解析失败时退回到正则提取python代码块。import json, re def parse_llm_response(text): try: data json.loads(text) return data[analysis], data[code] except Exception: code_match re.search(rpython\n(.*?), text, re.S) if code_match: return text[:200], code_match.group(1) return text, 这个兜底逻辑非常重要。实测下来JSON模式能覆盖大约七成的情况剩下三成靠正则兜底基本能保证执行器永远拿到一份可尝试运行的代码。让AI按固定格式输出不是限制它的发挥而是让后续的自动化流程有确定性的入口。3. 实测记录三类题目的AI解题全流程3.1 Web题源码分析加自动构造payload有一道登录绕过题题目附了后端处理登录的核心代码片段明显是SQL注入。我把代码片段完整贴给AI让它找漏洞点并生成利用脚本。AI的分析结论很标准登录查询用了字符串拼接单引号未过滤可以直接万能密码绕过。AI生成的脚本大概是这样import requests, sys url sys.argv[1] r requests.post(url, data{ username: or 11 --, password: x }) print(r.text)执行器把目标URL传进去脚本确实返回了管理员的页面内容校验器从响应里成功匹配到了flag。整个过程从拉题到提交不到两分钟比我手写payload再测试快太多。但我也碰到过AI分析对但代码跑不通的情况。有一次题目考察的是二次注入AI思路说得头头是道生成的代码却少了一个URL编码步骤导致payload里的空格被HTTP请求格式吃掉。这就是为什么执行器必须把报错信息回传给AI再迭代一版而不是简单判死。3.2 Crypto题模式识别加数学脚本生成Crypto题是AI提升自信心最明显的一类。有一道RSA题给了n、e、c三个大整数e很小经典的低加密指数攻击。AI看到参数后第一反应就是“e3直接对c开三次方”然后生成了用gmpy2库开方的脚本import gmpy2, sys n int(sys.argv[1]) e int(sys.argv[2]) c int(sys.argv[3]) m gmpy2.iroot(c, e)[0] flag bytes.fromhex(hex(m)[2:]).decode() print(flag)我原本以为这种题至少要人工推导几步结果AI直接给出了标准解法。这类题对AI来说本质上就是“题库检索”模型在训练阶段见过太多相同套路的RSA题只要把参数格式整理好它几乎不会错。Crypto题真正麻烦的是参数解析。题目给的数据可能放在文本文件里也可能嵌在题目描述中格式五花八门。我写了一个小函数把题目附件中的大整数按“key value”的形式提取出来再按顺序传给脚本。这套处理对AI的发挥帮助极大因为模型的优势完全建立在“参数清晰、问题明确”的前提上。3.3 Misc题图片隐写的探测与提取Misc题里AI发挥最稳的是编码类题。有一次附件是个文本文件里面是几层嵌套的base64AI直接给出脚本循环解码直到文本里出现flag头。这种题对模型而言没有任何门槛只是单纯地“照章办事”。图片隐写题就麻烦一点。题目给了一张PNG图片AI没法直接看像素所以我的获取器先把图片的关键信息提取出来宽高、通道数、是否有额外数据块、strings的结果。这些信息打包给AI后它推测可能是LSB隐写并生成了提取脚本from PIL import Image import sys, re img Image.open(sys.argv[1]) pixels img.load() width, height img.size bits for y in range(height): for x in range(width): r, g, b pixels[x, y][:3] bits str(b 1) data int(bits, 2).to_bytes(len(bits) // 8, byteorderbig) flag re.findall(rbflag\{[^}]\}, data) print(flag[0].decode() if flag else no flag)这个脚本实际跑下来确实提取到了flag虽然中间做了一个“按位拼接后转为字节”的假设但AI恰好猜对了编码顺序。我的体会是对Misc这类题AI的“联想能力”比精确推理更有价值。它不需要完全理解隐写原理只要能从常见的工具名和现象联想到“该试LSB了”就已经帮了大忙。4. 翻车实录AI解题的常见坑和排查技巧4.1 幻觉代码怎么治报错反馈闭环AI生成的代码最大的问题不是思路错而是调用了根本不存在的函数或库。有一道Reverse题AI生成的脚本用了ida_bytes.get_bytes这个接口在常见的Python环境里根本不存在。执行器一跑就报ImportError系统直接记录失败。后来我加了一个“报错反馈”机制执行器捕获Python异常后把异常信息追加到原来的提示词后面再让AI重新生成一版代码最多迭代三次。这一招效果立竿见影不少题目从“一次性失败”变成了“第二次就通过”。for attempt in range(3): code get_code_from_llm(task_info, last_error) result run_in_sandbox(code, task_attachment) if result[success]: break last_error result[stderr][-500:]这种“执行—报错—再生成”的闭环本质上就是把AI当成一个可以对话的开发者用编译器和解释器的报错作为它的“实时反馈”。你不能指望AI一次写对但你可以指望它在看到错误信息后改对。4.2 编码地狱被吞掉的flag和可读性处理这个问题浪费了我最多的时间。AI生成的脚本里如果有print(binary_data)Python会把字节串打印成bflag{xxx}校验器的正则如果没处理b前缀就永远匹配不到。类似的问题还有模型在flag前后加了多余的换行、用Unicode引号代替ASCII引号、Windows换行符导致正则边界失效。我的解决方案是全校验器统一用这一个正则import re flags re.findall(rflag\{[^}]\}, output, flagsre.IGNORECASE)并且在保存输出前先做一次bytes.decode(errorsignore)的容错处理。这样不管脚本输出的是字节串还是文本最终都能被正则抓到。规则越简单越好不要试图在提取阶段处理所有编码细节。4.3 超时、并发与队列管理自动解题过程中总有一些AI生成的脚本陷入死循环比如扫描端口时用了无超时的socket连接或者正则回溯复杂度过高。如果执行器没有超时机制整个队列会被一道题卡死。我的做法是每个脚本最多跑60秒超时直接kill然后用subprocess.run(timeout60)捕获超时异常记录日志后继续下一题。并发控制方面因为用的是开源模型接口并发太大会直接触发限流所以我把并发数限制在2个任务同时执行每道题之间再间隔1秒。这个节奏跑下来最稳定既不浪费算力也不容易触发服务端的访问限制。还有一个不起眼但很重要的细节执行日志一定要落盘。我把每道题的提示词、AI原始回复、生成的代码、运行输出、最终结果全部存成JSON行文件。这样即使某道题失败了回头复盘时也知道是分析错了、代码错了还是输出解析错了而不是对着终端里滚过的日志干瞪眼。5. 最后说点大实话我在实验里一共跑了二十多道题最终统计出来AI独立完整解出的大概四成加上我人工介入辅助后差不多能到七成。这个成绩不算惊艳但已经足够让我把“AI能不能打CTF”这个问题从“不能”改口成“看题型”。我个人最大的体会是AI在CTF里的定位不是解题者而是“超快的信息检索员代码初稿生成器”。那些纯机械的环节——读题、查编码、写脚本骨架、调库函数——AI做得又快又好把原本属于人的精力释放了出来。于是人从“什么都自己干”变成了“审核AI的分析、修正它的方向、处理它搞不定的边界情况”。这个过程里人并没有被AI替代而是被AI推向了更高层的判断位。最后再分享一个小技巧这条流水线稍加改动就能用来当CTF训练的“陪练”。在执行器前面加一句提示词“请不要直接给完整答案先给提示”AI就从一个答题者变成了助教。我用这种方式带过几个刚入门的朋友他们普遍反馈比对着题解硬啃要友好得多。工具是死的思路是活的。这个方向后续我还会继续折腾等跑出更多有意思的结果再来跟大家同步。