In the previous content, I learned that storage uses slots to store data. The delegatecall function has an interesting feature: when the external call using the delegatecall function involves the modification of the storage variable, it is modified according to the slot position instead of the variable name.
When contract B calls the testDelegatecall() function, the value of address c of contract B will change to the address of contract A, while address a remains unchanged. Because the function test() of contract A changes the value of slot1, similarly, when running in contract B, it also changes the value of slot1, that is, the value of address c.
We can see that there are two contracts. There is only one pwn function in the Lib contract to modify the owner of the contract. There is a fallback function in the HackMe contract. The content of the fallback function is to use the delegatecall to call the function in the Lib contract. We need to use HackMe.fallback() to trigger the delegatecall function to call Lib.pwn() to change the owner in the HackMe contract to itself.
Now let’s look at the logic of the entire attack:
1. The attacker calls attack() to launch an attack, and the attack function first calls HackMe.pwn();
2. There is no pwn function in the HackMe contract, and HackMe.fallback() is triggered at this time;
3. HackMe.fallback() uses deldegatecall to call the function in the Lib contract. The function name is msg.data, which is “pwn()”, and there happens to be a function named pwn in the Lib contract, so it runs in the HackMe contract pwn function;
4. The pwn function modifies the value of the slot0 position (that is, the owner of the HackMe contract) to msg.sender (that is, the attacker), which eventually causes the owner of the HackMe contract to become an attacker.
- When using delegatecall, it should be noted that the address of the called contract cannot be controllable;
- In a more complex contract environment, it is necessary to pay attention to the declaration order and storage location of variables. Because when using delegatecall for external calls, the data stored in the corresponding slot of the contract will be modified according to the data structure of the called contract, which may cause unexpected variable coverage when the data structure changes.
If you want to learn more about smart contracts and blockchain knowledge, welcome to the blockchain exchange community CHAINPIP community to exchange and learn together~ Community address: https://www.chainpip.com/