DeFi 攻擊者的作惡手段越發高明與隱蔽。近日慢霧安全團隊收到來自 PancakeSwap 社群用戶的求助,有一個專案在代幣沒有任何增發記錄的情況下,惡意攻擊者使用未被記錄的大量增發代幣捲走了池子中的資金,慢霧安全團隊針對此事件進行詳細的追蹤分析。
(前情提要:慢霧報告》2023上半年區塊鏈安全與反洗錢報告)
(背景補充:慢霧|追緝Web3假錢包!MetaMask、imToken、TokenPocket..下載處有鬼 )
背景
從 DeFi 之夏到現在,我們在遭受各種漏洞、後門、跑路等層出不窮的手段洗禮後,總算學會了在 DEX 上參與新專案前,應先檢查代幣合約的許可權、代幣的持倉分佈及合約的程式碼以保護自己的資產安全。但相對的,壞人們的作惡手段也更加高明與隱蔽。
近期,慢霧安全團隊收到來自 PancakeSwap 社群使用者的求助,其參與專案時觀察到,在專案代幣沒有任何增發記錄的情況下,惡意使用者使用未被記錄的大量增發代幣捲走了池子中的資金。慢霧安全團隊跟進分析此事件並將結果分享如下:
延伸閱讀:pGALA 增發10億鎂》慢霧科技追因:管理員私鑰在 GitHub 洩露
攻擊細節
惡意代幣 IEGT 在 BSC 上的部署地址是 0x8D07f605926837Ea0F9E1e24DbA0Fb348cb3E97D [1]。我們通過區塊瀏覽器觀察其 Holders,發現在 dead 與 pair 地址持有大量 IEGT 代幣的情況下,合約記錄的 totalSupply 仍為 5,000,000。
通過進一步檢視這些代幣的來源可以發現,這些代幣在 0x00002b9b0748d575CB21De3caE868Ed19a7B5B56 中只有轉出記錄而沒有轉入記錄。
我們都知道,EIP20 標準 [2] 規定了代幣轉移時必須實現 Transfer 事件,包括在代幣鑄造時,從 0x0 地址進行轉移也必須進行事件記錄。區塊瀏覽器依賴這些標準的事件記錄進行資料統計。
因此,當在區塊瀏覽器中發現其代幣總額與實際數量不匹配時,則表明代幣在進行增發時並未進行事件記錄,導致區塊瀏覽器只統計了轉帳後相關地址的餘額變化,而沒有任何代幣增發記錄。據此,我們可以確定代幣合約中必然存在增發代幣的惡意程式碼。
此代幣合約的程式碼是開源的,想來是專案方為了增加專案的可信度。接下來我們對其原始碼進行分析。一般來說,進行代幣增發最簡單的方式就是實現一個直接增加指定地址餘額的方法。在當前合約中是通過定義一個 _balances 反射,對使用者的代幣餘額進行記錄。但經過檢查,合約中並未實現對指定地址的 _balances 進行修改的程式碼。
既然沒有發現直接增加餘額的程式碼,那麼專案方又是如何進行增發的呢?我們回顧下智慧合約的基礎知識,可以知道使用者代幣餘額的變化本質上就是修改了合約在鏈上儲存的資料狀態。因此,只要修改特定地址的 _balances 在合約中對應儲存的插槽資料,即可修改其代幣餘額。
我們先簡單回顧下 EVM 中計算合約資料儲存位置的基礎知識,對於反射型別 _balances 來說,其會根據其鍵值 k 與其所佔據位置 p 進行 keccak256 後得到偏移量,作為其儲存的插槽位置,即 keccak256 (k,p)。通過分析 IEGT 合約的資料儲存位置,我們可以發現其 _balances 引數所在位置為 slot0,那麼使用者的餘額儲存位置即為 keccak256 (address,0) 。
帶入惡意地址進行計算,可以得到其餘額儲存位置為 0x9d1f25384689385576b577f0f3bf1fa04b6829457a3e65965ad8e59bd165a716。隨後查詢此插槽資料變化,可以發現其在合約部署時已被修改為一個巨大的值。
因此,我們可以確定在 IEGT 合約部署初始化時,專案方就隱蔽地增發了大量的代幣,為 Rug 做好準備。接下來我們跟進其初始化函式,分析發現其在進行 _pathSet 操作時,通過內聯彙編對合約儲存進行了修改,並且未對程式碼進行格式化處理,以降低其可讀性。
跟進計算發現 y 值為 2b9b0748d575cb21de3cae868ed19a7b5b56,通過兩次 mstore 將記憶體 0~64 位元組的位置填充為 00000000000000000000000000002b9b0748d575cb21de3cae868ed19a7b5b56,而惡意增加代幣餘額的地址為 0x00002b9b0748d575CB21De3caE868Ed19a7B5B56。可以發現惡意使用者通過構造一連串的資料,計算使得正好可以得到其控制的目標地址。因此,我們也可以從編譯後的位元組碼中發現此計算後未進行填充的 「地址」。
緊接著通過 keccak256 對記憶體 0~64 位元組的資料進行 hash 後,正好得到惡意使用者的餘額儲存插槽位置 0x9d1f25384689385576b577f0f3bf1fa04b6829457a3e65965ad8e59bd165a716,這也正是合約中將 _balances 置於 slot0 位置的原因,這極大方便了在內聯彙編中計算餘額實際的儲存位置。然後使用 sstore 將合約中此儲存位置的值修改為當前時間的 6 次方,此時即完成了對指定地址的餘額修改。隨後的內聯彙編操作類似,在此不做贅述。
至此,我們知道了專案方是在合約初始化時,通過內聯彙編的方式修改了指定地址餘額,隱蔽地增發了大量未被其他使用者獲悉的代幣,導致使用者在參與專案時被 Rug。
追蹤分析
通過 MistTrack [3] 分析此次事件獲利地址為 BSC 鏈上 0x000000481F40f88742399A627Cbc2Afb6Ec34FeD 與 0x00002b9b0748d575CB21De3caE868Ed19a7B5B56,共計獲利 114 萬 USDT,獲利地址轉移 USDT 的手續費來源為 Binance 交易所提款。
目前資金轉移情況如下圖:
此外,惡意合約建立者的手續費地址 0xb795ad917DAF9A1c98eE18E03E81FBBfb6D54355 同樣存在大量痕跡。
延伸閱讀:Certik不背鍋:確定是Merlin「官方Rug Pull」!但200萬鎂補償恐跳票
總結
此次事件中,專案方開源合約程式碼以增加使用者信任度,通過未格式化的程式碼降低程式碼可讀性,並且使用內聯彙編來編寫直接修改使用者餘額儲存插槽資料的程式碼,提高了程式碼分析門檻。其使用種種手段隱藏作惡痕跡,最後將池子席捲一空。可以發現,在使用者的安全意識越來越強的情況下,作惡者的手段也越發隱蔽與高明。
據 SlowMist Hacked [4] 統計,截止目前,由於 Rug Pull 導致的損失金額接近 5 億美元。因此,使用者在參與新專案時應著重分析其合約中是否存在可疑的程式碼,儘量不參與合約未開源且未經過審計的專案。MistTrack 團隊也將持續跟進並監控此事件。
___
參考連結:
[1] https://bscscan.com/address/0x8d07f605926837ea0f9e1e24dba0fb348cb3e97d
[2] https://eips.ethereum.org/EIPS/eip-20
[3] https://misttrack.io/
[4] https://hacked.slowmist.io/