# Table of contents- ## [Crackme](#challenge-name-crackme) ---
# Notes
### For some of the challenges, a rinkeby testnet wallet account is required. Make sure to get one before doing.
### I'm using Ubuntu 20.04 as my environment.
---
# Challenge name: Crackme![Question screenshot](../images/crackme.png)
## Information
Contract address: ```0xDb2F21c03Efb692b65feE7c4B5D7614531DC45BE```
> crackme.sol
```pragma solidity ^0.6.0;
contract crack_me{
    function gib_flag(uint arg1, string memory arg2, uint arg3) public view returns (uint[]){        //arg3 is a overflow        require(arg3 > 0, "positive nums only baby");        if ((arg1 ^ 0x70) == 20) {            if(keccak256(bytes(decrypt(arg2))) == keccak256(bytes("offshift ftw"))) {                uint256 check3 = arg3 + 1;                if( check3< 1) {                    return flag;                }            }        }        return "you lost babe";    }
    function decrypt(string memory encrypted_text) private pure returns (string memory){        uint256 length = bytes(encrypted_text).length;        for (uint i = 0; i < length; i++) {            byte char = bytes(encrypted_text)[i];            assembly {                char := byte(0,char)                if and(gt(char,0x60), lt(char,0x6E))                { char:= add(0x7B, sub(char,0x61)) }                if iszero(eq(char, 0x20))                {mstore8(add(add(encrypted_text,0x20), mul(i,1)), sub(char,16))}            }        }        return encrypted_text;    }}```
Personally i think this is similar to a reverse-engineer challenge. I need to call the contract's ```gib_flag()``` function to get the flag.
---gib_flag | arg1 | arg2 | arg3---------|------|------|-----condition | user_input ^ 0x70 == 20 |decrypt(user_input) == "offshift ftw"| user_input + 1 < 0correct input|Dec: 100 or Hex: 0x64|"evvixyvj vjm"|2**256 - 1 (Will cause overflow after += 1)
---
## My solution1. using python's brownie library2. run ```brownie init crackme_ctf```3. copy ```chall.sol``` into the generated ```contracts/``` folder4. do some modification to the ```chall.sol``` to make it compilable```> crackme_ctf/contracts/chall.solpragma solidity ^0.6.0;
contract crack_me{    string flag = "yeah"; // <- i added this line
    function gib_flag(uint arg1, string memory arg2, uint arg3) public view returns (string memory){        //arg3 is a overflow        require(arg3 > 0, "positive nums only baby");
    .    .    .```5. copy the entire code from ```chall.sol``` to another ```test.sol``` file in ```contracts/```
> crackme_ctf/contracts/test.sol```pragma solidity ^0.6.0;
contract hello{ // <- remember to change the contract name
    function gib_flag(uint arg1, string memory arg2, uint arg3) public view returns (string memory){        //arg3 is a overflow        require(arg3 > 0, "positive nums only baby");        if ((arg1 ^ 0x70) == 20) {            if(keccak256(bytes(decrypt(arg2))) == keccak256(bytes("offshift ftw"))) {                uint256 check3 = arg3 + 1;                if( check3< 1) {                    return "yeah you reversed it"; // <- replaced the flag variable with a string                }            }        }        return "you lost babe";    }
    // *** remember to change this function to public     function decrypt(string memory encrypted_text) public pure returns (string memory){        uint256 length = bytes(encrypted_text).length;        for (uint i = 0; i < length; i++) {            byte char = bytes(encrypted_text)[i];            assembly {                char := byte(0,char)                if and(gt(char,0x60), lt(char,0x6E))                { char:= add(0x7B, sub(char,0x61)) }                if iszero(eq(char, 0x20))                {mstore8(add(add(encrypted_text,0x20), mul(i,1)), sub(char,16))}            }        }        return encrypted_text;    }}```6. write a script to bruteforce the value for arg3> crackme_ctf/scripts/test.py```from brownie import *
def main():    accounts.add()  # Create a new local wallet account
    d = hello.deploy({"from":accounts[0]})
    target = "offshift ftw"    stored = ""
    # Valid ascii characters    for _ in range(32,128):        stored += str(chr(_))
    ans = ""    for x in range(len(target)):        for c in range(128):            tmp = d.decrypt(stored[c])            if(tmp == target[x]):                ans += stored[c]                break
    print(ans)``````Output of: $ brownie run scripts/test.py
Brownie v1.13.0 - Python development framework for Ethereum
CrackmeCtfProject is the active project.
Launching 'ganache-cli --port 8545 --gasLimit 12000000 --accounts 10 --hardfork istanbul --mnemonic brownie'...
Running 'scripts/test.py::main'...mnemonic: 'piece multiply pet next panel off special sketch dose illness domain naive'Transaction sent: 0x128e7a11fc664a3592afdb4db2550d3b368ccc2a95b8f0f6bea8a8442350eb64  Gas price: 0.0 gwei   Gas limit: 12000000   Nonce: 0  hello.constructor confirmed - Block: 1   Gas used: 287601 (2.40%)  hello deployed at: 0x3194cBDC3dbcd3E11a07892e7bA5c3394048Cc87
evvixyvj vjm <- user_input for arg3
Terminating local RPC client...```7. ```$ brownie console --network rinkeby``````Brownie v1.13.0 - Python development framework for Ethereum
CrackmeCtfProject is the active project.Brownie environment is ready.>>> myWallet = accounts.add(YOUR_OWN_RINKEBY_NETWORK_WALLET_PRIVATE_KEY)>>> d = web3.eth.contract(... address="0xDb2F21c03Efb692b65feE7c4B5D7614531DC45BE",... abi=crack_me.abi... )>>> d.functions.gib_flag(100,"evvixyvj vjm",2**256-1).call()```
8. Process the error manually
```  File "<console>", line 1, in <module>  File "web3/contract.py", line 954, in call    return call_contract_function(  File "web3/contract.py", line 1529, in call_contract_function    raise BadFunctionCallOutput(msg) from eBadFunctionCallOutput: Could not decode contract function call gib_flag return data b'\x00\x00\x00.......\x00\x00\x004' for output_types ['string']>>> return_data = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00g\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x007\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x005\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00_\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Y\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00u\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00_\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00K\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00_\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00m\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x005\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004">>> for a in return_data:...     if(a != '\x00'):...         print(a,end='')...C0ngr@75_Y0u_CR@CK3D_m3854>>>```
## Flag: flag{C0ngr@75_Y0u_CR@CK3D_m3854}
---