mcpField
B
blockchain-auditor

blockchain-auditor

github.com/ckorhonen安全2253 次安装5 周前更新
代码仓库

关于 blockchain-auditor

面向安全审计人员的智能合约审计 Skill,可检查已验证源码或未验证字节码,并按漏洞发现、分叉验证和风险评级组织审查流程。

主要功能

  1. 01源码与字节码侦察
  2. 02检查常见合约漏洞
  3. 03分析 DeFi 特定攻击面
  4. 04基于分叉验证漏洞利用
  5. 05漏洞评级与报告生成

适用场景

  1. 01审查已验证的智能合约
  2. 02调查仅有字节码的合约
  3. 03在分叉环境测试 DeFi 漏洞
  4. 04编写漏洞报告

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ckorhonen/claude-skills --skill blockchain-auditor

安装后在 Claude Code 中输入/blockchain-auditor确认已加载。

附带文件reference.md

详细介绍

区块链安全审计员

系统地审计智能合约,找出可被利用的漏洞,使无特权账户能够提取资金或获得未经授权的访问权限。

快速开始

# For verified contracts (Etherscan source available)
cast etherscan-source <address> --chain mainnet

# For unverified contracts (bytecode only)
cast code <address> --rpc-url $ETH_RPC_URL
cast disassemble <bytecode>

# Fork testing
forge test --fork-url $ETH_RPC_URL -vvv

# Static analysis
slither . --checklist

审计方法

阶段 1:侦察
  1. 收集合约信息:

    # Check balance
    cast balance <address> --rpc-url $ETH_RPC_URL
    
    # Get bytecode
    cast code <address> --rpc-url $ETH_RPC_URL
    
    # Check if verified on Etherscan
    curl "https://api.etherscan.io/api?module=contract&action=getsourcecode&address=<address>&apikey=$ETHERSCAN_API_KEY"
    
    # Check for proxy implementation
    cast storage <address> 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc --rpc-url $ETH_RPC_URL
    
  2. 识别合约类型:

    • 多签钱包(addOwner、execute、confirmTransaction)
    • 代币合约(transfer、approve、balanceOf)
    • DeFi 协议(deposit、withdraw、swap、liquidate)
    • 借贷协议(Compound/Aave 风格)
    • AMM/DEX(Uniswap v2/v3 风格,带流动性池)
    • 代理模式(EIP-1967、UUPS、Transparent、Beacon)
    • 金库/收益聚合器(ERC-4626)
    • 跨链桥(lock/mint、burn/release)
    • NFT 合约(ERC-721、ERC-1155)
阶段 2:源代码分析(已验证合约)
  1. 识别高风险函数:

    • selfdestruct / suicide - 可耗尽所有 ETH
    • delegatecall - 可执行任意代码
    • 带用户可控数据的 call - 可执行任意调用
    • 不带检查的 transfer / send - 重入风险
    • withdraw / claim / redeem - 资金提取点
    • initialize / init - 代理初始化(能否被调用两次?)
    • permit / permitAll - 绕过链下授权
    • flash / flashLoan - 闪电贷入口点
  2. 检查访问控制模式:

    // Weak patterns to look for:
    require(tx.origin == owner);     // tx.origin bypass
    require(msg.sender == owner);    // Check if owner is compromised
    // Missing modifier on sensitive function
    function withdraw() public {     // No onlyOwner!
        payable(msg.sender).transfer(address(this).balance);
    }
    // Proxy: unprotected initialize
    function initialize(address _owner) public {  // Missing initializer modifier!
        owner = _owner;
    }
    
  3. 已知漏洞模式:

    • 重入(在外部调用后才更改状态)
    • 整数溢出/下溢(Solidity < 0.8.0)
    • 未检查返回值
    • 易受抢先交易影响
    • 闪电贷攻击(在单笔交易中操纵价格)
    • 价格预言机操纵(现货价格与 TWAP)
    • Permit/EIP-2612 签名重放
    • ERC777 回调重入
    • 只读重入(在逻辑中误用 view 函数)
    • 捐赠攻击(代币余额膨胀)
    • 首位存款者份额膨胀(ERC-4626 金库)
阶段 3:DeFi 专属攻击向量

