跳到主要内容

Description

For this challenge, we have to deal only with a single Smart Contract called Switch. The goal of the challenge is to gain ownership of the contract, overriding the value of the owner state variable.

Code

/**
*Submitted for verification at Etherscan.io on 2022-08-13
*/

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

/**
* @title Claim ownership of the contract below to complete this level
* @dev Implement one time hackable smart contract (Switch)
*/
contract Switch {
address public owner;

modifier onlyOwner() {
require(msg.sender == owner, "caller is not the owner");
_;
}

constructor() {
owner = msg.sender;
}

// Changes the ownership of the contract. Can only be called by the owner
function changeOwnership(address _owner) public onlyOwner {
owner = _owner;
}

// Allows the owner to delegate the change of ownership to a different address by providing the owner's signature
function changeOwnership(
uint8 v,
bytes32 r,
bytes32 s
) public {
require(ecrecover(generateHash(owner), v, r, s) != address(0), "signer is not the owner");
owner = msg.sender;
}

// Generates a hash compatible with EIP-191 signatures
function generateHash(address _addr) private pure returns (bytes32) {
bytes32 addressHash = keccak256(abi.encodePacked(_addr));
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", addressHash));
}
}

Solution

我们可以看到在changeOwnership中只验证了VRS的有效性,但是没有认证ecrecover出来的地址是否是owner就直接切换了,所以我们随便传入一个签名都可以做到。

uint256 privateKey = 123456;
bytes32 hashedMessage = bytes32(0);

// sign the hashed message
(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, hashedMessage);