# LINE CTF 2021 - Reversing - Sakura
## TL;DR - Some Solidity smart contracts and the CLI application (webpacked) to manipulate them are given. - The flag is output when the state of multiple accounts is badly transitioned.   - The state referred to here is not the `State` defined in the contract. - Since there are only a few possible choices in the CLI application, **fuzzing** can solve this problem.
## Problem>Sakura is beautiful>nc 34.84.178.140 13000
The given files:```.├── contracts│   ├── Contract.sol│   └── openzeppelin│       └── contracts│           ├── access│           │   └── Ownable.sol│           └── utils│               └── Context.sol├── (flag)└── index.js```
## Solution `Contract.sol` is the core code of the app, `index.js` is the CLI application that manipulates the contract (the bytecode of the contract is embedded). `openzeppelin` is the standard library for contracts; thus, we do not need to read it. 
We access the app with `nc` (or run it locally) and then get the following results and select a choice.```txt❯ nc 34.84.178.140 13000Loading...Account: 0x66ab6d9362d4f35596279692f0251db635165871Account: 0x33a4622b82d4c04a53e170c638b944ce27cffce3Account: 0x0063046686e46dc6f15918b61ae2b121458534a5Set player account a balance of 100 ETHCompiling...Deploying the contract...Contract address: 0xe7cb1c67752cbb975a56815af242ce2ce63d3113--------------------------------------Welcome to Timeless Sakura Prediction Game
- You can get ETHs if you predict the future.- Oracle system that go beyond powerful time will judge.- We have GOD level BFT consensus model, Ethereum based single node blockchain.  (Yeah, We've solved the bloody byzantine general problem)- We use a smart contract engine based on a powerful EVM, the World computer.
--------------------------------------Today's question is
    What will be the weather tomorrow?
    1) Sunny    2) Rainy
--------------------------------------1) Bet2) Cancel3) Get Player's Balance4) Finalize```
First, we operate the app and then find the following. - The `Oracle response` we get in the `Finalize` choice is the opposite of the input of the `Bet` choice. It seems good if these are the same value. - The `Bet` choice reduces the balance of the accounts. If we cancel, it returns. - We can only enter a choice up to five times. - If proper input and proper order are not followed, transactions revert.   - Example: `Tx Reverted: [ 'Invalid state' ] { error: 'revert', errorType: 'VmError' }` - The number and content of transactions revert changes depending on the order of selection. There are probably transactions for multiple accounts. - etc.
Next, if we look for how `flag` is output, we find it in `index.js`. - `case 1: return 1 == I.sent().balance.gt(new Y.BN(G.convert("1000", "eth", "wei"))) && (console.log("win!"), console.log(k.readFileSync("/flag", "utf8"))), [2]` - We can see that the flag will probably be output when the balance of my account exceeds 1000 ETH. - If we change this 1000 value, the flag is actually be displayed at the timing of the `Finalize` choice.
We assume that there is a sequence of choices whose length is less than five that will output a flag. We can use a fuzzing approach.The code is as follows.```pyimport subprocessimport itertoolsfrom concurrent.futures import ProcessPoolExecutor
cands = [(1, 0), (1, 1), (1, 3), (2,), (3,)]
zenbu = [c + ((4,),) for c in itertools.product(cands, repeat=4)]
def work(tup):    print(tup)    proc = subprocess.Popen(["node", "sakura/index.js"],                            stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    s = "\n".join(str(x) for x in itertools.chain(*tup))+"\n"
    stdout, stderr = proc.communicate(s.encode())    stdout = stdout.decode()
    if "win!" in stdout or "LINECTF" in stdout:        print("!" * 1000, tup)        open("!!!.txt", "w").write(str(tup))        exit(0)
with ProcessPoolExecutor(max_workers=4) as executor:    executor.map(work, zenbu)```
We enter `(1,1),(1,3),(4,)` and then get the flag.
`LINECTF{S4kura_hira_hira_come_to_spring}`