在智能合約領域,"以太坊虛擬機 EVM" 以及其算法和數據結構就是第一性原理。
本文從合約為什么要分類出發,結合每個場景可能面對怎樣的惡意攻擊,最終給出一套達成相對安全的合約分類分析算法。
雖然技術含量較高,但亦可作為雜談讀物,一覽去中心化系統間博弈的黑暗森林。
因為太重要了,可謂是交易所、錢包、區塊鏈瀏覽器、數據分析平臺等等 Dapp 的基石!
一筆交易之所以是 ERC 20 轉賬,是因為他的行為符合 ERC 20 標準,至少得有:
交易的狀態是成功
To 地址為某個符合 ERC 20 標準的合約
調用了 Transfer 函數,其特點是該交易 CallData 的前 4 位為0x a 9059 cbb
執行后,在該 To 地址上發出了transfer的事件
分類有誤則交易行為會誤判
以交易行為為基石,則 To 地址能否被準確分類則對其 CallData 的判斷會有截然不然的結論。對 Dapp 而言,鏈上鏈下的信息溝通高度依賴于交易事件的監聽,而同樣的事件編碼也只有在符合標準的合約中發出,才具有可信度。
分類有誤則交易會誤入黑洞
如果用戶進行一筆 Token 轉移,轉入到某個合約中,如果該合約沒有預設 Token 轉出的函數方法,則資金會雷同于 Burn 一樣被鎖定,無法控制
動態 | 中國電信翼支付將在區塊鏈核心應用等方面深入開展技術創新合作:金色財經報道,中國電信翼支付將深化\"5G+金融科技\"創新合作,在支付媒介創新、用戶精準營銷、智能授信、智慧風控、智能投顧、區塊鏈核心應用等方面,深入開展技術創新合作,探索\"5G+金融科技\"新模式。[2019/12/12]
且如今大量項目開始增加內置的錢包支持,要為用戶管理錢包也就不可避免的,需要時刻從鏈上實時分類出最新部署的合約,是否能夠吻合資產標準。
鏈上是一個沒有身份沒有法治的地方,你無法制止一筆正常的交易,哪怕他是惡意的。
他可以是冒充外婆的狼,做出多數符合你預期的外婆行為,但目的是進屋搶劫。
聲明標準,但可能實質不符合
常見的分類方式是直接采用 EIP-165 標準,讀取該地址是否支持 ERC 20 等,當然,這是一個高效率的方法,但是畢竟合約是對方控制,所以終究是可以偽造出一份申明。
165 標準的查詢,只是在鏈上有限的操作碼中,用最低成本去防止資金轉入黑洞的方法。
這也是為什么我們之前分析 NFT 的時候,特地提及標準中會有一類SafeTransferFrom的方法,其中Safe就是指代了采用 165 標準判斷出對方聲明自己具備了 NFT 的轉移能力。
唯有從合約字節碼出發,做源碼層面的靜態分析,從合約預期的行為出發才有更精準的可能性。
接下來咱們將系統的分析整體方案,注意我們的目的是“精度”和“效率”兩項核心指標。
要知道即使方向是對的,但要抵達大洋的彼岸路途也并不明朗,要做字節碼分析的第一站是獲取代碼
動態 | 湖南婁底書記市長會見中國工程院院士陳純,深入探討區塊鏈技術與應用:據婁底新聞網消息,湖南婁底市委書記、市人大常委會主任李薦國9月19日會見中國工程院院士、杭州趣鏈科技有限公司董事長陳純。雙方圍繞區塊鏈技術與應用等方面開展合作,進行了深入探討。李薦國表示,婁底市委、市政府對于區塊鏈發展是積極支持、穩步推進的,目前已取得了初步成效。我們希望雙方能夠尋求一種利益共享、風險共擔、合作共贏的發展模式,在堅持政府引導、企業主導的基礎上,加強對區塊鏈技術應用的監管,讓區塊鏈更好地為經濟社會發展服務,為提高政府效能、創新社會管理服務,盡快把技術優勢轉化為經濟優勢,讓老百姓得到實惠。[2019/9/20]
從上鏈后的角度講有getCode,一個 RPC 方法,可以從鏈上指定的地址里獲取到字節碼,單論讀取的話這是非常快捷的,因為從 EVM 的賬號結構中就把 codeHash 放在最頂端的位置。
但是這個方法等于是單獨對某個地址做獲取,想要進一步提升精度和效率呢?
如果是部署合約的交易,如何在其剛執行完甚至他還在內存池中便獲取部署的代碼?
如果該筆交易是合約工廠的模式,則交易的 Calldata 里是否存在源碼呢?
最后的我的方式是,是分類進行一種類似篩子的模式
對于非合約部署的交易,則直接用getCode獲取其中涉及的地址進行分類,
對于最新內存池的交易,篩選出 to 地址為空的交易,其 CallData 則是帶有構造函數的源代碼
對于合約工廠模式的交易,由于其中可能是合約部署出的合約再循環調用其他合約來執行部署,則遞歸的去分析該筆交易的子交易,記錄每個 type 為CREATE或者為CREATE 2 的 Call。
聲音 | 央行研究局局長:將深入研究完善金融科技監管制度框架等問題:據財聯社消息,央行研究局局長王信今日在數字金融開放研究計劃首屆學術研討會上表示,央行高度總是金融科技應用的相關研發,下一階段值得深入研究的課題包括:Libra等加密數字貨幣有關問題,如是否會形成法定數字貨幣、少數數字穩定幣并存格局;探索數字金融更好地支持實體經濟發展,應開發多元化、全方位金融服務;完善金融科技監管制度框架,發展監管科技,如何將科技巨頭納入宏觀審慎監管框架;加強數字金融基礎設施建設,加強數字金融領域的國際協調合作等。[2019/7/8]
我做了個 demo 實現的時候,發現還好現在 rpc 的版本比較高,因為整個過程最難的便是執行 3 的時候,如何遞歸找到指定 type 的 call,最底層的方式是通過 opcode 還原上下文,我吃了一驚!
還好現在的 geth 版本里有debug_traceTransaction 方法,他可以幫助解決在通過 opcode 操作碼中梳理每一個 call 的上下文信息,整理出核心的字段。
最終可以對多種部署模式的(直接部署,工廠模式單部署,工廠模式批量部署)的原始字節碼都獲取到。
最最簡單但不安全的方式,是把 code 直接做字符串匹配,以 ERC 20 為例符合標準的函數則有
在函數名之后的,則是該函數的函數簽名,之前在分析的時候提及,交易都是依賴匹配 callData 的前 4 位找到目標函數的,拓展閱讀:
聲音 | 北郵教授:5G的本質是無限連接 將促進區塊鏈等技術的深入發展:據澎湃新聞消息,5月26日下午,2019中國國際大數據產業博覽會舉行“5G重構數字社會基礎生態”高端對話,中國信息經濟學會副會長、北京郵電大學教授呂廷杰在會上表示,5G循序漸進的發展一定會帶來一個完全不同的社會,它會使社會的效率更高,因此也會涉及到更大的安全問題。他指出,5G的本質是無限連接,連接產生了高價值的關鍵數據,未來的大數據會有全新的飛躍,將促進人工智能、區塊鏈等技術的深入發展,生產很多新的架構和生態,必將重構數字經濟的生態,在未來5-8年會滲透到生活的方方面面,也將改變10年以后的整個社會的游戲規則。[2019/5/26]
所以合約字節碼里必然存儲有這 6 個函數的簽名。
當然,這種方法非常快捷 6 個都查到就完事的,但不安全的因素則是,如果我采用 solidity 合約中,單獨設計一個變量,存儲值為0x 18160 ddd 那么他也會將認為我有了這個函數。
那進一步的準確方法則是做 Opcode 的反編譯!反編譯則是將獲取到的字節碼轉到操作碼的過程,更高級的反編譯則是再轉成偽代碼,更利于人的閱讀,這次我們用不上,反編譯的方法列于文末的附錄中。
solidity(高級語言)->bytecode(字節碼)->opcode(操作碼)
我們就可以清晰的發現一個特征,函數簽名都會被PUSH 4 這個操作碼所執行,所以進一步的方法則是從全文中提取PUSH 4 后的內容,與函數標準做匹配。
我也簡單做了下性能實驗,不得不說 Go 語言的效率很強大, 1 W 次反編譯只需要 220 ms。
福建省法院網信辦主任郭金焰:推動大數據、區塊鏈等與法院工作的深度融合、深入應用:福建省法院網信辦主任郭金焰介紹,法院系統將把科技理性與司法理性“兩個智慧”融合好,把制度優勢和技術優勢“兩個優勢”結合好,把制度鐵籠和數據鐵籠“兩個鐵籠”建構好,推動大數據、云計算、人工智能、移動互聯、區塊鏈等與法院工作的深度融合、深入應用,促進審判體系和審判能力現代化,讓人民群眾充分享受信息化和智慧法院建設帶來的獲得感。[2018/4/22]
接下來的內容會有一定難度
上文中準確率有所提升但還不夠,因為是全文搜索PUSH 4 的,因為我們仍然可以構建一個變量,是byte 4 的類型,這樣一來也會觸發PUSH 4 的指令。
在我苦惱的時候,想到一些開源項目的實現,ETL 是一個讀取鏈上數據做分析的工具,其中會解析出 ERC 20、 721 的轉移單獨成表,所以必然具備分類合約的能力。
分析下來,可以發現他是基于代碼塊的分類,只處理第一個basic_blocks[ 0 ]里的push 4 指令
那問題來到了,如何準確判斷代碼塊了
代碼塊的概念源于REVERT + JUMPDEST 這 2 個連續的操作碼,這里必然需要連續的 2 個,因為在整個函數選取器的 opcode 區間里,如果函數數量過多,則會出現翻頁的邏輯,那也會出現JUMPDEST 這個指令。
函數選擇器的作用是,讀取該筆交易的 Calldata 的前 4 位字節,并與代碼中預設有的合約函數簽名進行匹配,協助指令跳轉到存儲了該函數方法指定的內存位置
讓我們嘗試一個最小的模擬執行
這部分是兩個函數的選擇器store(uint 256)和retrieve(),可算出簽名是2 e 64 cec 1 , 6057361 d
進行反編譯后,則會得到如下的操作碼串,可以說分兩個部分
第一部分:
在編譯器中在合約中僅函數選擇器部分會去獲取到 callData 的內容,寓意是獲取其 CallData 的函數調用簽名,注釋如下圖。
我們可以通過模擬 EVM 的內存池變化來看看效果
第二部分:
判斷是否與選擇器的值匹配的過程
1、將 retrieve()的 4 字節函數簽名(0x 2 e 64 cec 1)傳入 stack 上,
2、EQ 操作碼從 stack 區彈出 2 個變量,即0x 2 e 64 cec 1 和0x 6057361 d,并檢查它們是否相等
3、PUSH 2 將 2 個字節的數據(這里為0x 003 b,十進制為 59)傳入 stack,stack 區有一個叫做程序計數器的東西,它規定了下一個執行命令在字節碼中的位置。這里我們設置 59 ,因為那是 retrieve()字節碼的起始位置
4、JUMPI 代表"如果...,則跳轉至...",它從 stack 中彈出 2 個值作為輸入,如果條件為真,程序計數器將被更新至 59 。
這就是 EVM 是如何根據合約中的函數調用,來確定它需要執行的函數字節碼的位置的原理。
實際上,這只是一組簡單的“if 語句”,用于合約中的每個函數以及它們的跳轉位置。
整體簡述如下
每個合約地址可以通過 rpc getcode 或者debug_traceTransaction,獲取到部署后的bytecode ,采用 GO 中 VM 和 ASM 庫,反編譯后即獲取到opcode
合約在 EVM 運行原理中,會有以下特征
采用REVERT+JUMPDEST這 2 個連續的 opcode 作為代碼塊的區分
合約必然具備函數選擇器的功能,該功能也必然在第一個代碼塊上
函數選擇器中,其函數方法均采用PUSH 4 作為 opcode ,
該選擇器所包含的 opcode 中,會出現連續的PUSH 1 00; CALLDATALOAD; PUSH 1 e 0; SHR; DUP 1 ,核心功能是加載 callDate 數據并進行位移操作,從合約功能上其他語法不會產生
3. 對應的函數簽名在 eip 中定義,并且有必選和可選的明確說明
走到這里我們就可以說,基本實現高效率,高準確率的合約分析方法了,當然既然已經嚴謹了這么久,不妨再嚴謹一些,我們上文方案里中基于 REVER+JUMPDEST 來做代碼塊的區分,結合其中必然的 CallDate 加載和位移來做唯一性判斷,那是否存在,我可以用 solidity 合約也實現出類似的操作碼序列呢?
我做了下對照實驗,從 solidity 語法層面雖然亦有 msg.sig 等獲取 CallData 的方法,但編譯后其 opcode 的實現方法不同
十四君
個人專欄
閱讀更多
金色早8點
Odaily星球日報
金色財經
Block unicorn
DAOrayaki
曼昆區塊鏈法律
CFTC v. Ooki DAO 案件,由于 Ooki DAO 無人應訴,CFTC 取得了壓倒式的勝利,法院裁判 Ooki DAO 停止在美運營 + 關閉網站刪除內容 + $643.
1900/1/1 0:00:00作者:Conor 編譯:白話區塊鏈自從以太坊過渡到 PoS 以來,任何愿意質押 ETH 的人都可以獲得大約 4% 的收益率.
1900/1/1 0:00:00美國商品期貨交易委員會(CFTC)在最近一起案件中首次涉足到"浪漫詐騙"(Romance Scam)領域.
1900/1/1 0:00:001.一夜上頭條 幕后金主、合規與否等十個問題看懂EDX Markets在發現EDX Markets得到Citadel Securities、紅杉、富達、嘉信理財、Paradigm、GTS、GSR.
1900/1/1 0:00:00原文作者:0xBeyondLee 來源:mirror事實上,早在多年以前,「聰」作為比特幣的最小不可分單位便已存在,即1 比特幣= 10 ^ 9 聰.
1900/1/1 0:00:00ZK Rollup作為一種以太坊的擴容方式,它允許交易在鏈下進行處理,并在主鏈上以單個壓縮交易的形式合并.
1900/1/1 0:00:00