平时用 AI 编码客户端写业务代码已经成了习惯,可一旦切换到逆向工程场景,大部分模型的表现会一下子“降智”。不是模型不懂反汇编,也不是它不会读代码,而是它缺少一套工程化的处理流程。最近我把自己在安全研究里积累的一套逆向工作流,整理成了一个叫 reverse-skill 的项目。简单来说,reverse-skill 是一套面向 AI 编码客户端的逆向工程技能路由包,它把文件识别、静态反汇编、动态调试、协议还原、密码算法识别这类高频任务封装成独立的 skill,再通过一个轻量的路由层,让 AI 客户端在收到任务时自动选择并加载正确的技能。
它解决的核心问题很直接:AI 编码客户端拿到一个未知二进制文件时,经常不知道接下来该调用哪个工具、按什么顺序执行、输出什么形态的结果。如果你在做 CTF、闭源 SDK 兼容分析、恶意文件应急,或者只是想把一个老程序逆向梳理成文档,这个路由包都能帮你把“AI 自由发挥”变成“AI 按流程干活”。
1. 技能路由包:整体设计与思路拆解
1.1 AI 编码客户端在逆向场景中的三个典型痛点
先说个我自己的观察。用 Cursor、Claude Code 这类 AI 编码客户端写 CRUD 页面、调接口、补测试,体验相当顺滑。但只要丢进去一个 .elf 或 .exe 文件,说一句“帮我看下这个程序在干什么”,模型十有八九给你一套正确的废话:建议你用 file 查看文件类型、用 strings 看字符串、用 objdump 反汇编、用 gdb 调试。这些建议单独看全对,但拼在一起根本没法指导一个新手完成逆向分析。
第一个痛点是任务缺少操作序列。逆向工程本质上是一个决策链很长的过程:拿到文件后先做什么,看到某个现象后下一步转向哪里,这是一个不断收敛的判断过程。通用模型虽然知道很多工具的用法,但它不知道在“现在”这个具体节点应该调用哪个工具。打个比方,让一个没拆过机的新手去修手机,跟他讲“你要检查屏幕、检查电池、检查主板”是没用的,他需要的是“先拧哪颗螺丝、再撬哪个卡扣、用什么工具”的步骤。
第二个痛点是上下文被无效信息占满。很多 AI 客户端支持直接把文件拖进对话,但二进制文件不是文本,扔进去只会变成一堆乱码,白白浪费上下文窗口。就算你把文件转成 hex 或反汇编文本,一股脑塞进去,模型也会被海量数据淹没,反而抓不住关键逻辑。我更倾向于让模型“读摘要”“读局部”,而不是“读全文”。
第三个痛点是工具链没有编排逻辑。一个真实的逆向流程里,file 的输出会影响你选择静态分析还是动态调试,checksec 的结果会影响你对保护措施的理解,strings 里出现的特殊字段可能直接指向某个协议。这些工具的依赖关系和优先级是靠经验累积出来的,通用模型没有这种“条件反射”,所以它给出的建议经常是跳跃的、不连贯的。
其实这三点背后的原因是一致的:模型缺少一个结构化的任务框架。reverse-skill 就是为这个框架设计的。
1.2 路由包的设计哲学:把经验翻译成流程
我做 reverse-skill 之前试过很多种方案,比如写一份超长的 system prompt,把逆向工程的所有原则、工具、步骤全部塞给模型。结果很尴尬:prompt 越长,模型越容易“盯着原则忘掉任务”,而且每次对话都要重新加载几千字规则,浪费上下文,效果还不稳定。
后来我换了个思路:不再给模型灌一整套方法论,而是把方法论拆成一组可独立调用的 skill,按需加载。就像你请了一个顾问团队,平时不带在车上,遇到什么问题就叫对应领域的顾问过来。每个 skill 负责一个子任务,只在这个子任务被触发时才加载,这样上下文负担小,专业度也高。
整个路由包的核心流程是这样的:用户提出一个问题,router 层对问题进行意图判断,匹配到对应的 skill,然后把 skill 的内容以提示词、工具定义或外部指令的形式交给 AI 客户端,AI 再按照 skill 里定义的步骤执行并输出结构化结果。
这中间的“路由”两个字,是整个设计的关键。传统做法是“一个巨大的 prompt 管理所有场景”,reverse-skill 则是“多个小 skill + 一个判断器”。判断器可以很简单,我最初的实现只有几十行规则和正则,就已经比“万能 prompt”可靠很多。
那为什么不直接让模型自己决定下一步呢?我在多个模型上试过,只跟模型说“你现在是一个逆向工程师”,它依然会陷入选择困难。模型不是没有知识,而是缺少优先级。路由层就是那个“优先级判断器”,它把“人类工程师在这个场景下会先做什么”的经验显式地写出来,模型只需要执行。
1.3 reverse-skill 与普通 Prompt、Custom Instructions 的差异
很多人会问,这跟 Cursor 里的 rules、Claude Code 里的 CLAUDE.md,或者一个精心编写的自定义指令有什么区别?区别在于触发机制和职责边界。
普通的 rules 或 instructions 更接近“恒定约束”,它们定义一个项目长期遵守的规范,比如代码风格、测试要求、目录结构。而 reverse-skill 里的每个 skill 是按场景触发的流程模板,同一个项目里可以挂几十个 skill,只有被 router 命中的那个才会真正影响模型行为。
我做过一个对比:同样一句“分析这个 samples/runme 文件”,如果用固定提示词,模型会给出通用的五步法;如果挂载了 reverse-skill,router 会识别出这是一个 ELF 文件,触发 file_triage 这个 skill,AI 会先执行 file、strings、checksec,并输出一份“文件初筛报告”。后者的结果更接近真实逆向工程师的产出,而且整个过程是可复现的——换一个模型来跑,只要路由逻辑不变,结果就基本一致。
还有一个差异是上下文开销。一个 full 的逆向方法论提示词可能有两三千字,但一次分析任务实际只会用到其中一小部分。技能路由包按需加载,每次只注入一个 skill,通常几百字就够,剩余上下文全部留给分析数据。这在处理大型二进制时非常重要。
2. 核心细节解析与实操要点
2.1 定义一个 skill 的标准结构
reverse-skill 里的每个 skill 就是一个结构化文档,我用 YAML 格式维护,因为它可读性好,也方便被程序解析。每个 skill 包含以下字段:
| 字段 | 作用 | 示例 |
|---|---|---|
| name | 技能名称,全局唯一 | file_triage |
| description | 技能职责描述,供 router 做意图匹配 | 对未知文件进行类型识别、基础信息采集和初步定性 |
| triggers | 触发词、正则模式或意图描述 | ["file", "文件类型", "what is this", "\\bELF\\b"] |
| inputs | 该技能需要的外部输入 | 目标文件路径、字符串提取范围 |
| tools | 需要调用或建议使用的工具链 | file,strings,checksec,ent |
| steps | 可执行步骤清单,按顺序排列 | 依次采集文件头信息、提取字符串、计算熵值 |
| output_format | 技能输出的标准模板 | 输出 Markdown 表格:字段/值/初步推断 |
| pitfalls | 常见坑位与注意事项 | 不要直接打开超过 10MB 的文件;字节序影响熵结果 |
下面是一个真实可用的 skill 示例,也是我路由包里第一个写的file_triage:
name: file_triage description: > 对目标文件进行初步识别,判断文件类型、架构、链接方式、 保护措施,并提取关键字符串与熵值。适用于任何未知名文件的 第一次分析。 triggers: - "file" - "文件类型" - "这是什么" - "what is this" - "\\b(file|elf|pe|mach-o)\\b" inputs: - path: 目标文件的本地路径 tools: - file - strings - checksec - ent steps: - 运行 file <path>,记录文件类型、目标架构、字节序 - 运行 checksec --file=<path>,记录 NX、PIE、RELRO、Canary 状态 - 运行 strings -n 6 <path>,提取长度大于等于 6 的字符串并分类 - 运行 ent <path>,记录文件熵值并判断是否可能加壳或加密 - 综合以上输出,生成文件初筛报告 output_format: | ## 文件初筛报告 - 文件类型:`file` 输出 - 架构/字节序:... - 保护措施:... - 可疑字符串:... - 熵值结论:... - 初步判断:... pitfalls: - 不要在 strings 输出过长时全量粘贴给模型,应截取前 100 行 - checksec 对非可执行文件可能报错,需在 steps 里加异常分支这个结构看起来简单,但实际使用中非常有效。因为它把“人类工程师会怎么做”显式化为模型可执行的步骤,模型不再需要自己猜测。
2.2 技能划分的粒度控制
我第一次做技能路由包时,一个常见的误区是技能划分太细或太粗。太细会导致路由复杂、每个 skill 都是碎片;太粗又回到“万能 prompt”的老路。经过多轮迭代,我最终把逆向工程场景收敛成了八个基础 skill:
file_triage:文件初筛,识别类型和基本信息。static_disassemble:静态反汇编,定位入口点、函数表和关键交叉引用。decompile_scan:反编译与伪代码分析,结合 Ghidra 或 retdec 输出还原核心逻辑。dynamic_debug:动态调试,用 gdb 或 ltrace 追踪运行时行为。protocol_reverse:协议分析与抓包日志梳理。crypto_identify:密码学算法识别与硬编码密钥搜索。unpack_shell:加壳与混淆样本的去壳检测和初步处理。report_writer:汇总所有阶段产物,生成结构化逆向分析报告。
每个 skill 我控制在 300 到 600 字之间。太长了模型执行到后面容易“迷失”,太短则无法提供足够信息。你可以在自己项目里按需要增删,但建议保持“一个 skill 只负责一条完整任务链”的原则。
举个例子,crypto_identify不会去管文件初筛,它只关心怎么识别 AES 常量、如何搜索密钥、如何通过熵值判断某块数据是否加密。这样路由时非常清晰:用户说“这里有一段密文”,router 直接命中crypto_identify,模型立刻进入算法识别模式,不会被其他步骤干扰。
2.3 路由匹配:怎么让 AI 选到正确技能
路由层是整个包的大脑。我在实现里用了三层策略,从快到慢依次是:关键字硬匹配、正则模式匹配、LLM 意图打分。
关键字硬匹配最快,适合“When user says file type, answer file_triage”这种明确指令。比如用户输入包含checksec、NX、PIE,大概率是静态保护分析。正则模式匹配用于处理一些可变表达,比如/\.(elf|so|dll|exe)$/i可以识别路径中的可执行文件后缀。
但真实用户提问往往不是标准命令,比如“这个程序好像有壳,怎么处理?”这种自然语言问题,关键字和正则都可能失效。这时候我用一个简单的打分函数:把 skill 的 triggers 和 description 里的关键词拆分成词袋,对用户输入做术语匹配,得分最高的 skill 胜出。这个函数不依赖大模型,几毫秒就能出结果。
如果打分结果有多个 skill 分数接近,说明用户的问题本身是复合型的,我会采用混合触发模式:先加载第一个 skill,等它跑完输出,再让 router 根据输出决定是否触发下一个 skill。这其实就是一个轻量级的“状态机”思路,我用一个state变量记录当前分析阶段,不同阶段允许触发不同的 skill。
真实的路由代码我放在第三章展示,这里先提一个经验:router 不要试图理解所有话。它只需要做分类,把判断结果交给 skill 之后,真正的内容理解模型自己会完成。这样设计,router 可以做得非常轻,甚至不依赖任何外部 API。
3. 从零构建一个可用路由包
3.1 目录结构设计
我把 reverse-skill 组织成一个纯本地项目,没有任何外部依赖时也能跑。目录结构如下:
reverse-skill/ ├── router.py # 路由主逻辑 ├── skills/ │ ├── file_triage.yaml │ ├── static_disassemble.yaml │ ├── decompile_scan.yaml │ ├── dynamic_debug.yaml │ ├── protocol_reverse.yaml │ ├── crypto_identify.yaml │ ├── unpack_shell.yaml │ └── report_writer.yaml ├── state.json # 当前分析会话的进度状态 └── output/ # 各阶段产物 ├── triage.md ├── disasm/ ├── decompile/ └── final_report.md这个结构很简单,核心是skills/目录下的 YAML 文件和router.py。state.json用来记录当前分析进度,这样 AI 客户端可以在多轮对话中保持路由状态一致。
实际使用时,我通常再建一个samples/目录放待分析文件,并在.gitignore里忽略它,避免把二进制样本误提交到仓库。
3.2 路由模块实现
我用 Python 实现了一个最小路由模块。整个思路是:读取所有 skill 文件,解析出 name、description、triggers,然后与用户输入做匹配,最后返回命中的 skill 内容。
#!/usr/bin/env python3 import re import sys import yaml from pathlib import Path SKILLS_DIR = Path(__file__).parent / "skills" def load_skills(): skills = [] for path in SKILLS_DIR.glob("*.yaml"): with open(path, "r", encoding="utf-8") as f: data = yaml.safe_load(f) data["file"] = path.name skills.append(data) return skills def score_skill(skill, text): score = 0 text_lower = text.lower() for trigger in skill.get("triggers", []): if trigger.startswith("\\b") or trigger.startswith("("): if re.search(trigger, text_lower): score += 3 else: # 普通关键词,按出现次数计分 count = text_lower.count(trigger.lower()) score += min(count, 3) # description 中的术语也能加分 for word in re.findall(r"[a-zA-Z_]{3,}", skill.get("description", "")): if word.lower() in text_lower: score += 1 return score def route(text, skills): scores = [] for skill in skills: s = score_skill(skill, text) if s > 0: scores.append((s, skill)) if not scores: return None scores.sort(key=lambda x: x[0], reverse=True) # 取最高分;如果有多个接近,返回前两个由上层决定 return scores[0][1] if __name__ == "__main__": text = sys.stdin.read().strip() skills = load_skills() hit = route(text, skills) if hit: print(f"matched: {hit['name']}") print("---") print(yaml.dump(hit, allow_unicode=True, sort_keys=False)) else: print("no skill matched")这个实现有几个值得注意的设计点。
第一,score_skill对正则触发词和普通关键词分别处理。像\bELF\b这种正则,如果原样当作关键词去 query.lower() 里 count,根本不会命中,所以要先判断是否以正则特征开头。
第二,路由结果分数相同时,我没有直接抛出异常,而是返回分数最高的,同时由上层环节决定是否追问用户。继续追问比“猜一个”更稳妥,尤其是恶意文件分析场景,猜错技能可能导致误判。
第三,所有 skill 文件在启动时一次性加载到内存。数量少时可以这么做,如果扩展到几十个 skill,建议改成按需加载,或者用索引文件标记每个 skill 的关键触发词。
3.3 接入 AI 编码客户端的三种方式
reverse-skill 的路由模块本身不是 AI 客户端,它需要和编码客户端配合。我在实际项目中试过三种接入方式,各有适用场景。
第一种,将 router 的输出作为上下文注入。适合 Claude Code、Cursor 这类支持项目内指示文件的工具。我在项目里加一个AGENTS.md或者.cursor/rules,里面动态写入路由结果。每次用户提问时,先跑一次python router.py,把命中的 skill 内容贴进对话。这种方式的优点是不需要客户端额外支持,缺点是多一步手动操作。
第二种,通过 MCP 工具暴露。适合自研 Agent 或支持 MCP 的客户端。我把route()函数封装成一个 MCP tool,客户端收到“分析这个文件”时自动调用该 tool,拿到 skill 内容后继续后续生成。这样路由过程对用户完全透明,体验最好。缺点是 MCP 环境配置有一定门槛。
第三种,作为标准 skill 文件放到客户端的原生技能目录里。现在很多 AI 编码客户端自带 skill 机制,比如某些助手支持把 YAML 文件放到.claude/skills/目录,模型会自动读取并匹配。我的 YAML 格式基本兼容这类机制,这是最省事的接入方式,我把skills/目录直接链接过去就能用。
三种方式的对比我放在下面:
| 接入方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 上下文注入 | 零依赖,任何客户端可用 | 需要手动跑 router | 快速验证思路 |
| MCP 工具 | 路由透明,自动触发 | 配置复杂 | 自研 Agent、重度用户 |
| 原生 skill 目录 | 最自然,无需中间层 | 依赖客户端识别能力 | 支持 skills 机制的客户端 |
如果你刚开始尝试,我建议先用第一种方式跑通流程,再逐步迁移到 MCP 或者原生 skill 目录。毕竟核心价值在 skill 内容和路由策略,不在接入方式。
4. 实战复现:还原一个 ELF 文件的核心逻辑
4.1 实验环境与合规说明
这里用一个模拟场景演示整个流程。我准备了一个自己编译的 Linux ELF 文件,它有三个功能:接收参数、用内置密钥解密一段内存数据、输出解密结果。整体逻辑很简单,但数据包被故意混淆过,适合演示技能路由包如何一步步拆解。
需要特别说明的是,所有样本都是我自己编译的,或者来自开源的 CTF 题目、已经授权的分析目标。做逆向工程分析,尤其是拿 AI 编码客户端辅助,合规边界要自己守住。不要拿别人的商业软件去破解授权校验,也不要在没有授权的情况下分析第三方程序。
4.2 阶段一:file_triage 文件初筛
我把文件路径丢给 AI 客户端:“请分析 samples/runme 这个文件。”
router 收到文本后,先做关键字匹配。samples/runme没有直接命中任何 skill 名,但分析、文件这类词在多个 skill 的 description 里都有,分数会很分散。于是 router 进入正则模式,发现用户输入末尾是.runme且没有任何后缀,判断这是一个未知名文件,最合理的起始点是file_triage,于是把该 skill 注入对话。
模型按 skill 里的 steps 依次执行:
file samples/runme # 输出:ELF 64-bit LSB executable, x86-64, dynamically linked checksec --file=samples/runme # 输出:No PIE, No NX, No Canary strings -n 6 samples/runme | head -50 # 输出中出现了 "key:", "decrypt", "usage: runme <input>" 等可读字符串根据这些输出,模型生成了第一份结构化报告:
- 文件类型:ELF 64 位动态链接可执行文件,x86-64。
- 保护措施:无 PIE、无 NX、无 Canary,说明编译时没有启用常见安全加固,这可能是一个用于教学或逆向练习的样本。
- 可疑字符串:包含
decrypt、key:、usage,初步判断程序接受一个输入参数,并执行某种解密操作。
这个过程如果没有路由包,模型可能会直接开始反汇编整个文件,浪费大量上下文。而file_triage让 AI 先花最少的资源拿到全局画像,为下一步提供路由依据。
4.3 阶段二:static_disassemble 静态反汇编
拿到初筛报告后,router 判断下一步应该进入static_disassemble。因为报告显示程序是动态链接的,而且有明确的字符串提示,不需要先动态调试,直接做静态分析定位关键函数更高效。
该 skill 指导模型执行:
objdump -d samples/runme | grep -A 30 "<main>:" # 定位 main 函数和它的调用序列 nm samples/runme # 查看符号表 readelf -s samples/runme | grep FUNC # 列出所有函数模型从输出中发现主函数在调用一个名叫parse_input的子函数后,又调用了位于.rodata段的一个数据地址。它并没有直接在反汇编文本里寻找,而是通过符号表和交叉引用,锁定了两个候选函数:parse_input和decrypt_buffer。
这里有一个实操技巧:不要让模型一次性读取整个objdump -d的输出。一个 50KB 的二进制反汇编出来可能有几万行,全量塞进去会立刻淹没上下文。我通常在 skill 里写明“使用 grep、sed 先过滤出关键函数,再逐步展开”,这样模型会把反汇编当成一个“可按需查询的数据库”,而不是全部读进对话。
4.4 阶段三:decompile_scan 与 crypto_identify 交叉分析
有了关键函数列表后,router 进入decompile_scan。模型调用 Ghidra 的头模式分析或者 retdec 反编译,只对main、parse_input、decrypt_buffer三个函数生成伪代码。此时模型看到decrypt_buffer里有一段固定的字节数组,以及一个明显的异或循环:
for (int i = 0; i < len; i++) { out[i] = in[i] ^ key[i % key_len]; }这在 CTF 和很多二进制分析里非常常见。但普通模型看到异或循环时不一定知道下一步该做什么,而路由包已经在crypto_identify这个 skill 里写好了“异或模式的判断方法”和“密钥长度估值技巧”。于是 router 在反编译输出中检测到xor和循环结构,自动追加加载crypto_identify。
该 skill 指导模型执行:
ubelt entropy samples/runme # 或者用 python: scipy.stats.entropy同时,模型在.rodata段找到了一个长度为 16 字节的字符串key: R3v3rs3_Sk1ll,正好与异或循环中的 key 长度匹配。到这里,核心解密逻辑基本清晰:程序接收输入字符串,与内置密钥按字节异或,输出结果。
4.5 阶段四:report_writer 汇总
最后,router 检测到用户输入“总结”“报告”等意图,触发report_writer。这个 skill 的输出模板要求模型把所有阶段产物整理成一份统一的 Markdown 报告,包括:文件基本信息、静态分析结论、关键函数伪代码、密码学算法识别结果、以及一个可执行的验证步骤(用 Python 复现解密逻辑)。
我把报告的最终结构列一下,方便你参考:
- 目标概览:文件路径、SHA256、文件类型。
- 初步结论:程序通过异或解密输入,密钥硬编码在二进制中。
- 关键函数:逐一说明
main、parse_input、decrypt_buffer的作用。 - 命令行验证:给出复现脚本和预期输出。
- 缓释措施:如果这是一个真实恶意样本,应该如何在沙箱里做动态验证。
到这里,一个完整的“从未知文件到核心逻辑还原”的流程就结束了。整个过程里,AI 客户端始终扮演执行者的角色,而在每一步决策上做引导的,是 reverse-skill 路由包。
5. 常见问题与排查技巧实录
5.1 路由选错技能怎么办
最常见的情况是用户提问太模糊,比如“这个文件很可疑”。router 里多个 skill 的 description 都可能包含“可疑”这类词,分数接近,导致选错。
我的排查思路是:先看 router 的原始打分,是哪个触发词让分数持平,然后在对应 skill 里增加更精确的排除词或触发词。比如在file_triage的 triggers 里增加"未知文件"、"是什么文件",在dynamic_debug里增加"运行后"、"调试",这样即使输入包含“可疑”,也会根据上下文意图选择不同路径。
如果模糊程度实在太高,我会在 route 函数里增加一个返回阈值:最高分低于设定阈值时,返回一个“无法确定,请补充信息”的默认响应,而不是强行选一个。
5.2 上下文仍然被撑爆
即使按需加载 skill,反汇编、反编译输出还是会很快填满上下文。我在static_disassemble和decompile_scan两个 skill 里都加了一条硬性规则:任何单次工具输出超过 200 行时,必须截断保存到本地文件,只把摘要或前若干行发给模型。
具体做法是让模型把完整输出写到output/目录下的临时文件,然后在步骤里用grep、head、tail快速定位。比如“只查看 main 函数附近的 30 行”比“把整个反汇编看完”高效得多。
这个办法很土,但极其有效。它本质上是把“外部记忆”从模型上下文转移到了项目文件系统里,AI 编码客户端最擅长处理文件,就让文件来承担记忆职责。
5.3 工具缺失或版本不一致
不是所有人都装了 Ghidra、checksec、ent 这些工具。我在 skill 文件的tools字段里标注了每项工具的替代方案,比如没有checksec时,可以用readelf -h、readelf -l手查 NX、PIE;没有ent时,写一个 10 行的 Python 脚本来计算熵值。
实践中,模型通常能处理这种替换,但你需要提前把“替代路径”写在 pitfalls 里,否则模型会卡在“我没有 checksec”而中断流程。
5.4 模型输出格式不稳定
路由包的一个核心价值就是稳定输出格式,但实际使用中,不同模型对 YAML 输出模板的遵循程度不一样。我的解决方式是,在output_format里规定“必须用 Markdown 表格,列名固定为 字段/值/初步推断”,并且在 skill 的开头加一句“严格按模板输出,不要额外解释”。
如果模型还是跑偏,就在 router 与客户端的中间层做一次格式校验,检测输出的关键标题是否存在,缺失时提示模型重新生成。这个我一般放在 MCP 工具里做,因为原生 skill 目录不支持这种后处理。
5.5 排错速查表
| 问题 | 现象 | 排查方向 | 解决办法 |
|---|---|---|---|
| 路由误判 | 用户问“文件类型”,却触发了dynamic_debug | 查看 router 触发词打分 | 增加关键词和排除词,降低模糊命中率 |
| 上下文溢出 | 反汇编输出几万行,模型开始答非所问 | 检查 skill 的 steps 是否限制输出 | 强制截断、grep 关键函数、写临时文件 |
| 工具缺失 | 模型说无法执行 Ghidra | 检查 tools 字段替代方案 | 在 pitfalls 中补充 Python/objdump 替代 |
| 格式混乱 | 输出报告缺失关键章节 | 检查 output_format 是否被覆盖 | 增加后处理校验,重建缺失部分 |
| 多技能冲突 | 一个文件分析被反复路由到不同 skill | 检查 state.json 是否正确记录阶段 | 明确 state 切换条件 |
写在最后
做了几轮迭代之后,我有一个很深的体会:reverse-skill 本质上不是在教 AI 逆向工程,而是在把经验结构化。真正的价值不在代码量,也不在路由算法多么高级,而在于把“我遇到这种情况会怎么选”的判断,沉淀成了一组可以被模型复用的显式规则。
我个人实际跑下来的感受是,用路由包之后,分析一个样本的平均时间从原来的人工查找约四十分钟,缩短到十分钟内,重点是输出结果稳定,不会因为换了一个模型就出现风格和质量的大幅波动。如果你也想尝试,我的建议是不要一上来就写满八个 skill,先找一个你最高频的动作,比如“文件初筛”,把它写成一个 skill,用三个样本验证,再继续扩展。
最后再分享一个小技巧。每个 skill 你在真实跑完一次之后,一定要回头修改 pitfalls 字段,把那一次踩到的坑补进去。几次迭代之后,这个 skill 就会越来越像一个真实的逆向工程师手册,而不是一个通用的提示词模板。这就是 reverse-skill 后续最值得扩展的地方——技能包的内容会随你的实战经验一起成长。