Appearance
潜入“假冒者二号”,盗取合约财富!
Ethernaut 挑战又一关,这次的战场来到了名为“Impersonator Two”的合约。我们的目标直截了当——将合约中所有的资金全部收入囊中!
听起来是不是既刺激又有点难度?别担心,官方已经为我们提供了一些关键线索,让我们一起拨开迷雾,找到通往胜利的捷径。
合约核心机制:签名验证的艺术
“Impersonator Two”合约的核心在于其严谨的权限控制。它通过 ECDSA 签名 来验证操作者的身份。更具体地说,合约的安全性依赖于 合约的 owner 签发的特定签名。
合约中最重要的两个函数是:
setAdmin(bytes memory signature, address newAdmin): 用于设置合约的管理员。这个函数要求提供一个签名,并且只有当签名是由 合约的 owner 签发,并且验证通过后,才能成功更新admin地址。switchLock(bytes memory signature): 用于切换合约的locked状态,也就是是否允许提款。同样,这个函数也需要一个由 合约 owner 签发的有效签名。
关键的线索:隐藏在签名中的秘密
题目描述中特别强调了要“仔细查看 owner 用于锁定合约和设置 admin 的两个签名”。这绝非偶然,而是我们解决问题的关键所在。
通常,在 CTF 题目中,这些“签名”并不是随机生成的,它们可能包含了特定信息,或者是在某个特定状态下生成的。我们需要理解的是,setAdmin 和 switchLock 函数在验证签名时,会依赖于 nonce 和其他信息来生成待验证的哈希。
攻击思路:伪造签名,狸猫换太子
既然我们的目标是盗取资金,而 withdraw() 函数需要 onlyAdmin 权限且合约未被锁定,那么我们的攻击思路就非常明确了:
- 成为管理员: 通过某种方式,让合约相信我们就是合法的管理员。
- 解锁合约: 将
locked状态切换为false。 - 执行提款: 以管理员的身份,将合约中的所有资金提走。
这里最核心的挑战在于如何生成有效的签名。由于 _verify 函数会尝试通过 ECDSA.recover(hash, signature) 来恢复签名者的地址,并且要求其必须是合约的 owner(),这意味着我们需要 拥有合约 owner 的私钥 才能生成有效的签名。
难道我们真的需要破解 owner 的私钥吗?
Bingo!这就是这个题目的巧妙之处。在 Ethernaut 的设计中,它通常会模拟一个情境,让你拥有某个特定角色的私钥。在这个题目中,通过查看 MyScript.sol 提供的答案,我们不难发现:
vm.envUint("PRIVATE_KEY")和vm.addr(playerpk)表明,我们拥有的是 玩家(player) 的私钥。setAdminSig和switchLockSig这两个bytes memory变量,虽然看起来是乱码,但它们被 硬编码 进了脚本。这意味着,这些签名并不是我们动态生成的,而是 预先提供的,并且它们是由 某个特定地址(很可能是题目设计者预设的,或是与合约 owner 相关的某个地址)签名生成的。
答案揭晓:利用预设签名,完成身份伪造
MyScript.sol 的 run() 函数为我们揭示了答案:
- 获取玩家私钥: 脚本通过
vm.envUint("PRIVATE_KEY")和vm.addr(playerpk)获取玩家的私钥和地址,以便后续进行广播交易。 - 硬编码签名: 脚本中直接定义了
setAdminSig和switchLockSig。这些签名是 关键,它们被认为是能够通过_verify函数验证的有效签名。 - 执行操作:
ImpersonatorTwo(IMPERSONATORTWO_INST).setAdmin(setAdminSig, player);:使用预设的setAdminSig,将当前玩家的地址设置为合约的admin。ImpersonatorTwo(IMPERSONATORTWO_INST).switchLock(switchLockSig);:使用预设的switchLockSig,将合约的locked状态切换为false。ImpersonatorTwo(IMPERSONATORTWO_INST).withdraw();:以新的admin身份,执行提款操作,将合约中的所有资金转移到玩家地址。
总结:
“Impersonator Two” 题目巧妙地利用了 预设的签名 来绕过直接破解私钥的难题。通过分析合约的验证逻辑,并结合 MyScript.sol 中硬编码的签名,我们可以成功地伪造管理员身份,解锁合约,最终将合约中的所有资产据为己有。
这是一个关于理解智能合约权限控制、签名验证机制,以及如何利用 CTF 题目提供的线索来制定攻击策略的绝佳范例!