对于 DeFi 协议,以下攻击向量价值最高且常被利用:

  1. 价格预言机操纵:

    // Vulnerable: spot price used as oracle
    function getPrice() public view returns (uint256) {
        (uint112 reserve0, uint112 reserve1,) = IUniswapV2Pair(pool).getReserves();
        return reserve1 * 1e18 / reserve0;  // Manipulable in a single tx!
    }
    // Attack: flash loan → manipulate pool → call vulnerable function → repay
    
    • 检查协议是否在任何地方使用现货价格
    • TWAP 预言机是安全的;Chainlink 数据源是安全的(在心跳间隔内)
    • 查找 getReserves()、slot0()、直接查询 AMM 池的调用
  2. 闪电贷攻击面:

    • 是否可以使用借入的资金调用任何状态更改函数?
    • 检查:借入大额资金 → 执行操作 → 在同一笔交易中偿还
    • 关键问题:协议是在用户存款前还是存款后测量价格/余额?
  3. 重入变体:

    // Cross-function reentrancy
    function withdraw() external {
        // State updated after transfer → reenter via deposit()
        IERC20(token).safeTransfer(msg.sender, amounts[msg.sender]);
        amounts[msg.sender] = 0;  // Too late!
    }
    
    // Read-only reentrancy (in Curve, Balancer)
    // Attack: during callback, totalSupply() returns old value
    // Another protocol reads it via getVirtualPrice() during the callback
    
  4. ERC-4626 金库膨胀攻击:

    • 首位存款者可通过捐赠代币抬高份额价格
    • 目标:以 (deposit * totalShares) / totalAssets 铸造份额的协议
    • 如果 totalShares = 0,首位存款者将获得 deposit 份额;随后可通过捐赠抬高份额价格
  5. 签名/Permit 漏洞:

    // EIP-2612 permit can be front-run
    // Front-runner takes the permit, uses it themselves before victim's tx
    // Safe if permit is used atomically in the same tx
    
    // Check: does permit use chainId? (cross-chain replay)
    // Check: does it use nonces? (replay protection)
    
  6. 治理/时间锁攻击:

    • 治理机制能否提议并执行恶意升级?
    • 是否设有时间锁?时长是多少?
    • 能否通过闪电贷获取投票权以绕过法定人数?
阶段 4:字节码分析(未经验证的合约)
  1. 反汇编字节码:

    cast disassemble <bytecode> > contract.asm
    
  2. 提取函数选择器:

    # Look for PUSH4 followed by 4 bytes
    grep -oE '63[0-9a-f]{8}' contract.asm | cut -c3-10 | sort -u
    
  3. 查询签名:

    curl "https://www.4byte.directory/api/v1/signatures/?hex_signature=0x<selector>"
    # Also try openchain.xyz/signature-database
    
  4. 识别危险操作码:

    操作码十六进制风险
    SELFDESTRUCTff严重 - 销毁合约
    DELEGATECALLf4高 - 执行任意代码
    CALLf1中 - 外部调用
    CALLCODEf2高 - 已弃用,危险
    CREATE2f5中 - 确定性部署
    TLOAD/TSTORE5c/5dEIP-1153 新增 - 瞬态存储
  5. 分析控制流:

    • 查找函数入口点的 JUMPDEST 位置
    • 跟踪 CALLER/ORIGIN 检查以识别访问控制
    • 查找用于状态访问的 SLOAD/SSTORE 模式
阶段 5:漏洞评级

根据当前区块链状态评估每项发现被利用的可能性:

评级标准操作
严重目前可直接利用,价值高立即编写 PoC
高满足特定条件后可利用进行分叉测试
中需要不太可能出现的条件记录
低仅存在理论可能,相关条件极不可能出现仅作备注

影响可能性的因素:

  • 当前区块链状态(所有者密钥、时间锁、余额)
  • 所需前置条件(存款、授权、区块编号)
  • Gas 成本与潜在收益的比较
  • MEV/抢先交易风险(攻击者能否进行三明治攻击?)
  • Flashbots 私有内存池的可用性
