# Beard | C0041103 - 第 6 週作業 本週作業在完成 Ethernaut 1 ~ 10關,這邊按照順序寫下: ## 1. Fallback 題目如下: {%gist BeardYing/4ccb583197057a930c7a01bc6e5edec2 %} 主要工作為提領光合約的balance,基本上需要操作 *withdraw()* 功能,而 *withdraw()* 被 onlyOwner 保護著,所以表示先需要取得 Owner 角色! <br/> 首要工作取得 Owner 角色,分析程式後可以藉由 *contribute()* 以及 *receive()* 取得。 - contribute() 當 傳入金額 < 0.001 ether 可以貢獻累積金額,但是需要累積到達目前Owner的金額 (1000 ether)才可以取得變成 Owner - receive() 需要為既有貢獻者(已經有貢獻紀錄),並且本次傳入的貢獻金額 > 0 ,就可以Owner 此時解題的方法就為兩種: 1. ❌ 藉由 contribute() 貢獻金額,然後累積超過 1000 ether,再進行 withdraw() 2. ✅ 藉由 contribute() 貢獻一點點金額,然後利用 receive() 再進行貢獻,即可取得Owner,再進行 withdraw() ❌ 表示並非好方法,所以採取 2 解法: 1. 開啟瀏覽器 Console 操作 2. <code>await contract.owner()</code> - 可以查看目前的擁有者,為合約部署者錢包地址 3. <code>await contract.contribute({value: 1})</code> - 貢獻 1 wei 給此合約,成為既有貢獻者 4. <code>await contract.sendTransaction({value: '1'})</code> - 再次貢獻 1 wei,成為 Owner 5. <code>await contract.owner()</code> - 可以發現擁有者已經為操作者錢包地址 6. <code>await contract.withdraw()</code> - 提款 7. 點擊介面 “Submit instance” 按鈕,收工! ![](https://i.imgur.com/xV1qnRJ.png) :::info 可以在 console 中利用 help() 取得相關的操作資訊 ::: <br/><br/> ## 2. Fallout {%gist BeardYing/b72e035294e861c77aa1eb38f2b67310 %} 本題題目要求取得 Owner 角色,大致瀏覽後,可以看到有一 function - *Fal1out()* 可以設定 owner,雖然上面標示 /* constructor */,但是此一 function 並非與 contract 同名(而且0.6版本已經不支援合約同名的 constructor) 所以此題需要: 1. <code>await contract.owner() </code> - 先查看一下擁有者,應該為 address(0) 3. <code>await contract.Fal1out()</code> - 更換成 Owner 4. <code>await contract.owner() </code> - 查看一下目前擁有者,應該為自己錢包地址 5. 點擊介面 “Submit instance” 按鈕,收工! ![](https://i.imgur.com/9pMJLxn.png) <br/><br/> ## 3. Coin Flip {%gist BeardYing/5400a448ab79a51103c9838687e5ceb4 %} 此題要連續猜對硬幣正反(true/false) 10次, 看題目中的弱點為使用可預期或是開放的鏈上數據,只要撰寫另份合約進行預先計算,就可以得知答案,所以撰寫以下合約程式進行連續攻擊。 <small>攻擊合約</small> {%gist BeardYing/1d4405a5275829cdaa729361c4a270bc %} <small>Remix部署與攻擊,點擊attackCoin成功10次:</small> ![](https://i.imgur.com/2UfMS4I.png) 1. <code>await contract.consecutiveWins()</code> - 可以查看成功次數 ( o.words[0]) 2. 開啟 Remix 部署攻擊合約 3. 持續慢慢點擊 attackCoin 4. <code>await contract.consecutiveWins()</code> - 確認成功次數超過10次 ( o.words[0]) 5. 點擊介面 “Submit instance” 按鈕,收工! <small>攻擊結果:</small> ![](https://i.imgur.com/XsIeRoV.png) ## 4. Telephone {%gist BeardYing/5ed450330904f3a0b915da0bc42ea8d8 %} 此題題目要取得 owner,可以看到突破點為:changeOwner, 發現條件為:<code>tx.origin != msg.sender</code> 即可切換成owner 這時候根據tx.origin跟 msg.sender的差異即可攻破,撰寫一個中介的合約, 可以達到 **呼叫流程如下:** wallet <i><-- 呼叫 --></i> attack contract <i><-- 呼叫 --></i> target contract **取得資訊如下:** | wallet | attack contract | target contract | | -------- | -------- | -------- | | | *tx.origin*: wallet<br/>*msg.sender*: wallet | *tx.origin*: wallet<br/>*msg.sender*: attack contract | attack contract 如下: {%gist BeardYing/c6caf6260d3925729bbef5738f8fa8e6 %} 1. 在 console 中,使用 instance 可以取得合約地址 2. 使用 <code>await contract.owner()</code> - 先查看合約 Owner 3. 利用Remix部署合約 Telephone-attack.sol ,並且傳入參數 步驟一取得的地址 4. 呼叫攻擊合約 <code>attack()</code> - 更換合約Owner 5. 使用 <code>await contract.owner()</code> - 確認合約 Owner 是否正確拿下 6. 點擊介面 “Submit instance” 按鈕,收工! <small>Remix部署與攻擊:</small> ![](https://i.imgur.com/KnllTTy.png) <small>攻擊結果:</small> ![](https://i.imgur.com/Fgl6Gxe.png) ## 5. Token {%gist BeardYing/5be618fb80490602eeba6bdc21b15517 %} 這題是需要得到大量或是額外的Token,所以查看transfer中可以看到 require的判斷是用一般的運算,在v0.6版本是會有 overflow的議題存在,所以這題思路是讓合約運算 overflow 達到取得額外的 Token 1. <code>await contract.balanceOf(*attacker address*)</code> - 先查看一下自己的 Token 數量 2. <code>await contract.totalSupply()</code> -- 取得總發行量,為了要讓運算 overflow 3. <code>await contract.transfer('0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2', toWei('21000000'));</code> -- 隨便轉給一個地址(幸運兒),輸入最大發行量 4. <code>await contract.balanceOf(*address B*)</code> -- 查看目前 Token 數量,發現已經成功取得大量的Token 5. 點擊介面 “Submit instance” 按鈕,收工! <small>攻擊結果:</small> ![](https://i.imgur.com/XeMvDpc.png) <br/><br/> ## 6. Delegation {%gist BeardYing/d2e9c54a08054abe526527a2c5f788ec %} 此關過關條件為取得 Owner,此題可以藉由 Contract Delegation 中的 fallback function,憑藉 delegatecall 呼叫 Delegate 中的 funciton,來利用 <code>Delegate:pwn()</code> 以切換 owner 帳號 另外這題還包還了另外一個項目,如果要利用交易送出,該如何取得function name ? 會需要將呼叫的 function 進行 keccak256 hash 後,取的前8碼 ( 4個bytes ),這裡我藉著[線上工具](https://emn178.github.io/online-tools/keccak_256.html)轉換出 pwn() = **dd365b8b**15d5d78ec041b851b68c8b985bee78bee0b87c4acf261024d8beabab 1. 開啟Console 2. <code>contract.sendTransaction({data: 'dd365b8b'})</code> - 送出交易,會被 fallback 接收,轉而 delegatecall Delegate合約 3. <code>contract.owner()</code> - 取得驗證owner 4. 點擊介面 “Submit instance” 按鈕,收工! <small>攻擊結果:</small> ![](https://i.imgur.com/FrggCje.png) :::warning ### 特殊狀況 這裡我有另外用 Remix 嘗試,會發生問題 由於上堂課中,有製作國王金庫的題目,想試試 Remix 的 delegatecall 是否也可以解決此題,按照流程將 Delegate.sol 通過編譯後,將 at Address 設置入 contract Address,後來調用 pwn() 發現有送出交易,但是在Remix中會發現 internal tx會發生 gas 的問題,就沒有正常的轉換 Owner [後記] 後來經過 Jimbo 提點,需要在 Metamask 中手動調高 gas limit,這樣就可以正常的運作完成! ![](https://i.imgur.com/ghHKkoC.png) ::: <br/><br/> ## 7. force {%gist BeardYing/ebbcabde69767a89faaffb1796ab05e6 %} 這關其實一開始完全不知如何下手,後來找尋後發現可以使用 selfdestruct 來把自爆的合約的款項硬是塞給指定地址,真的是太黑暗了,想收也無法不收! 1. 部署 attack合約 (送出時介面記得要順便設定 msg.value) {%gist BeardYing/664b065def10fc71adb35dabaf102450 %} ![](https://i.imgur.com/mb0KGal.png) 2. 點擊介面 “Submit instance” 按鈕,收工! <small>攻擊結果:</small> ![](https://i.imgur.com/3BaVN2F.png) ![](https://i.imgur.com/TVPPPpc.png) <br/><br/> ## 8. Valut {%gist BeardYing/c1405acfef2043c56bd4283342864b57 %} 這題目非常簡單,就是解開金庫即可,看完整份Code後,發現只要利用 unlock 解開 password即可,但是 password 的可視性目前設定成 private,所以無法直接呼叫來看,所以就想到開 slot 來看了,但是語法不熟,後來找到以下方法: 1. await web3.eth.getStorageAt(*contract address*, 0, console.log); 發現印出 0x00....001 > bool locked = true 2. await web3.eth.getStorageAt(*contract address*, 1, console.log); 發現印出 0x412076657279207374726f6e67207365637265742070617373776f7264203a29 > 挖到 bytes32 password 3. contract.unlock('0x412076657279207374726f6e67207365637265742070617373776f7264203a29') - 塞入取得的 password 解鎖 4. 點擊介面 “Submit instance” 按鈕,收工! <small>攻擊結果:</small> ![](https://i.imgur.com/ZuxG82H.png) :::info 鏈上數據公開透明,敏感資訊不要放在鏈上啊! ::: <br/><br/> ## (Not yet) 9. King {%gist BeardYing/f3c2a1884d4da20ced4c97afa2242b13 %} ## (Not yet) 10. Reentrance {%gist BeardYing/db6842e2814734e25d46575ad7788ecd %} REF: - 查詢語法時,發現學習的好資源: https://solidity-by-example.org/ ###### tags: `Solidity 工程師實戰營第 4 期`