Appearance
S1C11: Who Can Call Me?
1. 问题
合约只允许从特定的调用者地址调用 mintFlag。需要部署一个合约在特定地址,然后从这个"被允许"的地址发起调用。
2. 原因
合约检查 msg.sender 是否等于某个预计算的地址。该地址由 CREATE2 或 CREATE 的确定性部署决定 — 需要找到合适的 salt 使部署地址匹配要求。
3. 方案
- 分析合约中允许的调用者地址的计算方式
- 使用
CREATE2的 salt grinding 技术找到合适的 salt - 部署攻击合约到允许的地址
- 从该合约调用
mintFlag
solidity
// 在 Foundry 中 grinding salt
for (uint256 salt = 0; salt < MAX; salt++) {
address predicted = computeCreate2Address(deployer, salt, initCodeHash);
if (predicted == targetAddress) {
// Found it!
break;
}
}
4. 遇到的陷阱
Salt grinding 计算量: 如果目标地址约束很强,可能需要 grinding 数百万甚至数十亿个 salt。
5. 陷阱的原因
CREATE2 地址 = keccak256(0xff ++ deployer ++ salt ++ keccak256(initCode))。要匹配特定地址前缀或精确地址,平均需要 2^n 次尝试(n 为约束位数)。
6. 如何解决
使用 Rust 或优化后的 Solidity 脚本进行 salt grinding。Foundry 的 vm.computeCreate2Address 可以辅助预测。如果约束不强(如前几个字节匹配),在合理时间内可以找到。
7. 技术要点
| 要点 | 说明 |
|---|---|
| CREATE2 | 确定性合约部署,地址由 sender + salt + initCodeHash 决定 |
| Salt grinding | 暴力搜索 salt 值以获得目标地址 |
| 地址约束 | 越精确的地址匹配(更多字节)需要越多计算量 |