Write-up for Usurper's Throne
Overview
This challenge is meant to test a competitors understanding of SSTORE2Map. Specifically, why is the stored data prefixed with a 00 byte? Why is it critical that the stored data cannot be executed?
To make the challenge more interesting, the logic of the CREATE3 library was also modified to selfdestruct the proxy contract, allowing both the proxy contract and (potentially) the data contract to be redeployed.
In this challenge, the map was used to store DAO proposal calldata payloads, and were filtered before storing. The DAO also stored proposal descriptions (string) in this manner, but in a way that enabled collisions on the map key. As the descriptions were unfiltered, a collision between one proposal's description and another's calldata could cause the calldata to be modified after verification, allowing filtered methods to be called by the DAO.
Solving the puzzle
The challenger needs to get the DAO to call two methods: forgeThrone and addUsurper. The forgeThrone call is easy to execute by simply using the DAO as intended. To craft a call to addUsurper, you must perform the following steps:
- Pick a arbitrary, unused proposal ID, say
x. - Construct a proposal with
id = keccak256(x, x)with payload data beginning with theforgeThroneselector (0x6d2cd781) that can be self-destructed. To do this, notice that the first byte (6d) is aPUSH14opcode, meaning that when executed, the first 15 bytes of the proposal will execute as a valid instruction. Simply placing aselfdestruct(0xff) after this instruction will suffice. Execute the payload contract created above, self-destructing it. - Execute the payload contract created above, self-destructing it.
- Create a new proposal with
id = xwith any payload data, but with description equal to the new payload data:abi.encodeWithSelector(Throne.addUsurper.selector, solver). This will recreate the payload contract for proposalkeccak(x, x), but with no validation checks. - Vote for and execute proposal ID
keccak256(x, x).
Solve script
Check out our solve script below for more details.