用戶參與新專案時應著重分析合約中是否存在可疑代碼。

作者:kong

背景

從 DeFi 之夏到現在,我們在遭受各種漏洞、後門、跑路等層出不窮的手段洗禮后,總算學會了在 DEX 上參與新專案前,應先檢查代幣合約的許可權、代幣的持倉分佈及合約的代碼以保護自己的資產安全。 但相對的,壞人們的作惡手段也更加高明與隱蔽。 近期,慢霧安全團隊收到來自 PancakeSwap 社區使用者的求助,其參與專案時觀察到,在專案代幣沒有任何增發記錄的情況下,惡意使用者使用未被記錄的大量增發代幣捲走了池子中的資金。 慢霧安全團隊跟進分析此事件並將結果分享如下:

攻擊細節

惡意代幣 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 位元組的數據進行哈希後,正好得到惡意使用者的餘額存儲插槽位置 0x9d1f25384689385576b577f0f3bf1fa04b6829457a3e65965ad8e59bd165a716,這也正是合約中將 _balances 置於 slot0 位置的原因, 這極大方便了在內聯彙編中計算餘額實際的存儲位置。 然後使用 sstore 將合約中此儲存位置的值修改為當前時間的 6 次方,此時即完成了對指定地址的餘額修改。 隨後的內聯彙編操作類似,在此不做贅述。

至此,我們知道了專案方是在合約初始化時,通過內聯彙編的方式修改了指定地址餘額,隱蔽地增發了大量未被其他使用者獲悉的代幣,導致使用者在參與專案時被 Rug。

追蹤分析

通過 MistTrack[3] 分析此次事件獲利位址為 BSC 鏈上 0x000000481F40f88742399A627Cbc2Afb6Ec34FeD 與 0x00002b9b0748d575CB21De3caE868Ed19a7B5B56,共計獲利 114 萬 USDT,獲利位址轉移 USDT 的手續費來源為 Binance 交易所提款。

目前資金轉移情況如下圖:

此外,惡意合約創建者的手續費位址 0xb795ad917DAF9A1c98eE18E03E81FBBfb6D54355 同樣存在大量痕跡。

總結

此次事件中,專案方開源合約代碼以增加使用者信任度,通過未格式化的代碼降低代碼可讀性,並且使用內聯彙編來編寫直接修改使用者餘額存儲插槽數據的代碼,提高了代碼分析門檻。 其使用種種手段隱藏作惡痕跡,最後將池子席捲一空。 可以發現,在使用者的安全意識越來越強的情況下,作惡者的手段也越發隱蔽與高明。 據 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/

免責聲明:作為區塊鏈資訊平臺,本站所發佈文章僅代表作者及嘉賓個人觀點,與 Web3Caff 立場無關。 本文內容僅用於資訊分享,均不構成任何投資建議及要約,並請您遵守所在國家或地區的相關法律法規。