Ethernaut Level 6 — Delegation

Tellico Lungrevink
2 min readAug 8, 2022

The Ethernaut is a Web3/Solidity based wargame inspired on overthewire.org. Here’s the solution to the Level 6 Delegation.

The challenge description states:

The goal of this level is for you to claim ownership of the instance you are given.Things that might help- Look into Solidity’s documentation on the delegatecall low level function, how it works, how it can be used to delegate  operations to on-chain libraries, and what implications it has on  execution scope.- Fallback methods- Method ids

The description heavily hints what needs to be done. Let’s look at the code. There are two contracts: delegation and delegate . The delegation is the one deployed and contains a delegatecall in the fallback function. The delegatecall is unsafe, because because is called for user-suppplied data (from msg.data ):

A contract which is a target of the delegatecall is called delegate . It contains a funtion named pwn , which sets the contract owner to a current sender. What’s important, its owner property is at the same position, as the same property in the delegation contract.

As it turns out, when the delegatecall is run, it modifies caller’s data, not callee’s. In this case, the delegation contract running the delegate’s pwn function, will set it’s own owner to a sender. Which is all the attacker needs!

How to do it in practice? First I’ll need a 4-byte function call hash:

> callHash = web3.eth.abi.encodeFunctionCall({name:”pwn”, type: “function”, inputs:[]},[])‘0xdd365b8b’

Now I need to send a transaction to the delegation contract to force the fallback call. The call data will be the callHash I’ve calculated above to trigger the pwn function:

> await web3.eth.sendTransaction({"to": instance, "from": player, "data": callHash})

That’s it! The contract has been take over, and the challenge can be submitted.

--

--