本文將揭開一個大規模自動化的,透過「退出騙局」方式進行資產收割的駭客團隊。

作者:Certik

封面: Photo by Milad Fakurian on Unsplash

近日,CertiK 安全專家團隊頻繁地偵測到多起手法相同的「退出騙局」,也就是我們俗稱的 Rug Pull。

在我們進行深入挖掘後發現,多起相同手法的事件都指向同一個團夥,最終關聯到超過 200 個 Token 退出騙局。這預示著我們可能發現了一個大規模自動化的,透過「退出騙局」方式進行資產收割的駭客團隊。

在這些退出騙局中,攻擊者會創建一個新的 ERC20 代幣,並用創建時預挖的代幣加上一定數量的 WETH 創建一個 Uniswap V2 的流動性池。

當鏈上的打新機器人或使用者在該流動性池購買一定次數的新代幣後,攻擊者則會透過憑空產生的代幣,將流動性池中的 WETH 全部耗盡。

由於攻擊者在憑空獲取的代幣沒有體現在總供應量(totalSupply),也不觸發 Transfer 事件,在 etherscan 是看不到的,因此外界難以感知。

攻擊者不僅考慮了隱蔽性,還設計了一個局中局,用來麻痺擁有初級技術能力,會看 etherscan 的用戶,用一個小的問題來掩蓋他們真正的目的…

深入騙局

我們以其中一個案例為例,詳解一下該退出騙局的細節。

被我們偵測到的實際上是攻擊者用巨量代幣(偷偷 mint 的)耗乾流動性池並獲利的交易,在該交易中,項目方共計用 416,483,104,164,831(約 416 萬億)個 MUMI 兌換出了約 9.736 個 WETH,耗乾了池子的流動性。

然而該交易只是整個騙局的最後一環,我們要了解整個騙局,就需要繼續往前追溯。

部署代幣

3 月 6 日上午 7 點 52 分(UTC 時間,下文同),攻擊者地址(0x8AF8)Rug Pull 部署了名為 MUMI(全名為 MultiMixer AI)的 ERC20 代幣(地址為 0x4894),並預挖了 420,690,000(約 4.2 億)個代幣且全部分配給合約部署者。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

預挖代幣數量與合約原始碼相對應。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

添加流動性

8 點整(代幣創建 8 分鐘後),攻擊者地址(0x8AF8)開始增加流動性。

攻擊者地址(0x8AF8)調用代幣合約中的 openTrading 函數,透過 uniswap v2 factory 創建 MUMI-WETH 流動性池,將預挖的所有代幣和 3 個 ETH 添加到流動性池中,最後獲得約 1.036 個 LP 代幣。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密
Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

從交易細節可以看出,原本用於添加流動性的 420,690,000(約 4.2 億)個代幣中,有 63,103,500(約 6300 萬)約個代幣又被發送回代幣合約(地址 0x4894),透過查看合約原始碼發現,代幣合約為每筆轉帳收取一定的手續費,而收取手續費的地址正是代幣合約本身(具體實現在「_transfer 函數中」)。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

奇怪的是,合約中已經設定了稅務地址 0x7ffb(收取轉帳手續費的地址),最後手續費卻被發到代幣合約本身。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

因此最後被添加到流動性池的 MUMI 代幣數量為扣完稅的 357,586,500(約 3.5 億),而不是 420,690,000(約 4.3 億)。

鎖定流動性

8 點 1 分(流動性池創建 1 分鐘後),攻擊者地址(0x8AF8)鎖定了透過添加流動性獲取的全部 1.036 個 LP 代幣。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

LP 被鎖定後,理論上攻擊者地址(0x8AF8)擁有的所有的 MUMI 代幣便被鎖定在流動性池內(除開作為手續費的那部分),因此攻擊者地址(0x8AF8)也不具備通過移除流動性進行 Rug Pull 的能力。

