当前位置: 首页 > news >正文

大语言模型辅助智能合约静态审计:利用 AST 语法树解析与 LLM 提示词链漏洞扫描实战

大语言模型辅助智能合约静态审计:利用 AST 语法树解析与 LLM 提示词链漏洞扫描实战

Web3 安全是去中心化金融(DeFi)生态的生命线。传统的智能合约静态审计工具(如 Slither, Mythril)主要依赖预设的特征规则或符号执行(Symbolic Execution),虽然能够快速筛查出经典的逻辑漏洞,但对于复杂的业务逻辑漏洞与协议级复合攻击却显得力不从心。同时,随着大语言模型(LLM)的发展,直接将几千行的智能合约源码塞入大模型容易受到上下文窗口限制、关键信息稀释以及严重“幻觉(Hallucination)”的困扰。本文将提出一种创新的静态审计范式——通过AST(抽象语法树)预筛选与函数切片提取,精确锁定敏感执行路径,再结合LLM 提示词链(Chain of Thought)进行深度漏洞推理与分类审计。


一、 智能合约审计的局限与演进

传统的静态代码分析工具通过遍历代码并生成中间表示(如 Slither 的 SlithIR),基于控制流图(CFG)和数据流依赖关系查找漏洞。

然而,传统静态审计往往存在以下局限性:

  1. 误报率(False Positive Rate)极高:因为工具无法识别真实的业务语义,例如将正常的升级重置逻辑误判为权限丢失。
  2. 多合约级联调用难以追踪:无法理解跨 DeFi 协议的闪电贷(Flashloan)套利与操纵预言机(Oracle Manipulation)等金融攻击。

大模型(LLM)的引入打破了这一僵局。LLM 拥有强大的代码语义理解能力,能够识别高层次的代码设计意图。但其核心痛点在于:如何确保 LLM 只专注于真正有风险的敏感逻辑?
因此,“AST 预分析(精密制导) + LLM 语义判断(精确打击)”是当前提升代码审计精度和效率的最佳路径。


二、 审计流水线架构设计

本系统的基本审计逻辑如下:

  1. AST 解析阶段:将 Solidity 合约文件输入 AST 解析器,生成结构化的抽象语法树。
  2. 敏感操作码检测与提取:遍历 AST 树,搜索潜在的高风险操作码(例如:外部转账call、自毁指令selfdestruct、修改所有权的transferOwnership等)。
  3. 漏洞相关上下文切片(Slicing):追踪包含上述高风险节点的完整函数定义,提取该函数的参数定义、状态修改语句以及调用逻辑。
  4. LLM 提示词链审计:利用提示词链分步推理,评估是否存在重入漏洞(Reentrancy)、重入锁失效或状态更改后置等逻辑缺陷。
flowchart TD Source[Solidity 源代码] --> Parser[AST 语法树解析器] Parser --> AST[AST 结构化 JSON] AST --> Detector{高风险操作检测} Detector -->|发现 call.value / selfdestruct| Slicer[提取漏洞函数切片] Detector -->|无风险节点| Pass[忽略/通过] Slicer --> SystemPrompt[构造 Step-by-Step 推理提示词] SystemPrompt --> LLM[LLM 推理引擎] LLM --> Step1[步骤 1: 追踪外部调用前后的状态变量修改] Step1 --> Step2[步骤 2: 分析重入攻击的可能性与利用链] Step2 --> Report[生成结构化漏洞诊断报告]

三、 AST 节点结构与重入风险特征

在 Solidity 的 AST 中,一个重入漏洞通常具有以下拓扑特征:

  • 存在一个FunctionDefinition节点。
  • 该函数内部包含一个ExpressionStatement,其底层是一个MemberAccesscall且附带value参数的成员函数调用(即外部转账操作)。
  • 在上述call操作之后,存在对StateVariable的写入或修改操作(违反了“检查-效果-交互”规范)。

四、 工业级 AST 预处理与 LLM 审计管道 Python 实现

下面提供一个完全闭环、手写的 Python 审计脚本。该脚本包含一个轻量级 Solidity 语法扫描器(模拟 AST 节点遍历),提取可能存在重入攻击的函数切片,并构造高控制度的 Chain-of-Thought(思维链)提示词,结合大模型客户端完成漏洞分析。代码中不包含任何占位符。

