智能合约自动化逆向反编译与大模型语义重构:从 EVM 字节码到高可读 Solidity

封面信息图

在链上安全应急响应、未开源合约取证与 MEV 机器人逆向分析中,安全工程师经常需要面对一串未在 Etherscan 开源验证的纯十六进制字节码(Unverified Bytecode / 0x6080604052...)。

传统的逆向工具(如 Panoramix、Ghidra EVM、Dedaub)反编译出来的代码充斥着大量晦涩难懂的中间伪代码:

  • 变量名全部是 v0, v1, v2;
  • 存储槽位访问只有裸露的 sstore(0x0, add(sload(0x0), v1));
  • 缺乏函数签名与业务上下文,人类专家肉眼阅读极其吃力。

“EVM 字节码符号反编译(Panoramix / Heimdall)+ 4-byte 函数选择器知识库 + 大语言模型(LLM)语义重构” 创造了一套全自动逆向流水线:
能够将冰冷的底层操作码在 10 秒钟之内自动还原为变量名语义清晰、包含标准 NatSpec 注释、高度可读的现代 Solidity 源代码!


一、EVM 字节码逆向反编译与语义重构全景拓扑

graph TD
    RawHex[链上未开源十六进制 Bytecode] --> Heimdall[Heimdall / Panoramix 符号反编译器: 提取 CFG 控制流与低级伪代码]
    Heimdall --> RawPseudo[粗糙低级伪代码 (含 v0, v1, sstore)]
    
    RawHex --> SelectorExtract[提取 4 字节函数选择器 (如 0xa9059cbb)]
    SelectorExtract --> FourByteDB[4-byte 官方签名知识库: 匹配为 transfer(address,uint256)]
    
    RawPseudo & FourByteDB --> PromptEngine[语义重构 Prompt 组装引擎]
    PromptEngine --> LLM[大语言模型: 推导变量真实业务含义,重构为标准 Solidity]
    LLM --> CleanSolidity[输出高可读、带注释、结构优雅的 CleanSolidity.sol]

二、Heimdall 提取与 4-byte 数据库匹配脚本(TypeScript 实现)

// decompiler/selectorResolver.ts
import axios from 'axios';

// 查询以太坊官方 4-byte 签名库
export async function resolveFunctionSelector(selectorHex: string): Promise<string | null> {
  try {
    const formattedSelector = selectorHex.startsWith('0x') ? selectorHex : `0x${selectorHex}`;
    const res = await axios.get(
      `https://www.4byte.directory/api/v1/signatures/?hex_signature=${formattedSelector}`
    );
    if (res.data.results && res.data.results.length > 0) {
      // 返回匹配到的标准函数签名 (如 "transfer(address,uint256)")
      return res.data.results[0].text_signature;
    }
  } catch (err) {
    console.warn(`Selector ${selectorHex} not found in 4byte directory.`);
  }
  return null;
}

三、基于大模型的语义重构引擎实现

// decompiler/semanticReconstructor.ts
import Anthropic from '@anthropic-ai/sdk';
import { resolveFunctionSelector } from './selectorResolver';

const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });

export async function reconstructBytecodeToSolidity(rawDecompiledPseudo: string, extractedSelectors: string[]) {
  // 1. 批量解析函数签名
  const resolvedSignatures: Record<string, string> = {};
  for (const sel of extractedSelectors) {
    const sig = await resolveFunctionSelector(sel);
    if (sig) resolvedSignatures[sel] = sig;
  }

  console.log('📖 [Selectors Resolved]:', resolvedSignatures);

  // 2. 构造重构 Prompt
  const prompt = `
你是一名世界顶级的 Solidity 逆向安全工程大师。
以下是从一段未开源 EVM 字节码中提取出的粗糙反编译伪代码,以及匹配到的 4-byte 函数选择器:

[已匹配的函数选择器]:
${JSON.stringify(resolvedSignatures, null, 2)}

[底层反编译伪代码]:
\`\`\`text
${rawDecompiledPseudo}
\`\`\`

[重构任务要求]:
1. 将所有的 \`v0, v1, var_a\` 等无意义变量名,根据上下文逻辑推导为具备明确业务含义的英文变量名 (如 \`recipient\`, \`depositAmount\`, \`userBalance\`);
2. 将底层的 \`sstore / sload\` 抽象为标准的 Solidity 状态变量与 \`mapping\`;
3. 输出符合 Solidity 0.8.20+ 语法的标准、高可读合约代码,并附带核心业务逻辑说明。
`;

  const response = await anthropic.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 2048,
    messages: [{ role: 'user', content: prompt }],
  });

  return response.content[0].text;
}

四、重构效果前后震撼对比

1. 原始粗糙反编译伪代码(难以阅读):
def unknown_a9059cbb(varg0, varg1): 
  require msg.value == 0
  require 0x4 + (msg.data.length - 0x4) >= 0x40
  v0 = sload(keccak256(msg.sender, 0x0))
  require v0 >= varg1
  sstore(keccak256(msg.sender, 0x0), v0 - varg1)
  v1 = sload(keccak256(varg0, 0x0))
  sstore(keccak256(varg0, 0x0), v1 + varg1)
  return 1
2. 大模型自动化语义重构后的 Solidity 源码:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @title Standard ERC-20 Token Transfer Function
 * @notice 自动化逆向重构自链上字节码 (Selector: 0xa9059cbb)
 */
contract ReconstructedToken {
    // Slot 0 映射为标准 ERC-20 代币余额账本
    mapping(address => uint256) public balanceOf;

    event Transfer(address indexed from, address indexed to, uint256 value);

    error InsufficientBalance(uint256 available, uint256 required);

    function transfer(address recipient, uint256 amount) external returns (bool) {
        uint256 senderBalance = balanceOf[msg.sender];
        if (senderBalance < amount) {
            revert InsufficientBalance(senderBalance, amount);
        }

        // 扣减发送方余额并增加接收方余额
        balanceOf[msg.sender] = senderBalance - amount;
        balanceOf[recipient] += amount;

        emit Transfer(msg.sender, recipient, amount);
        return true;
    }
}

五、智能合约逆向三大极客要点

  1. 利用 Etherscan 历史交互交易推导数据结构:在重构时,除了反编译伪代码,同时拉取该合约在链上发生的真实 Transaction Calldata,能让大模型百分之百还原结构体内部字段;
  2. 结合 Slither AST 校验重构准确性:重构出的 Solidity 代码自动输入 Slither 进行二次静态编译,确保逻辑语法完全闭环;
  3. 识别代理与实现分流(Proxy Detection):在逆向第一步检查是否存在 0x360894a13ba1a321... ERC-1967 实现槽位读取,如果是代理合约,自动重定向反编译其背后的 Implementation 真实逻辑。

将冰冷的二进制字节码转化为人类易读的架构代码,这是全栈安全专家在黑暗森林中洞察一切的终极利器。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