关于 blockchain-security
blockchain-security 是一项用于分析和利用区块链 CTF 合约的技能,涵盖合约检查、存储与访问控制分析、常见攻击向量,以及验证挑战胜利条件。
主要功能
- 01反编译合约并映射存储布局
- 02检查特权操作与访问控制
- 03利用 delegatecall 和 CREATE 地址机制
- 04检查重入与签名漏洞
- 05部署利用合约并验证胜利条件
适用场景
- 01分析源代码或字节码形式的 CTF 合约
- 02测试存储布局与 delegatecall 利用方式
- 03检查签名、校验和访问控制缺陷
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ transilienceai/ communitytools --skill blockchain-security安装后在 Claude Code 中输入/blockchain-security确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
reference/create-address-prediction.mddelegatecall-attacks.mdstorage-layout.md详细介绍
区块链安全
快速开始
- 下载并反编译合约(源代码或字节码)
- 映射存储布局并识别特权操作
- 检查 delegatecall、CREATE 地址预测、重入和访问控制
- 使用 web3.py 或 cast/forge 部署攻击合约
- 验证胜利条件(isSolved/flag 端点)
区块链 CTF 挑战模式
# Get connection info
curl http://$HOST:$PORT/connection_info # -> PrivateKey, Address, TargetAddress, setupAddress
# RPC endpoint
RPC_URL="http://$HOST:$PORT/rpc"
# Win condition: Setup.isSolved() must return true
主要攻击向量
1. Delegatecall 存储操纵
当合约 A 对合约 B 执行 delegatecall 时,B 的代码会在 A 的存储上下文中运行。
- 部署一个存储布局与 A 相同的攻击合约
- 攻击合约通过 delegatecall 写入 A 的存储槽
- 关键:存储布局必须完全一致(槽位顺序相同)
- 参见 reference/delegatecall-attacks.md
2. CREATE 地址预测(Nonce 操纵)
通过 CREATE 生成的合约地址是确定性的:keccak256(rlp([sender, nonce]))[12:]
- 暴力枚举 nonce,找出能生成目标地址的 nonce
- 发送虚假交易(向自己转账)以递增 nonce
- 在恰好生成目标地址的 nonce 下部署攻击合约
- 参见 reference/create-address-prediction.md
3. 存储布局与槽位计算
- 映射:
keccak256(h(key) || uint256(slot_number))- 值类型:
h(k) = abi.encode(k)(左侧填充至 32 字节) - String/bytes:
h(k) = keccak256(k)
- 值类型:
- 通过
eth_getStorageAt读取私有变量 - 参见 reference/storage-layout.md
4. 空数组/零长度输入绕过
当函数遍历用户提供的数组以验证项目(签名、批准、投票)时,传入一个空数组会完全跳过循环。如果没有最小长度检查,验证就会被绕过。
- 检查:
for (uint i = 0; i < arr.length; i++),且没有require(arr.length >= N) - 利用方式:使用
[]调用函数以跳过所有验证
5. ECDSA 签名可塑性
原始 ecrecover 同时接受 (v, r, s) 和 (v', r, N-s)(其中 N = secp256k1 阶,v 在 27↔28 之间翻转)。如果合约根据原始字节的哈希对签名去重,可塑形式的哈希不同,但恢复出的签名者相同。
- 检查:使用
ecrecover时没有强制要求s <= N/2(OpenZeppelin 的 ECDSA.sol 会强制执行此要求) - 利用方式:获取一个已知有效的签名,计算
new_s = N - s,翻转v,并将其作为“新”签名提交
6. 常见漏洞类别
| 漏洞 | 检查项 |
|---|---|
| 重入 | 状态更新前进行外部调用 |
| 访问控制 | 缺少 onlyOwner / msg.sender 检查 |
| 整数溢出 | Solidity < 0.8.0 且未使用 SafeMath |
| Delegatecall 注入 | delegatecall 目标由用户控制 |
| tx.origin 身份验证 | 使用 tx.origin 而非 msg.sender |
| Selfdestruct | 强制发送 ETH,重置合约 nonce |
| 随机数薄弱 | 将 blockhash/timestamp 作为熵源 |
| 空数组绕过 | 循环验证没有最小长度检查 |
| 签名可塑性 | 使用原始 ecrecover,未对 s 进行规范化 |
工具
# web3.py essentials
from web3 import Web3
w3 = Web3(Web3.HTTPProvider(RPC_URL))
acct = w3.eth.account.from_key(PRIVATE_KEY)
# Read private storage
w3.eth.get_storage_at(contract_addr, slot)
# Deploy contract
from solcx import compile_source, install_solc
install_solc("0.8.13")
compiled = compile_source(source, output_values=["abi", "bin"], solc_version="0.8.13")
# Send raw bytecode deployment
tx = {'data': bytecode, 'gas': 3000000, 'gasPrice': w3.eth.gas_price, 'nonce': nonce, 'chainId': chain_id}
signed = acct.sign_transaction(tx)
w3.eth.send_raw_transaction(signed.raw_transaction)
参考
关键规则
- 攻击前始终读取存储(链上的私有变量可以读取)
- 利用 delegatecall 时,精确匹配存储布局
- 暴力枚举 CREATE nonce 时,系统性检查 0-100000+ 范围内的 nonce
- CTF 实例通常是临时的——编写完整攻击脚本以提高速度
评论
支持 Markdown