You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Mar 1, 2025. It is now read-only.
in this challenge, we become owner by leveraging an attack surface generated from implementing the low-level function delegatecall (from opcode DELEGATECALL).
CALL and DELEGATECALL opcodes allow ethereum developers to modularize their code.
standard external message calls are handled by CALL (code is run in the context of the external contract/function).
DELEGATECALL is almost identical, except that the code executed at the targeted address is run in the context of the calling contract (useful when writing libraries and for proxy patterns).
when a contract executes DELEGATECALL to another contract, this contract is executed with the original contract msg.sender, msg.value, and storage (in particular, the contract's storage can be changed).
in this problem, we are provided with two contracts. Delegate() is the parent contract, which we want to become owner of.
conveniently, the function pwn() is very explicit on being our target:
contractDelegate {
addresspublic owner;
constructor(address_owner) {
owner = _owner;
}
function pwn() public {
owner =msg.sender;
}
}
now, note that the variable owner is in the first slot of both contracts.
ordering of variable slots (and their mismatches) are what DELEGATECALL exploits in the wild usually explore.
this is important because we are dealing with opcodes, as every variable has a specific slot and should match in both the origin and destination contracts.
in our case, we when trigger the fallback in Delegate() to generate a delegate call to run pwn() in Delegation(), the owner variable (which is at slot0 of both contracts) updates Delegation()'s storage slot0.
the second contract, which we have access, is Delegation(), comes with has another convenience: a delegatecall() in the fallback function.
this fallback function is simply forwarding everything to Delegate():