import json import re # ========================================================================= # 模拟 Solidity AST 树结构数据 (用于演示无需安装 solc 的完整闭环运行) # ========================================================================= MOCK_SOL_CODE = """ contract VulnerableBank { mapping(address => uint256) public balances; function withdraw(uint256 _amount) public { uint256 bal = balances[msg.sender]; require(bal >= _amount); // 外部转账操作,容易遭到重入攻击 (bool success, ) = msg.sender.call{value: _amount}(""); require(success); // 状态更新后置,违反了 Checks-Effects-Interactions 规范 balances[msg.sender] -= _amount; } } """ MOCK_AST_DATA = { "nodeType": "SourceUnit", "children": [ { "nodeType": "ContractDefinition", "name": "VulnerableBank", "children": [ { "nodeType": "FunctionDefinition", "name": "withdraw", "parameters": ["_amount"], "body": [ "uint256 bal = balances[msg.sender];", "require(bal >= _amount);", "(bool success, ) = msg.sender.call{value: _amount}(\"\");", "require(success);", "balances[msg.sender] -= _amount;" ] } ] } ] } class SoliditySmartAuditor: def __init__(self, raw_code: str, ast_json: dict): self.raw_code = raw_code self.ast_json = ast_json self.findings = [] def scan_sensitive_nodes(self) -> list: """ 遍历 AST,查找包含敏感操作(例如外部 call 调用)的函数切片 """ vulnerable_slices = [] contracts = [node for node in self.ast_json.get("children", []) if node.get("nodeType") == "ContractDefinition"] for contract in contracts: functions = [node for node in contract.get("children", []) if node.get("nodeType") == "FunctionDefinition"] for func in functions: func_body = func.get("body", []) has_external_call = False has_state_modification_after_call = False call_index = -1 # 遍历函数体语句 for idx, stmt in enumerate(func_body): # 匹配外部 call 发送以太币的操作 if ".call{" in stmt or "transfer(" in stmt or "send(" in stmt: has_external_call = True call_index = idx break # 如果存在外部调用,检查之后是否进行了状态变更 if has_external_call and call_index != -1: for idx in range(call_index + 1, len(func_body)): stmt_after = func_body[idx] # 简单匹配状态变量修改操作(如 -=, +=, = 赋值) if re.search(r"balances\[.*?\]\s*[\-+=\*]=", stmt_after) or "=" in stmt_after: has_state_modification_after_call = True break if has_external_call: # 提取函数上下文切片 func_slice = { "contract": contract.get("name"), "function": func.get("name"), "code": "\n".join(func_body), "has_risk_state_order": has_state_modification_after_call } vulnerable_slices.append(func_slice) return vulnerable_slices def build_llm_prompt(self, func_slice: dict) -> str: """ 构造高控制度的 Chain-of-Thought 推理提示词 """ prompt = f""" 你是一名资深的智能合约安全审计专家。请针对以下提取的 Solidity 函数代码切片进行静态审计。 [合约名称] {func_slice['contract']} [函数定义] {func_slice['function']} [提取的代码切片] ```solidity {func_slice['code']}

请遵循以下步骤逐步进行分析:
步骤 1: 确定函数中所有执行的外部调用(External Call)操作,并评估它们是否会将控制权转移给不受信任的外部合约。
步骤 2: 追踪所有在外部调用之后执行的状态变量修改操作。
步骤 3: 分析此函数是否容易遭到“重入漏洞(Reentrancy Attack)”的攻击,如果是,请指出攻击者可能实施的具体利用链。
步骤 4: 评估上述状态顺序不当的潜在危害(是否会导致资金被盗、重置错误等)。

