此智慧合約利用一個函式庫來儲存兩個不同時區的兩個不同時間。 建構函數會為每個要儲存的時間創建兩個庫實例。 本關卡的目標是獲得該合約的所有權。
delegatecall 在 Level 6 - Delegation 用到過,技巧就是呼叫別人的 function 改自己的變數
存變數如何儲存和存取在 Level 8 - Vault
不同資料類型之間轉換在 Level 13 - Gatekeeper One
先看合約,Preservation
在第 21, 26 行皆使用 delegatecall 的方式呼叫另一個合約 LibraryContract
裡的 function,但是兩個合約宣告的變數並不相同,在 Level 6 - Delegation 中有提到過如果要使用 delegatecall 必須要有一樣的變數(包含宣告的順序),所以當我們使用關卡合約 Preservation
呼叫 LibraryContract
中的 setTime(uint256 _time)
時,以 LibraryContract
合約來看是修改 storedTime
;但其實修改到的是 Preservation
的 timeZone1Library
(皆為合約中第一個宣告的變數)。
剛好 Preservation
的第一個變數 timeZone1Library
是儲存呼叫對象的地址,代表上述提到的 bug 會導致呼叫完 20 行的 setFirstTime(uint256 _timeStamp)
後,timeZone1Library
被改變,下次再呼叫 setFirstTime(uint256 _timeStamp)
時其實是呼叫到不同地址的合約。
透過這個 bug,我們的攻擊流程:
setTime(uint _newOwnerAddress)
的惡意合約,其功能為將 owner 修改成自己setTime()
,參數為我們部署的惡意合約setTime()
,就會呼叫惡意合約的 function