為了讓用戶放心購買新推出的代幣,許多項目方都是將 LP 進行鎖定,意思是項目方在說:“我不會跑路的,大家放心買吧!”,然而事實真的是這樣嗎?顯然不是,這個案例就是如此,讓我們繼續分析。

Rug Pull

8 點 10 分,出現了新的攻擊者地址②(0x9DF4),Ta 部署了代幣合約中聲明的稅收地址 0x7ffb。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

這裡有三個值得一提的點:

1. 部署稅收地址的地址和部署代幣的地址並不是同一個,這可能說明項目方在有意減少各個操作之間與地址的關聯性,提高行為溯源的難度

2. 稅收地址的合約不開源,也就是說稅務地址中可能隱藏有不想暴露的操作

3. 稅收合約比代幣合約晚部署,而代幣合約中稅收地址已被寫死,這意味著專案方可以預知稅收合約的地址,由於 CREATE 指令在確定創建者地址和 nonce 的情況下,部署合約地址是確定的,因此專案方提前就使用創建者地址模擬計算出了合約地址

其實有不少退出騙局都是透過稅收地址進行,且稅收地址的部署模式特徵符合上述的 1、2 點。

上午 11 點(代幣創建 3 小時後),攻擊者地址②(0x9DF4)進行了 Rug Pull。他透過呼叫稅收合約(0x77fb)的「swapExactETHForTokens」方法,用稅收地址中的 416,483,104,164,831(約 416 萬億)個 MUMI 代幣兌換出了約 9.736 個 ETH,並耗盡了池子中流動性。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

由於稅收合約(0x77fb)不開源,我們對其字節碼進行反編譯,反編結果如下:

https://app.dedaub.com/decompile?md5=01e2888c7691219bb7ea8c6b6befe11c

查看稅務合約(0x77fb)的「swapExactETHForTokens」方法反編譯程式碼後,我們發現實際上該函數實現的主要功能就是透過 uniswapV2 router 將數量為「xt」(呼叫者指定)的稅收合約(0x77fb)擁有的 MUMI 代幣兌換成 ETH,並發送給稅收地址中聲明的 “_manualSwap” 地址。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密
Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密
Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

_manualSwap 位址所處的 storage 位址為 0x0,以 json-rpc 的 getStorageAt 指令查詢後發現_manualSwap 對應的位址正是稅務合約(0x77fb)的部署者:攻擊者②(0x9DF4)。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

此筆 Rug Pull 交易的輸入參數 xt 為 420,690,000,000,000,000,000,000,對應 420,690,000,000,000(約 420 兆)個 MUMI 代幣(MUMI 代幣的 decimal 為 9)。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

也就是說,最終專案方用 420,690,000,000,000(約 420 兆)個 MUMI 將流動性池中的 WETH 耗幹,完成整個退出騙局。

然而這裡有一個至關重要的問題,就是稅收合約(0x77fb)哪來的這麼多 MUMI 代幣?

從前面的內容我們得知,MUMI 代幣在部署時的代幣合約時的總供應量為 420,690,000(約 4.2 億),而在退出騙局結束後,我們在 MUMI 代幣合約中查詢到的總供應量依舊為 420,690,000(下圖中顯示為 420,690,000,000,000,000,需要減去 decimal 對應位數的 0,decimal 為 9),稅收合約(0x777)中的遠超總供應量的代幣(300,600,000 億)就彷彿憑空出現的一樣,要知道,如上文所提,0x77fb 作為稅收地址甚至沒有被用於接收 MUMI 代幣轉賬過程中產生的手續費,稅收被代幣合約接收了。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

手法揭秘

  • 稅收合約哪來的代幣

為了探討稅收合約(0x7ffb)的代幣來源,我們查看了它的 ERC20 轉帳事件歷史。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

結果發現在全部 6 筆關於 0x77fb 的轉帳事件中,只有從稅收合約(0x7ffb)轉出的事件,而沒有任何 MUMI 代幣轉入的事件,乍一看,稅收合約(0x7ffb)的代幣還真是憑空出現的。

