惡意合約要怎麼在不驚動使用者的情況下,事先知道自己正在被模擬環境執行,而不是被真實鏈上執行?
關鍵在於區塊鏈執行環境裡有一批被稱為「特殊變數」(special variables)的環境資訊,例如目前的區塊高度、時間戳記、以及本文提到的區塊出塊者地址(COINBASE)。這些變數是每一筆交易在執行時,合約程式碼可以主動讀取、並依此做出不同判斷的資訊,設計初衷是為了讓合約邏輯能感知自己所處的鏈上狀態(例如根據時間戳記判斷某個活動是否已經結束)。
問題出在:在真實鏈上,這些變數永遠會被填入具體、有意義的數值;但在模擬環境裡,因為當下並沒有真正的區塊被打包、也沒有真正的出塊者存在,開發模擬工具的團隊必須自己決定要在這些欄位填入什麼——ZenGo 團隊的研究發現,部分實作方式選擇了最省事的做法,直接填入零值或空地址。這個看似無傷大雅的簡化,卻給了惡意合約一個能明確辨識「我現在是不是在被模擬」的判斷依據,等同於在合約程式碼裡留了一道能檢查「觀眾席上有沒有人在看」的窗口。
如果模擬工具乾脆把區塊出塊者這類環境變數,也填入跟真實鏈上一樣的具體數值,是不是就能徹底解決這個問題?
這確實是業界目前主要採取的修補方向,ZenGo 團隊在揭露這項研究時也明確指出,修補方式相對直接:不要再用零值或空地址這種容易被辨識的「捷徑」,改成填入從真實鏈上狀態擷取的、有意義的具體數值,讓模擬環境盡可能真實地複製鏈上狀態。多數收到揭露通知的廠商,也確實在短時間內完成了這類修補。
但這個解法能解決的,只是「COINBASE 是否為零地址」這一種具體的判斷方式,而不是「合約有沒有辦法分辨模擬與真實環境」這個更根本的問題。理論上,只要模擬環境跟真實鏈上環境之間,還存在任何一絲可被合約邏輯偵測到的差異——不論是執行速度的細微落差、某些底層系統呼叫的行為差異、還是尚未被公開研究過的其他環境變數——精心設計的惡意合約,理論上就有機會找到新的判斷依據。這也是為什麼多數資安研究者的態度是:修補已知手法能大幅提高攻擊門檻,但「模擬環境是否能做到跟真實環境完全無法區分」,本質上是一場需要持續投入資源才能維持領先的競賽,而不是一次性能徹底解決的問題。
除了這種利用環境變數差異的偵測手法,還有沒有其他方式能讓惡意合約規避交易模擬的檢查?
有,而且從防禦的角度來看,另一種手法造成的實際影響可能更嚴重。除了讓合約本身偵測並規避模擬環境,攻擊者也可以把腦筋動到模擬結果被呈現給使用者的那個環節——也就是說,即使模擬工具本身如實跑出了正確的模擬結果,如果錢包介面在把這個結果轉換成使用者看得懂的畫面時,解析或呈現的邏輯本身有缺陷,攻擊者依然有機會讓使用者看到跟實際模擬結果不符的畫面。舉例來說,如果一筆交易實際上包含把使用者錢包的所有權轉移給攻擊者控制的合約這個指令,但錢包介面的解析邏輯沒有正確辨識出這個指令、只顯示了「即將收到 1 SOL」這類看似無害的部分,使用者依然會在完全不知情的情況下,簽下一筆會讓自己徹底失去錢包控制權的交易。
這類「模擬結果本身沒問題、但呈現給使用者的畫面出問題」的風險,跟本站已經介紹過的盲簽核心邏輯高度相關——都指向同一個更根本的原則:使用者實際看到的畫面,跟背後真正在發生的技術操作之間,永遠存在一層由某段軟體負責轉譯的中介層,而這層轉譯本身,不管是模擬引擎、還是錢包介面,都可能是被攻擊或設計不良的環節。
面對這類連交易模擬工具本身都可能被規避的風險,一般用戶實際上還能做什麼?聽起來好像沒有任何工具是真正可靠的。
這個結論下得太快了。這起研究揭露的,是「交易模擬不是絕對保證」這個事實,而不是「交易模擬沒有用」——事實上,多數需要用到這類進階規避手法才能突破的攻擊,本身就代表攻擊者投入了相當程度的技術資源與規劃,這類精心設計的攻擊,通常不會浪費在金額很小、目標不明確的交易上。對於日常大多數的交易,交易模擬工具依然是目前最有效、成本最低的第一道防線,繼續使用它,仍然遠比完全不用來得安全。
更務實的心態,是把交易模擬工具當成「大幅降低風險機率的必要措施」,而不是「一旦通過就可以完全不用再多想」的萬能保證,尤其在幾種特定情境下值得額外提高警覺:交易涉及金額特別龐大、要互動的合約是近期才剛部署、你要簽署授權的對象並非知名度高的主流協議,或是模擬結果顯示的報酬高到不太合理的程度。在這些情境下,額外花幾分鐘用第二個獨立來源核對合約邏輯、或乾脆先觀望幾天讓其他使用者先踩過雷,都是用不了多少成本、卻能實質提高安全邊際的做法——資安從來不是靠單一工具做到滴水不漏,而是靠多層防護疊加,讓任何單一環節被攻破的後果,都不至於是全盤皆輸。
如果你最近讀過這個站點介紹盲簽風險的文章,可能會記得其中一項具體建議:在簽署交易之前,先用交易模擬工具跑一次,看看這筆交易實際上會讓你的資產發生什麼變化,再決定要不要簽。這個建議本身沒有錯,交易模擬工具(Coinbase Wallet、Rabby、Blowfish 等主流錢包與擴充功能都已內建這項功能)確實能攔下大量惡意交易。但 2023 年資安研究團隊 ZenGo 揭露的一項技術,讓這個原本被視為「防線之一」的工具,暴露出一個此前很少被公開討論的盲點:惡意合約有辦法「察覺」自己正在被模擬,並且針對模擬環境刻意表現良好,等到交易真的送上鏈才露出真面目。
ZenGo 團隊把這種手法稱為「紅藥丸攻擊」(red pill attack),核心原理利用的是智能合約執行時能讀取的一些「環境變數」,例如 COINBASE(代表當前區塊出塊者的地址)。這些變數在真實鏈上交易裡,永遠會被填入一個具體、非零的地址;但在模擬環境裡,因為根本不存在真正的區塊與出塊者,部分模擬工具的實作方式,會直接把這個欄位設成全零地址,圖個方便。惡意合約只要在程式碼裡寫一段簡單的判斷邏輯——「如果 COINBASE 是零地址,就回傳一個對使用者有利的假結果;如果不是零地址,就執行真正想做的惡意行為」——就能精準區分自己現在是在模擬環境裡跑,還是正在真實鏈上被執行。
ZenGo 團隊實際示範了這個攻擊在 Polygon 鏈上如何運作:一個惡意合約要求使用者先送出約 0.1 枚 MATIC(當時價值約 0.1 美元),模擬結果顯示使用者將會收到 0.016 枚 WETH(當時價值約 30 美元)作為回報,看起來是一筆穩賺不賠的划算交易,使用者因此放心點下確認。但當這筆交易真正送上鏈執行時,因為此時 COINBASE 欄位已經被填入真實出塊者地址,合約識別出自己不在模擬環境,直接跳過原本承諾要回傳的獎勵,只留下使用者送出的 MATIC,全數收入自己口袋。這起研究後來擴大調查範圍,發現包括 Coinbase Wallet、Rabby、Blowfish、Pocket Universe 在內共六款主流錢包與資安擴充功能,都曾對這類手法存在防護漏洞——多數廠商在收到負責任揭露通知後迅速完成修補,ZenGo 也因此獲得多筆漏洞賞金。
這起研究揭露的核心教訓,不是「交易模擬工具沒有用,不要用」——事實上,多數主流工具在揭露後已經修補了這類已知的偵測手法,而且交易模擬依然能攔下絕大多數不涉及這種進階規避技巧的惡意交易,繼續使用它遠比不用來得安全。真正該調整的認知是:交易模擬給出的「安全」結果,是一種機率上的高度可信信號,而不是一份無法被繞過的絕對保證——尤其面對來源不明、剛部署不久、或跟知名協議刻意做出高度相似介面的新合約,額外的謹慎依然有其必要。具體可以做的事包括:對於金額特別大的交易,除了看單一模擬工具的結果,額外用另一個獨立來源(例如區塊鏈瀏覽器的合約原始碼查詢功能)核對一次合約邏輯;對於聲稱「穩賺不賠」、報酬明顯高於合理範圍的交易,保持比平常更高的警覺,因為這正是攻擊者最有動機透過偽裝模擬結果來誘導使用者簽署的情境;以及優先選擇長期投入資源、持續更新偵測邏輯以對抗新型規避手法的模擬服務商,而不是把「有做模擬」當成一次性檢查完就能高枕無憂的終點。