EVM 是一個輕量級的虛擬機,其設計初衷就是提供一種可以忽略硬件、操作系統等兼容性的虛擬的執行環境供以太坊網絡運行智能合約。
簡單來說 EVM 是一個完全獨立的沙盒,在 EVM 中運行的代碼是無法訪問網絡、文件系統和其他進程的,以此來避免錯誤的代碼能讓智能合約毀滅或者影響外部環境。
在此基礎上,知道創宇區塊鏈安全實驗室帶大家一起深入理解 EVM 的存儲機制和安全問題。
可以看到 EVM 存儲數據分為兩類:
存儲在 code 和 storage 里的數據是 non-volatile (不容易丟失的)
存儲在 stack,args,memory 里數據是volatile(容易丟失的)
Code
code 部署合約時儲存 data 字段也就是合約內容的空間,即專門存儲智能合約的二進制源碼的空間
Storage
Storage 是一個可以讀寫修改的持久存儲的空間,也是每個合約持久化存儲數據的地方。Storage 是一個巨大的 map,一共 2^256 個插槽 (slot),每個插糟有 32byte,合約中的“狀態變量”會根據其具體類型分別保存到這些插槽中。
Stack
stack 即所謂的“運行棧",用來保存 EVM 指令的輸入和輸出數據。可以免費使用,沒有 gas 消耗,用來保存函數的局部變量,數量被限制在 16 個。stack 的最大深度為 1024 ,其中每個單元是 32 byte。
國務院辦公廳:深入推進人工智能社會實驗,開展區塊鏈創新應用試點:1月6日消息,國務院辦公廳發布關于印發要素市場化配置綜合改革試點總體方案的通知,通知指出,發揮領軍企業和行業組織作用,推動人工智能、區塊鏈、車聯網、物聯網等領域數據采集標準化。深入推進人工智能社會實驗,開展區塊鏈創新應用試點。[2022/1/6 8:29:41]
Args
args 也叫 calldata,是一段只讀的可尋址的保存函數調用參數的空間,與棧不同的地方的是,如果要使用 calldata 里面的數據,必須手動指定偏移量和讀取的字節數。
Memory
Memory 一個簡單的字節數組,主要是在運行期間存儲數據,將參數傳遞給內部函數。基于 32byte 進行尋址和擴展。
前面已經說過 Storage 是每個合約持久化存儲數據的地方其儲存數據的方式是通過插槽來實現的,現在就具體介紹它是怎么實現的:
1.對于大小在 32 字節以內的變量(常量),以其定義的順序作為它的索引值來存儲。即第一個變量的索引為 key(0),第二個變量的索引為 key(1)...
2.對于連續較小的值,可能被優化存儲在同一個位置,比如:合約中前四個狀態變量都是 uint64 類型的,則四個狀態變量的值會被打包成一個 32 字節的值存儲在 0 位置。
共和黨眾議院領袖麥卡錫呼吁美國決策者更深入地了解比特幣:4月13日消息,眾議院少數黨領袖凱文·麥卡錫呼吁美國的決策者更深入地了解比特幣。CNBC的Joe Kernen詢問麥卡錫有關美國財政部長耶倫和美聯儲主席鮑威爾是否應閱讀《比特幣標準》(一本由經濟學家Saifedean Ammous撰寫的暢銷書)時,麥卡錫回答:“要走向未來,他們不應該忽視比特幣……對于那些監管者和執政者來說,最好現在就開始理解比特幣對未來而言意味著什么,因為其他國家(尤其是中國)正在向前發展。”麥卡錫警告說,如果不采取行動,美國最終可能落后于中國。(U.today)[2021/4/13 20:15:34]
未優化:
pragma solidity ^0.4.11;contract C {? ?uint256 a = 12;? ?uint256 c = 12;? ?uint256 b = 12;? ?uint256 d = 12;? ?function m() view public returns(uint256,uint256,uint256,uint256){? ? ? ?return (a,b,c,d);? ?}}
優化后:
pragma solidity ^0.4.11;contract C {? ?uint64 a = 12;? ?uint64 c = 12;? ?uint64 b = 12;? ?uint64 d = 12;? ?function m() view public returns(uint64,uint64,uint64,uint64){? ? ? ?return (a,b,c,d);? ?}}
聲音 | 原保監會副主席:區塊鏈等技術通過保險業務流程全面深入,提升了保險行業的業務效率:金色財經報道,近日,全國政協經濟委員會委員、國務院參事室特約研究員、原保監會副主席周延禮在“三亞財經國際論壇——全球格局變化下的應對與抉擇”上表示,近年來,科技和互聯網巨頭跨入保險界,大數據與人工智能成為保險科技的主要驅動力,大數據、云計算、區塊鏈、人工智能等技術通過保險業務流程全面地深入,提升了保險行業的業務效率,改變了產品形態與服務的交互方式,新的商業模式和保險生態隨之而產生。[2019/12/11]
對于大小在 32 字節以內的結構體同樣也是順序存儲,例如結構體變量索引定義在位置 0,結構體內部有兩個成員,則這兩個成員的依序為 0 和 1。
pragma solidity ^0.4.11;contract C {struct Info {? ?uint256 a ;? ?uint256 b ;}? ?function m() ?external returns(uint256,uint256){? ? ? ?Info storage info;? ? ? ?info.a = 12 ;? ? ? ?info.b = 24 ;? ? ? ?return(info.a,info.b);? ?}}
聲音 | 大連港:將繼續開拓區塊鏈技術 深入開展創新工作:金色財經報道,大連港(601880)被提問“除了區塊鏈電子放貨平臺之外,接下來還有什么區塊鏈項目落地”時表示,目前,大連港利用區塊鏈的去中心化、不可篡改、共享賬本等特征所建立的區塊鏈信任機制,使業務信息公開透明公正,借助區塊鏈的數據加密作用強化數據信息安全功能,確保數據的安全性、完整性和一致性,使船、輪駁公司、智慧港口平臺各方都能實時、安全、無縫地傳遞拖輪作業信息,實現全程留痕和全程可追溯,滿足輪駁業務的安全性和準確性要求。未來大連港還將繼續開拓區塊鏈技術業務實現場景,深入開展創新工作,在全港口領域推行區塊鏈技術應用落地。(上證e互動)[2019/10/30]
map 存儲位置是通過 keccak256 (bytes32(key) + bytes32(position) ) 計算得到的,position 表示 key 對應 storage 類型變量存儲的位置。
pragma solidity ^0.4.11;contract Test {?mapping(uint256 => uint256) knownsec;?function go() public {? ? ?knownsec[0x60] = 0x40;?}}
同上,只要在 32 字節以內也是順序存儲,不過在編譯時編譯器會進行邊界檢查防止越界。
Binance Labs主管Christy Choi:正與對區塊鏈和加密貨幣有深入見解的基金進行合作:今日Binance Labs主管Christy Choi在reddit的Ask Me Anything環節表示,幣安生態系統基金的目的是確定和支持對整個生態系統產生持久影響的項目。因此目前正在與關心整個行業、對投資負責、對區塊鏈和加密貨幣有深入見解的基金進行合作。只要關心生態系統并建立一個健康的產業,BNB最終會變得更好。[2018/6/7]
pragma solidity ^0.4.11;contract C {? ?uint256 a = [12,24,48] ;? ?? ?function m() public view returns(uint256,uint256,uint256){? ? ? ?return (a,a,a);? ?}? ?}
由于可變長度數組長度不定,一般在編譯可變長度數組時會提前預留存儲空間,所以就會使用狀態變量的位置存儲可變長度數組的長度。
而具體的數據地址會通過計算 keccak256 (bytes32(position)) 算得數組首地址,再加數組長度偏移量獲得具體的元素。
pragma solidity ^0.4.11;contract C {? ?uint256[] a = [12,24,48] ;? ?? ?function m() public view returns(uint256,uint256,uint256){? ? ? ?return (a,a,a);? ?}? ?}
如果長度小于等于31字節 :
1.對于定長字節數組則是同定長數組一樣;
2.對于可變字節數組和字符串,會在存儲值位置補0一直到32字節,并用補0的最后一個字節存儲字符串的編碼長度。
pragma solidity ^0.4.4;contract A{? ?string public name0 = "knownsec";?? ?bytes8 public name=0x6b6e6f776e736563;? ?bytes public g ;? ?? ?function test() public {? ? ? ?g.push(0xAA);? ? ? ?g.push(0xBB);? ? ? ?g.push(0xCC);? ?}? ?function go() public view returns(bytes){? ? ? ?return g;? ?}}
當節數組和字符串長度大于31字節時
1.變量位置存儲編碼長度,并且編碼長度公式更換為編碼長度 = 字符數 * 2 + 1
2.真實存儲值第一個位置通過公式 keccak256(bytes32(position)) 獲取,剩余值在獲取到的位置順序存儲,同樣在最后存儲位置補0到32字節。
string public name = "knownsecooooooooooooooooooooooooo";
前面已經講到EVM的存儲結構及存儲機制,現在我們再來探討其安全問題。
漏洞原理:
在官方手冊中提到結構體,數組和映射的局部變量默認是放在 storage 中的,而 solidity 語言中函數中設置的局部變量的默認類型取決于它們本身的類型。
因此如果在函數內部設置以上 storage 類型變量卻沒有進行初始化,他們就相當于存儲指針指向合約中的其他變量,當我們對其進行改變時改變的就是其指向的變量。漏洞合約,目的修改 owner 為自己地址:
pragma solidity ^0.4.0;contract testContract{? ?bool public unlocked = false;? ?address public owner = 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c;struct Person {? ?bytes32 name;? ?address mappedAddress;}? ?function test(bytes32 _name , address ?_mappedAddress) public{? ? ? ?Person person;? ? ? ?person.name = _name;? ? ? ?person.mappedAddress = _mappedAddress;? ? ? ?require(unlocked);? }}
漏洞合約分析:
可以看到該合約在函數部分創建新的結構體時沒有進行初始化,由此我們可以利用該函數進行對owner的修改。不過使用該函數我們還要通過require驗證,不過這也不難因為狀態變量unlocked也同樣在我們可控的范圍內。
具體操作:
調用test函數分別傳入向_name 傳入:0x0000000000000000000000000000000000000000000000000000000000000001(真值)
_mappedAddress 傳入:0xfB89eCb0188cb83c220aADDa1468C1635208e821(個人地址)
傳參前:
傳參后:
可以看到已經成功更改了地址。
可以看到 EVM 的存儲器就是一個 key=>value 的健值數據庫,存儲的數據可以通過校驗和來確保一致。但是其也是和智能合約語言進行交互的,當其中一些規則發生沖突很可能就被別有用心的人用來作惡,所以規范的使用智能合約語言是避開漏洞的必要條件。
Tags:UININT區塊鏈UBLNew Guinea Singing InuSAINTwpc幣區塊鏈Publish Token
10月14日,螞蟻鏈粉絲粒推出一個潮玩系列的NFT數字藏品,限量出售,受到市場熱捧。該系列NFT作品分為三種,基于潮牌QEE熊公仔,打造出“鳳凰于飛”“馬到成功”“如虎添翼”三種不同風格的數字藏.
1900/1/1 0:00:00如果沒有清華北大的學歷背書,如果沒有阿里騰訊的豪華經歷,如果沒有高瓴紅杉的資本朋友,普通的你我是否還有“白手起家”的機會?在所謂大人物的大生意之外.
1900/1/1 0:00:00由于 DeFi 開源透明、去中心化和安全的性質,通過代碼塑造的加密資產想象力更加豐富。因此,除了加密貨幣市場之外,DeFi 衍生品市場也在被開發者們不斷發掘.
1900/1/1 0:00:00拜登政府尋求將穩定幣發行者作為銀行進行監管。▌美SEC宣布推遲4支BTC ETF決策時間10月1日消息,美國證券交易委員會(SEC)宣布,將4支 BTC ETF 申請裁定時間延長 45 天.
1900/1/1 0:00:001、現在資金充沛。每個人都有錢,他們想進行投資。涌入加密領域的資金每周就會增加,以滿足這種愿望.
1900/1/1 0:00:00自從今年3季度以來,美聯儲何時縮減資產購買(Taper)、以何種次序、什么速度退出非常規貨幣政策引發了市場關注.
1900/1/1 0:00:00