所以稅收合約(0x7ffb)地址中憑空出現的巨額 MUMI 代幣有兩個特點:

1. 沒有對 MUMI 合約的 totalSupply 產生影響

2. 代幣的增加並沒有觸發 Transfer 事件

那麼想法就很明確了,即 MUMI 代幣合約中一定存在後門,這個後門直接對 balance 變數進行修改,且在修改 balabce 的同時不對應修改 totalSupply,也不觸發 Transfer 事件。

也就是說,這是一個不標準的、或者說是惡意的 ERC20 代幣實現,用戶無法從總供應量的變化和事件中感知到專案方在偷偷 mint 代幣。

接著就是驗證上面的想法,我們直接在 MUMI 代幣合約原始碼中搜尋關鍵字「balance」。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

結果我們發現合約中有一個 private 類型的 “swapTokensForEth” 函數,傳入參數為 uint256 類型的 tokenAmount,在該函數的第 5 行,項目方直接將_taxWallet,也就是稅收合約(0x7ffb)的 MUMI 餘額修改為 tokenAmount * 10**_decimals,也就是 tokenAmount 的 1,000,000,000(約 10 億)倍,然後再從流動性池中將 tokenAmount 數量的 MUMI 兌換為 ETH 並存在代幣合約(0x4894)中。

再接著搜尋關鍵字 “swapTokenForEth“。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

“swapTokenForEth” 函數在 “_transfer” 函數中被調用,再細看調用條件,會發現:

1. 當轉帳的接收位址 to 位址為 MUMI-WETH 流動性池。

2. 當有其他地址在流動性池中購買 MUMI 代幣的數量超過_preventSwapBefore(5 次)時,「swapTokenForEth」函數才會被調用

3. 傳入的 tokenAmount 為代幣地址所擁有的 MUMI 代幣餘額和_maxTaxSwap 之間的較小值

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密
Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

也就是說當合約偵測到用戶在池子中以 WETH 兌換成 MUMI 代幣超過 5 次後,便會為稅收地址偷偷 mint 巨量代幣,並將一部分代幣兌換成 ETH 儲存在代幣合約中。

一方面,專案方表面上進行收稅並定期自動換成少量 ETH 放到代幣合約,這是給用戶看的,讓大家以為這就是專案方的利潤來源。

另一方面,專案方真正在做的,則是在用戶交易次數達到 5 次後,直接修改帳戶餘額,把流動性池全部抽乾。

  • 如何獲利

執行完「swapTokenForEth」函數後,「_transfer」函數也會執行 sendETHToFee 將代幣地址中收稅獲得的 ETH 傳送到稅收合約(0x77fb)。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

稅收合約(0x77fb)中的 ETH 可以被其合約內實現的 “rescue” 函數取出。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

現在再回看整個退出騙局中最後一筆獲利交易的兌換記錄。

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

獲利交易中共進行了兩次兌換,第一次是 4,164,831(約 416 萬)個 MUMI 代幣換 0.349 個 ETH,第二次是 416,483,100,000,000(約 416 兆)MUMI 代幣 9.368 個代幣 9.968 其中第二次兌換即為稅收合約(0x7ffb)中「swapExactETHForTokens」函數內發起的兌換,之所以數量與輸入參數代表的 420,690,000,000,000(約 420 兆)個代幣不符,是因為有部分代幣作為稅收發送給了代幣合約(0x4894),如下圖所示:

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

而第一次兌換對應的,則是在第二次兌換過程中,當代幣從稅收合約(0x7ffb)發送至 router 合約時,由因為滿足代幣合約內的後門函數觸發條件,導致觸發 “swapTokensForEth” 函數所發起的兌換,並非關鍵操作。

  • 背後的大鐮刀