最终,请以 JSON 格式输出审计结论,要求包含以下字段:
{{
"is_vulnerable": true/false,
"vulnerability_type": "漏洞名称",
"reasoning_steps": ["步骤1结论", "步骤2结论", ...],
"remediation": "修复方案建议"
}}
"""
return prompt.strip()

def run_audit(self): """ 执行审计流程 """ print("[静态扫描] 开始解析 AST 语法结构树...") slices = self.scan_sensitive_nodes() if not slices: print("[静态扫描] 未发现任何包含敏感外部调用的函数。") return print(f"[静态扫描] 提取出 {len(slices)} 个敏感函数切片进行大模型定向投递。") for s in slices: print(f"\n--- 针对函数 {s['contract']}.{s['function']} 进行审计 ---") if s['has_risk_state_order']: print("[警告] 静态检查发现该函数疑似违反了 'Checks-Effects-Interactions' 规范(状态修改滞后)。") prompt = self.build_llm_prompt(s) print("[大模型投递准备] 提示词链构建完毕。提示词预览:") print("-" * 60) print("\n".join(prompt.split("\n")[:12]) + "\n... (省略后续详细引导步骤) ...") print("-" * 60) # 模拟 LLM 响应 (为了保证没有外部 API Key 依赖依然可以闭环运行) mock_llm_response = { "is_vulnerable": True, "vulnerability_type": "Reentrancy (重入漏洞)", "reasoning_steps": [ "步骤 1: `msg.sender.call{value: _amount}` 确实会将执行控制权转交给调用者地址。", "步骤 2: `balances[msg.sender] -= _amount` 减法更新余额的操作,放在了外部 call 调用之后执行。", "步骤 3: 攻击者可以在 `fallback` 或 `receive` 函数中反复调用 `withdraw`,由于余额未被及时扣除,会不断提取合约中的余额直至耗尽。", "步骤 4: 该漏洞会直接导致项目合约的全部资金被非法洗劫。" ], "remediation": "将 `balances[msg.sender] -= _amount;` 语句移动到 `msg.sender.call` 调用之前执行(即先修改状态,后发起外部交互)。" } print("[大模型审计结果]") print(json.dumps(mock_llm_response, indent=2, ensure_ascii=False))

=========================================================================

执行主程序

=========================================================================

ifname== "main":
auditor = SoliditySmartAuditor(MOCK_SOL_CODE, MOCK_AST_DATA)
auditor.run_audit()

http://www.jsqmd.com/news/963958/

相关文章:

  • 新手入门:基于快马平台生成第一个potplayer字幕翻译脚本
  • 2026年工衣/防静电工衣/电子厂工衣/食品厂工衣/夏天工衣供应厂家分析:透气舒适与安全防护双优之选 - 品牌企业推荐师(官方)
  • YOLO26红外小目标检测实战:缝合DASI模块,实现暗光环境下的特征极速增强
  • QGC地面站视频流拉不通?别急,先用这5个排查步骤搞定(从Ping到VLC播放器)
  • 3大核心功能彻底改变你的B站桌面体验
  • 普宁月子中心口碑排名|从月嫂、月子餐、修复三维怎么评 - 品牌观察
  • 跨学科研究新思路:怎么用 GPT-5.5 寻找不同领域之间的学术交叉点?(附实战教程)
  • Android应用保活技术突破:基于Linux特性的永生方案实现
  • 实战应用:基于js深入浅出vue理念,在快马平台快速构建博客后台管理系统
  • 嵌入式开发模块化编程实战:从Keil软仿真到工程架构设计
  • 2026指针电压表行业:解读三大核心发展趋势 - 资讯速览
  • AI辅助开发体验:借助快马智能模型构建漫画链接智能推荐系统
  • 智微JM系列桥接芯片选型、设计与实战指南
  • Vidupe:智能视频去重工具,彻底解决重复视频存储问题
  • Hermes+Obsidian打造终身可用的AI知识库
  • 零基础策划:如何用 GPT-5.5 在 5 分钟内写出商业活动策划案?(附大模型选型表)
  • 进入2026年,餐饮行业的数字化转型已从简单的“在线点餐”进化到了“全感知智能化管理”阶段。对于消费者和经营者普遍关心的核心痛点
  • 合肥矮小症哪个医院靠谱
  • 家里闲置黄金怎么处置?从经营模式看清杭州回收门店优劣 - 奢侈品回收评测
  • Beyond Compare 5终极激活指南:三步实现完整密钥生成与高效配置
  • 组件库工程底座:基于 TypeScript + Rollup 的多端通用(ESM/CommonJS)高质量组件打包体系搭建
  • 终极宝可梦随机化工具:Universal Pokemon Randomizer ZX 完整指南
  • 公司电话号码认证服务商哪家好?2026最新实力推荐 - 企业服务推荐
  • 【学术干货】 | 22TB数据集破解“光线骗局“——3DReflecNet:首个面向反光/透明物体的3D重建数据集
  • 零基础入门天元云网络自动化:快马平台带你写出第一个运维脚本
  • 工业防爆监控硬件原理与浙江工矿场景选型方案详解
  • 终极教程:如何用一句话生成专业CAD图纸的完整指南
  • YOLO26无人机视角(UAV)优化:针对大视场角、剧烈尺度变化场景的定制化改进
  • 消费增值与传统消费补贴底层商业模式对比、风控设计及实体落地条件详解
  • B2B网站如何做谷歌排名优化?多语言乱码报错的3个排雷技巧