阶段 6:分叉验证
  1. 设置 Foundry 测试:

    // test/Exploit.t.sol
    pragma solidity ^0.8.20;
    import "forge-std/Test.sol";
    import "forge-std/interfaces/IERC20.sol";
    
    interface IFlashLoanProvider {
        function flashLoan(uint256 amount) external;
    }
    
    contract ExploitTest is Test {
        address target = 0x<TARGET_ADDRESS>;
        address attacker;
    
        function setUp() public {
            // Fork at specific block for determinism
            vm.createSelectFork(vm.envString("ETH_RPC_URL"), <BLOCK_NUMBER>);
            attacker = makeAddr("attacker");
            vm.deal(attacker, 1 ether);
        }
    
        function test_exploit() public {
            uint256 balanceBefore = attacker.balance;
    
            vm.prank(attacker);
            (bool success,) = target.call(abi.encodeWithSelector(0x<SELECTOR>));
    
            uint256 balanceAfter = attacker.balance;
    
            // CRITICAL: Verify actual fund extraction
            assertGt(balanceAfter, balanceBefore, "Exploit failed - no funds extracted");
        }
    
        // Flash loan exploit template
        function test_flashLoanExploit() public {
            uint256 targetBalanceBefore = IERC20(token).balanceOf(target);
    
            vm.prank(attacker);
            FlashLoanAttacker exploitContract = new FlashLoanAttacker(target);
            exploitContract.attack();
    
            assertLt(IERC20(token).balanceOf(target), targetBalanceBefore, "No drain");
            assertGt(IERC20(token).balanceOf(attacker), 0, "No profit");
        }
    }
    
  2. 在分叉上运行:

    forge test --fork-url $ETH_RPC_URL -vvvv --match-test "test_exploit"
    
  3. 验证资金是否被提取(而不只是调用成功):

    • 检查攻击者余额是否增加
    • 验证目标余额是否减少
    • 确认合约状态是否按预期改变
    • 调用成功并不意味着利用成功
阶段 7:生成报告

对于已确认的漏洞,创建报告:

# Vulnerability Report: [Contract Address]

## Summary
- **Severity**: Critical/High/Medium/Low
- **Type**: [Reentrancy/Access Control/Oracle Manipulation/etc.]
- **Impact**: [Amount at risk, what attacker gains]
- **Exploitable**: Yes/No (with current blockchain state)
- **Block confirmed**: [Block number of fork test]

