Appearance
S2C10: CREATE2 Double Constraint
1. 问题
需要部署一个合约,其地址必须同时满足两个约束条件(如地址前缀匹配某些字节)。使用 CREATE2 的 salt grinding 找到合适的 salt。
2. 原因
合约使用地址约束作为访问控制 — 只有从特定地址调用的函数才能执行。通过 CREATE2 的确定性部署,攻击者可以"选择"部署地址。
3. 方案
- 分析合约中的地址约束条件(哪些字节必须匹配)
- 编写攻击合约
- 使用 salt grinding 找到满足双约束的 salt
- 部署攻击合约到目标地址
- 从该地址调用 mintFlag
solidity
// Salt grinding in Foundry
function findSalt() external {
bytes32 salt = 0;
while (true) {
address predicted = address(uint160(uint256(
keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, initCodeHash))
)));
if (checkConstraint1(predicted) && checkConstraint2(predicted)) {
break; // Found!
}
salt = bytes32(uint256(salt) + 1);
}
}
4. 遇到的陷阱
双约束 grinding 时间: 两个约束条件组合后,搜索空间可能很大。需要高效的计算方法。
5. 陷阱的原因
每个额外的字节约束使搜索空间缩小 256 倍。两个约束组合意味着 256^2 = 65536 倍更大搜索空间(最坏情况)。
6. 如何解决
使用 Rust 脚本或优化的 Foundry test 进行 grinding。对于 2-3 字节的约束组合,通常可以在 < 1000 万次迭代内找到。
7. 技术要点
| 要点 | 说明 |
|---|---|
| CREATE2 地址计算 | keccak256(0xff + deployer + salt + keccak256(initCode)) 的最后 20 字节 |
| 多重约束 grinding | 组合多个地址匹配条件增加搜索复杂度 |
| initCode hash | 相同的合约代码产生相同的 hash,变化 initCode(如 constructor 参数)可改变地址 |