---
# System prepended metadata

title: Beard | C0041103 - 第 6 週作業
tags: [Solidity 工程師實戰營第 4 期]

---

# 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 後，取的前８碼 ( 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 期`