文章总结: 文档介绍Hati系统如何利用Markdown文件定义47个渗透测试技能,通过SkillLoader自动加载匹配目标信息,并由LLM动态适配具体攻击模板。关键创新包括:基于关键词的快速技能匹配机制、LLM将通用技能模板转化为针对目标的实际HTTP请求、多模式确认机制将误报率从25%降至3%。系统支持零代码添加新技能,只需编写Markdown文件即可扩展能力。 综合评分: 88 文章分类: 渗透测试,AI安全,WEB安全,安全工具,安全运营
第六章 – 重生之我是AI人:47 个攻击技能 — 怎么被 LLM 调用
TtTeam
2026年6月19日 12:38 广东
在小说阅读器读本章
去阅读
以下文章来源于威胁情报Z分析 ,作者Gachong
威胁情报Z分析 .
国际网络安全威胁情报,地缘政治事件分析。
- 关于内置的skills
在 Hati 里,一个”技能”就是一个Markdown 文件,写着”如果遇到 X 情况,按 Y 步骤测”。
对比传统概念:
● Ansible playbook:YAML 写的运维剧本
● Burp extension:Java/Python 写的插件
● Hati skill:Markdown 写的渗透测试剧本
为啥选 Markdown?
● 人类能读、LLM 能读、版本控制友好
● 改一个技能不需要重新编译代码
● 加新技能零代码(下一节细讲)
- SKILL.md 长什么样
位置:skills/hack-skills/skills/sqli-sql-injection/SKILL.md
完整内容(简化版):
---name: sqli-sql-injectiondescription: SQL injection detection and exploitationseverity: hightags: [sqli, database, web]---
## detection1. 找带参数的 URL(id=1, page=2, search=...)2. 加单引号 ' 看是否报错3. 加 ' OR '1'='1 看是否绕过4. 加 UNION SELECT 1,2,3 看是否回显
## exploitation- 联合查询: ' UNION SELECT username,password FROM users--- 布尔盲注: ' AND SUBSTRING(@@version,1,1)='5'--- 时间盲注: '; IF(1=1, SLEEP(5), 0)--
## success_indicators- 响应里出现: SQL syntax, MySQL, syntax error- 页面长度变化超过 20%- UNION 回显数字
## pocsGET /artists.php?artist=1' OR '1'='1 HTTP/1.1GET /products?id=1 UNION SELECT 1,2,3--
几个有意思的字段:
● success_indicators:多模式确认的特征字符串(避免误报)
● pocs:通用模板,具体目标要 LLM 适配
● severity:告诉 LLM 漏洞严重程度
● tags:用来自动匹配(下节讲)
- 全部 47 个技能一览
我把所有技能按漏洞类型整理:
- 怎么加载:SkillLoader
文件:agents/skill_loader.py:21-100
加载逻辑很短:
class SkillLoader: def __init__(self, skills_path=None): if skills_path is None: skills_path = "skills/hack-skills/skills" self.skills_path = Path(skills_path) self._skills_cache = {} self._load_all_skills()
def _load_all_skills(self): for skill_dir in self.skills_path.iterdir(): if skill_dir.is_dir(): skill_name = skill_dir.name skill_data = self._load_skill(skill_dir) if skill_data: self._skills_cache[skill_name] = skill_data print(f"[SkillLoader] 已加载 {len(self._skills_cache)} 个攻击技能")
def _load_skill(self, skill_dir): skill_file = skill_dir / "SKILL.md" if not skill_file.exists(): return None
content = skill_file.read_text(encoding='utf-8') metadata = self._parse_frontmatter(content) # YAML 解析 sections = self._extract_sections(content) # ## 标题切分
return { "name": metadata.get("name", skill_dir.name), "description": metadata.get("description", ""), "content": content, "sections": sections, "dir": skill_dir.name, }
注意细节:
● 用 Python pathlib,跨平台
● 解析 YAML frontmatter(用 — 包围的元数据)
● 切分 ## 章节(给 LLM 喂特定章节不用全文)
- 怎么自动匹配:match_skills
文件:agents/skill_loader.py:143-220
这是 LLM 不参与的一步 — 纯关键词打分。为啥不用 LLM 匹配?
● 快:不烧 token,不调外部 API
● 便宜:0 成本
● 稳定:LLM 匹配有随机性,关键词不会
def match_skills(self, target_info): """ target_info = { "url": "http://testphp.vulnweb.com", "tech": ["php", "mysql"], "open_ports": [80, 3306], "keywords": ["search", "login"] } """ matched = [] for name, skill in self._skills_cache.items(): score = 0 reasons = []
# 看到数据库端口 → SQL 相关加分 if 3306 in target_info["open_ports"] and "sql" in name.lower(): score += 2 reasons.append("数据库端口开放")
# 看到 PHP → 文件操作类加分 if "php" in target_info["tech"] and "rce" in name.lower(): score += 2 reasons.append("PHP 目标")
# 看到 login 关键词 → 认证类加分 if any(k in target_info["url"] for k in ["login", "auth", "admin"]): if "auth" in name.lower() or "bypass" in name.lower(): score += 2 reasons.append("认证相关 URL")
if score > 0: matched.append({"name": name, "score": score, "reasons": reasons, ...})
return sorted(matched, key=lambda x: -x["score"])
打分逻辑:
● 数据库端口(3306/1433/5432)→ SQL 类 +2
● PHP 目标 → RCE/LFI 类 +2
● URL 含 login → 认证类 +2
● 描述里出现 target 的 keyword → +1
返回的是 top N,按 score 倒序,LLM 拿到后再二次决策。
- LLM 怎么”用”技能:模板适配
这是最巧的一步。技能是模板,目标是动态的。Hati 不会傻到把技能原文直接发出去 — 它让 LLM 改写。
文件:agents/orchestrator.py 中 _llm_adapt_skill_to_target
简化版逻辑:
def _llm_adapt_skill_to_target(self, skill_content, target_info): prompt = f""" 技能模板: {skill_content}
目标: - URL: {target_info['url']} - 技术栈: {target_info['tech']}
请把技能里的通用模板改写成针对这个目标的具体 HTTP 请求。 输出 JSON: {{"url": "...", "method": "...", "headers": ..., "body": "..."}} """ response = self.llm.chat(prompt) return parse_poc_from_llm(response)
实际效果:
技能原文: "在 id 参数后加 ' OR '1'='1,看是否返回所有数据"
LLM 适配后:{ "url": "http://testphp.vulnweb.com/artists.php?artist=1' OR '1'='1", "method": "GET", "headers": {"User-Agent": "..."}, "body": null}
这一步是 Hati 跟普通工具的本质区别 — 它真的能适配目标,而不是死板发模板。
- 多模式确认
发包之后,Hati 不信 LLM 的”我觉得成功了”。它用特征字符串二次确认。
def multi_pattern_confirm(self, response, skill): indicators = skill["sections"].get("success_indicators", []) for pattern in indicators: if re.search(pattern, response.text, re.IGNORECASE): return True return False
为啥要二次确认?
● LLM 自己可能说”我觉得成功了”但其实没 — 幻觉
● 一次发包可能命中也可能是巧合
● 多模式确认大幅降低误报
实际数据:加二次确认后,误报率从 25% 降到 < 3%。
- 怎么加新技能(零代码)
这是 Hati 最”工程友好”的地方。
步骤:
- 在 skills/hack-skills/skills/ 下新建目录
mkdir skills/hack-skills/skills/my-new-vuln
2.写一个 SKILL.md
---name: my-new-vulndescription: Something new---
## detection...
## success_indicators...
3.重启 Hati(或重新调 get_skill_loader())
完事。 没有改任何 Python 代码。
加新技能的成本:
✅ 不需要懂 Python
✅ 不需要重启核心服务(可热加载,见 get_skill_loader 单例)
✅ 自动被 LLM 发现和匹配
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:TtTeam 《第六章 – 重生之我是AI人:47 个攻击技能 — 怎么被 LLM 调用》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论