We are back at it!
In case you missed the previous post, here is the link to the previous post Ethernaut Walkthrough - Part 1
Levels
5. Telephone
Thought process
- Notice in
Telephone.sol
that we just have to callchangeOwner
such thattx.origin
andmsg.sender
are not the same and we can change the owner to whichever address we want
- Did a quick google on
“tx origin solidity”
which led me to this page https://docs.guardrails.io/docs/vulnerabilities/solidity/use_of_insecure_function#:~:text=,calls into a malicious contract.
- So
tx.origin
is the address of the account that sent the transaction
Solution
- Deploy the following contract
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.2 <0.9.0; contract TelephoneSolution { function solve(address telContractAddress) external { Telephone telephone = Telephone(telContractAddress); telephone.changeOwner(msg.sender); } } interface Telephone { function changeOwner(address _owner) external; }
- Get contract’s address by running the following in the browser console
await contract.address()
- Run the deployed
TelephoneSolution.solve
with the contract’s address
Takeaways
tx.origin
is the address which started the transaction
msg.sender
is the address which sent the message to the contract, and this could be another contract that was triggered by the transaction
6. Token
Thought Process
- I had to google for help on this one. I googled a little and found out that it had to do with integer underflow and overflow.
To hack this contract first you need to understand the concept of integer underflow and overflow. The overflow is a situation when uint (unsigned integer) reaches its byte size. Then the next element added will return the first variable element. - https://hackernoon.com/how-to-solve-the-ethernaut-games-level-5-token
Solution
1. Execute the following in the browser console
await contract.transfer(ethernaut.address, 21)
Takeaways
- We can check overflow with the following
if(a + c > a) { a = a + c; }
- An easier alternative is to use OpenZeppelin's SafeMath library that automatically checks for overflows in all the mathematical operators. The resulting code looks like this:
a = a.add(c);
- Or use solidity
0.8
onwards (refer to v0.8.0 Solidity Changes)
7. Delegation
Thought Process
- Went to research about
delegatecall
as suggested (reference: Solidity Docs) - Notice that
delegatecall
is similar to using another contract’s code as a library
- Notice that in
Delegate.sol
thepwn()
function changes the owner tomsg.sender
Solution
- Load this interface into remix IDE
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.18; interface Delegation { function pwn() external; fallback() external; receive() payable external; }
- Just overlay this interface on top of the level's contract address
- And call
pwn()
- Make sure that there is enough gas limit given
Takeaways
delegatecall
combined withfallback
is very much like composition in OOP (Object Oriented Programming)
- Solidity documentation on
fallback
function was not easy to understand, in my opinion.
- The first possible way to trigger
fallback
function was just calling a non-existent method on the target contract. This can be simulated by overlaying a wrong interface on an contract address and calling whichever method that was defined in the interface but not on the contract
- The second possible way to trigger
fallback
function was not easy to understand for me. I thought I could trigger solve the level another way by sendingEther
to it but turns out that does not work. Thefallback
function has to be markedpayable
for that to work