## Vulnerable Function
\`\`\`solidity
function vulnerableFunction() public {
    // Vulnerable code
}
\`\`\`

## Attack Vector
1. Attacker calls function X with parameter Y
2. Contract fails to check Z
3. Funds transferred to attacker

## Proof of Concept
\`\`\`solidity
// Foundry test that demonstrates the exploit
function test_exploit() public {
    // Setup and exploit code
}
\`\`\`

## Execution Script (if confirmed)
\`\`\`bash
cast send <target> "vulnerableFunction()" --rpc-url $ETH_RPC_URL --private-key $PRIVATE_KEY
\`\`\`

## Remediation
- Add access control modifier
- Implement checks-effects-interactions pattern
- Use SafeMath for arithmetic (or upgrade to Solidity >= 0.8.0)
- Replace spot price with TWAP oracle

常见漏洞检查清单

访问控制
  • 所有敏感函数都使用了适当的修饰符
  • 所有者/管理员地址未被攻破
  • 多签需要足够数量的确认
  • 时间锁得到执行
  • 未使用 tx.origin 进行身份验证
  • 代理初始化函数无法被重复调用
  • UUPS 升级函数受到访问控制
  • 治理法定人数不能通过闪电贷绕过
重入
  • 外部调用前先更改状态(CEI 模式)
  • 资金转账使用了 ReentrancyGuard
  • 不会回调不可信合约
  • 已考虑 ERC-777 tokensReceived 钩子
  • 已检查跨函数重入
  • 已检查只读重入(getVirtualPrice、汇率)
算术(Solidity < 0.8.0)
  • 所有运算都使用 SafeMath
  • 不存在处理用户输入的 unchecked 代码块
  • 边界检查正确
  • 检查 0.5.x - 0.6.x 溢出漏洞
预言机 / 价格操纵
  • 不使用现货价格预言机(可被闪电贷操纵)
  • 在适用时使用 TWAP
  • 检查 Chainlink 心跳时效性
  • 关键路径使用多预言机聚合
  • 不将池余额用作价格来源
闪电贷
  • 状态不能被操纵后又在同一笔交易中读取
  • 不会在不可信外部调用后进行价格/比率检查
  • 所有可通过闪电贷调用的函数都设有重入保护
DeFi 特定检查
  • ERC-4626 已防护首个存款人份额通胀攻击(虚拟份额/资产)
  • Permit/EIP-2612 有重放保护(nonce、chainId)
  • 针对基于余额的记账提供了捐赠攻击防护
  • 在适用时提供 MEV 三明治攻击防护
  • 跨链桥:提供消息重放保护
外部调用
  • 检查返回值
  • 适当设置 Gas 限制
  • 正确处理 Fallback/receive 函数
Solidity 版本特定问题
版本问题检查项
< 0.8.0整数溢出/下溢SafeMath 的使用
< 0.6.0构造函数名称混淆constructor() 关键字
< 0.5.0未初始化的存储指针变量声明
Anytx.origin 身份验证访问控制模式
Any代理存储冲突是否使用 EIP-1967 槽位

误报指标

注意以下看似可利用、实则不可利用的模式:

  1. 多签待处理交易:kill() 可以成功,但需要 N-of-M 确认
  2. 用户专属余额:withdraw() 只会返还调用者存入的金额
  3. 时间锁定的释放:资金会转入硬编码地址,而非调用者地址
  4. 代理模式:即使代理没有检查,实现合约也可能有检查
  5. 调用成功但没有转账:函数执行完成,但没有 ETH 转移
  6. 附带即时还款检查的闪电贷:如果在结束时验证余额,就无法利用
  7. 可暂停合约:管理员可以暂停合约,但这是设计如此

在判定漏洞可利用之前,务必先在分叉环境中验证资金是否实际发生转移。

工具参考

工具用途命令
castRPC 调用、反汇编cast code/call/send/disassemble
forge分叉测试forge test --fork-url
anvil本地分叉节点anvil --fork-url $RPC
slither静态分析slither . --checklist
4byte.directory选择器查询API 或网页
openchain.xyz选择器查询API 或网页
Etherscan源代码、ABIAPI 或网页
Mythril符号执行myth analyze
Tenderly交易模拟网页 UI
Dedaub字节码反编译器dedaub.com

环境设置

所需环境变量:

export ETH_RPC_URL="https://eth-mainnet.g.alchemy.com/v2/<KEY>"
export ETHERSCAN_API_KEY="<KEY>"

所需工具:

# Foundry (forge, cast, anvil)
curl -L https://foundry.paradigm.xyz | bash
foundryup

# Slither
pip3 install slither-analyzer

# Node.js (for Hardhat if needed)
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox

示例工作流

# 1. Check contract value and code
cast balance 0x<address> --rpc-url $ETH_RPC_URL
cast code 0x<address> --rpc-url $ETH_RPC_URL > bytecode.hex

# 2. Check for proxy (EIP-1967 slot)
cast storage 0x<address> 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc --rpc-url $ETH_RPC_URL

# 3. Disassemble if unverified
cast disassemble $(cat bytecode.hex) > contract.asm

# 4. Extract and lookup selectors
grep -oE '63[0-9a-f]{8}' contract.asm | cut -c3-10 | sort -u | while read sel; do
  sig=$(curl -s "https://www.4byte.directory/api/v1/signatures/?hex_signature=0x$sel" | jq -r '.results[0].text_signature // "unknown"')
  echo "0x$sel: $sig"
done

# 5. Run slither on source (if available)
slither . --checklist 2>&1 | head -100

# 6. Create and run fork test
forge test --fork-url $ETH_RPC_URL -vvvv

# 7. Verify fund extraction (not just call success!)

# 8. Generate report if confirmed exploitable

数据库集成

审计多个合约时,请在 SQLite 中跟踪发现:

CREATE TABLE contracts (
  address TEXT PRIMARY KEY,
  balance_usd REAL,
  is_verified INTEGER,
  exploitable INTEGER DEFAULT 0,
  attack_type TEXT,
  notes TEXT
);

-- Update after analysis
UPDATE contracts SET
  exploitable = 0,
  notes = 'Multi-sig wallet. kill() requires confirmations. NOT exploitable.'
WHERE address = '0x...';

安全与法律说明

  • 仅在分叉环境中测试;未经明确授权,切勿在主网上测试
  • 记录所有发现,包括误报
  • 对于线上漏洞,请考虑负责任地披露
  • 注意执行漏洞利用可能涉及的法律问题
  • 此技能仅用于经授权的安全研究
  • Immunefi、Code4rena、Sherlock — 请通过官方漏洞赏金渠道报告

评论

支持 Markdown