從上文可以看出,MUMI 代幣從部署,到創建流動性池,再到 Rug Pull,整個退出騙局週期才約 3 個小時,但是卻以不到約 6.5 個 ETH 的成本(3 ETH 用於添加流動性,3 ETH 用於從流動性池中兌換 MUMI 以作誘導,不到 0.5 ETH 用於部署合約和發起交易)獲得了 9.7 個 ETH,利潤超過 50%。

攻擊者用 ETH 換 MUMI 的交易有 5 筆,前文並沒有提到,交易資訊如下:

  • https://etherscan.io/tx/0x62a59ba219e9b2b6ac14a1c35cb99a5683538379235a68b3a607182d7c814817
  • https://etherscan.io/tx/0x0c9af78f983aba6fef85bf2ecccd6cd68a5a5d4e5ef3a4b1e94fb10898fa597e
  • https://etherscan.io/tx/0xc0a048e993409d0d68450db6ff3fdc1f13474314c49b734bac3f1b3e0ef39525
  • https://etherscan.io/tx/0x9874c19cedafec351939a570ef392140c46a7f7da89b8d125cabc14dc54e7306
  • https://etherscan.io/tx/0x9ee3928dc782e54eb99f907fcdddc9fe6232b969a080bc79caa53ca143736f75

透過分析在流動性中進行操作的 eoa 地址後發現,相當一部分的地址為鏈上的 “打新機器人”,結合整個騙局快進快出的特點,我們有理由認為,這整個騙局針對的對象正是鏈上十分活躍的各種打新機器人、打新腳本。

因此無論是代幣看似沒必要但是複雜的合約設計、合約部署、流動性鎖定流程,還是中途攻擊者相關地址主動用 ETH 換取 MUMI 代幣的疑惑行為,都可以理解成是攻擊者為了試圖騙過鏈上各類打新機器人的反詐騙程式而做的偽裝。

我們透過追蹤資金流後發現,攻擊所獲得的收益最後全被攻擊地址②(0x9dF4)發送到了地址資金沉澱地址 (0xDF1a)

Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

而實際上我們最近檢測到的多起退出騙局最初的資金來源以及最後的資金去向都指向這個地址,因此我們對這個地址的交易進行了大致的分析和統計。

最終發現,該地址在約 2 個月前開始活躍,到今天為止已經發起了超過 7,000 筆交易,並且該地址已經和超過 200 個代幣進行過交互。

我們對其中的約 40 個代幣交易記錄進行分析,然後發現我們查看的幾乎所有代幣對應的流動性池中,最後都會有一筆輸入數量遠大於代幣總供應量的兌換交易將流動性池中的 ETH 耗盡,且整個退出騙局的週期都較短。

其中部分代幣(名煙中華)的部署交易如下:

https://etherscan.io/tx/0x324d7c133f079a2318c892ee49a2bcf1cbe9b20a2f5a1f36948641a902a83e17
Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密
https://etherscan.io/tx/0x0ca861513dc68eaef3017e7118e7538d999f9b4a53e1b477f1f1ce07d982dc3f
Web3安全警示丨鏈上打新局中局,大規模Rug Pull手法解密

因此我們可以認定,該地址實際上就是一個大規模的自動化「退出騙局」收割機,收割的物件就是鏈上的打新機器人。

該地址現在仍在活躍。

寫在最後

如果一個代幣在 mint 時不對應修改 totalSupply,也不觸發 Transfer 事件,那麼我們是很難感知專案方是否有在偷偷 mint 代幣的,這也將加劇「代幣是否安全,完全依賴專案方是否自覺」的現況。

因此我們可能需要考慮改進現有的代幣機製或引入一種有效的代幣總量檢測方案,來保障代幣數量變更的公開透明,現在憑藉 event 來捕獲代幣狀態變更是不夠的。

而我們需要警醒的是,儘管現在大家的防騙意識在提高,但是攻擊者的反防騙手段也在提高,這是一場永不停息的博弈,我們需要保持不斷學習和思考,才能在這樣的博弈中保全自身。

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