以太坊價格 以太坊價格
Ctrl+D 以太坊價格
ads
首頁 > 比特幣 > Info

ETH:有趣的智能合約蜜罐(下)

Author:

Time:1900/1/1 0:00:00

1.概述

在有趣的智能合約蜜罐中我們對古老的欺騙手段和神奇的邏輯漏洞進行了講解和復現,在下部分中我們將會對新穎的賭博游戲和黑客的漏洞利用進行講解以及復現,從而進一步增加對智能合約蜜罐的了解。同樣的,所有的智能合約蜜罐代碼都可以GitHub上找到,這里再次給出他們的網址:smart-contract-honeySolidlity-Vulnerable2.新穎的賭博游戲

賭博行業從古至今一直存在,而區塊鏈的去中心化似乎給賭博行業帶了新的機會,它的進入會讓人們覺得賭博變得公平,然而我們都知道賭博結果往往都是必輸,那么接下來就通過分析四個基于區塊鏈的賭博游戲合約來介紹莊家是如何最后穩贏的。2.1加密輪盤賭輪:CryptoRoulette

2.1.1蜜罐分析第一個要介紹的是CryptoRoulette,它譯為「加密輪盤賭輪」。GutHub地址:smart-contract-honeypots/CryptoRoulette.solEtherscan地址:CryptoRoulette|0x94602b0E2512DdAd62a935763BF1277c973B2758蜜罐的完整代碼如下:

該合約設置了一個私有屬性的隨機數secretNumber,在shuffle()函數中被指定范圍在1-20,玩家可以通過play()函數去盲猜這個隨機數,如果猜對了就可以將合約中的所有錢取走,每次調用play()函數后都會重置隨機數。這么看來這個合約好像沒有什么問題,隨著猜錯的玩家越來越多,合約中的代幣余額也會積累的越多,如果碰巧猜對了就可以獲取所有的獎金,然而事實是這樣的嘛?我們可以看到在這個蜜罐合約中,最重要的就是shuffle()和play()這兩個函數,下面就來分析下這兩個函數。初始的secretNumber是在構造函數CryptoRoulette中調用shuffle()函數,而shuffle()函數中只有一行代碼,就是設置secretNumber的值,從代碼中也可以看出secretNumber的值既和區塊的數目有關,也和時間有關。函數代碼如下:

而play()函數就是提供給用戶進行賭博來猜這個隨機數的,玩家攜帶不小于0.1eth并傳入自己猜的數字number,玩家猜的這個數字number去和secretNumber進行比較,如果相等就可以獲勝,轉走合約中的所有以太幣,但是在函數的開頭中有一個檢查require,其中后面要求玩家猜的數字不能大于10,而secretNumber我們在上面的函數中講到范圍是1-20,這樣看來雖然加大了難度,但是也存在猜對可能性,然而事實是secretNumber一定會大于10,玩家永遠都不可能猜對數字,合約所有者卻可以通過調用kill()函數轉走合約中的所有以太幣。

這里會有人問了,secretNumber為啥一定會大于10呢?原因就是結構體game的初始化對存儲數據secretNumber的覆蓋,我們在函數里直接初始化結構體必須加memory關鍵字,因為memory是使用內存來進行存儲,這樣一來就可以避免占用storage的存儲位,而蜜罐合約中并未使用memory關鍵字,從而導致了變量覆蓋。該問題在Solidity0.5.0版本以前只是進行了提示,并沒有做出錯誤警告,所以在老版本編譯器中要注意該問題。在下面的代碼復現中可以看到問題所在。2.1.2代碼復現

將蜜罐合約的代碼復制到RemixIDE中,為了方便我們查看secretNumber的值,我們將secretNumber的類型設置為public,這樣就可以在RemixIDE中直接看到它的值了。甚至有些蜜罐部署者為了誘惑攻擊者來攻擊合約,也可以設置為public屬性,因為就算告訴攻擊者secretNumber的值他也不能猜對這個數字。使用地址0x5B3點擊「Deploy」部署合約,調用secretNumber查看初始隨機數為1,由于這里還沒有初始化結構體也就不會覆蓋隨機數所以是正確的。

國際清算銀行創新樞紐負責人:薩爾瓦多采用比特幣作為法定貨幣是一個有趣的試驗:國際清算銀行創新樞紐負責人Benoit?Coeure:薩爾瓦多采用比特幣作為法定貨幣是一個有趣的試驗,我們認為比特幣是一種投機資產,應該受到監管。(金十)[2021/6/11 23:31:06]

之后攻擊者發現了該蜜罐合約,查看secretNumber為1并認為該合約可以進行攻擊獲利,所以在符合play()函數中的第一個判斷條件情況下傳入數字1和攜帶1個以太幣進行函數調用,函數調用成功后查看賬戶余額發現賬戶余額不僅沒有得到合約中的所有代幣反而將剛才函數調用時攜帶的1個以太幣也損失掉了。

為了探究具體原因我們對剛才的函數調用進行Debug。

調試點擊下一步直到第一個條件判斷,此時secretNumber仍然為1。

繼續點擊按鈕進行下一步的調試,當進行到game.player=msg.sender時由于結構體game的初始化對存儲數據secretNumber進行了覆蓋,導致secretNumber變成了msg.sender的uint256內容,這樣一來就使得后面的if判斷條件不能成立,從而使得攻擊者不能轉走合約中的所有代幣余額。

2.2開放地址彩票:OpenAddressLottery

2.2.1蜜罐分析第二個要介紹的是OpenAddressLottery,它譯為「開發地址彩票」。GutHub地址:Solidlity-Vulnerable/OpenAddressLottery.solEtherscan地址:OpenAddressLottery|0xd1915A2bCC4B77794d64c4e483E43444193373Fa蜜罐的完整代碼如下:

蜜罐合約OpenAddressLottery的游戲邏輯很簡單,合約中有一個初始值為1的狀態變量LuckyNumber,競猜者每次競猜時都會根據其地址隨即生成0或者1,如果生成的值和LuckyNumber一樣,那么競猜者就可以獲得1.9倍的獎金,且每個地址只能贏得一次游戲勝利,之后將無法繼續參加競猜。該蜜罐合約的重點就在于participate()、luckyNumberOfAddress()和forceReseed()函數,下面來對這3個函數進行依次講解。首先是participate()函數,這是用戶參與競猜的函數:

接著是luckyNumberOfAddress()函數,將競猜者的地址作為參數傳入,通過n=uint(keccak256(uint(addr),secretSeed))%2;來計算競彩時競猜者對應的數字,由于是對2取余,所以得到的結果只能為0或者1。在計算這個數字時使用了變量secretSeed,而該變量總是通過reseed()函數得到的。

馬斯克:狗狗幣是最有趣的加密貨幣:推特網友表示,人們把狗狗幣當作笑話來取笑,卻忽略了一個事實,那就是作為笑話是狗狗幣最大的優點之一。對此,馬斯克回復表示,它是最有趣的加密貨幣。[2021/2/7 19:09:16]

最后我們來講下上面說到的reseed()函數,通過keccak256算法將傳入的4個參數來生成secretSeed。

通過上面對合約的分析,看起來合約沒有什么問題,中獎率也是50%,但其實是有陷阱的,這就要說到Solidity0.4.x結構體局部變量引起的變量覆蓋漏洞,也就是給未初始化的結構體局部變量賦值時會直接覆蓋掉智能合約中定義的前幾個變量,這樣就使得合約中forceReseed()函數被調用后,第四個定義的參數LuckyNumber會被s.component4=tx.gasprice*7給覆蓋并將其設置為7,該蜜罐合約原理和上一個蜜罐合約類似。查看該合約的交易內容,可以發現OpenAddressLottery的交易數量很多,這也說明了蜜罐合約OpenAddressLottery的欺騙性。

2.2.2代碼復現將蜜罐合約的代碼復制到RemixIDE中,為了方便我們查看LuckyNumber的值,我們將LuckyNumber的類型設置為public,這樣就可以在RemixIDE中就有獲取其值的getter()函數了。同樣的,蜜罐部署者也可以將該變量設置為public屬性讓攻擊者誤以為有利可圖,因為LuckyNumber的值會被覆蓋永遠為7。使用地址0x5B3點擊「Deploy」部署合約,調用LuckyNumber查看其值為1,由于這里還沒有初始化SeedComponent結構體也就不會覆蓋掉LuckyNumber的值,所以它還是1。

使用合約所有者0x5B3調用forceReseed()函數來初始化SeedComponent中的四個變量,可以看到LuckyNumber的值由于初始化已經變成了7。

攻擊者0x4B2看到該合約后認為其存在漏洞,攜帶10eth調用participate()函數,調用后查看余額發現并沒有增加。查看自己的地址對應的luckyNumberOfAddress的值為1,但是卻沒有得到獎勵,再查看LuckyNumber的值發現一直為7。其原因就是在部署者調用forceReseed()函數初始化后LuckyNumber的值就被覆蓋為了7,而攻擊者地址生成的隨機數只能是0或1,這就意味著永遠不會有人獲得勝利。這就是利用了編譯器的漏洞,該問題已經在Solidity0.5.0中修復,所以這種蜜罐合約只有在Solidity0.4.x中才會生效。

2.3山丘之王:KingOfTheHill

2.3.1蜜罐分析第三個要介紹的是KingOfTheHill,它譯為「山丘之王」。GutHub地址:Solidlity-Vulnerable/KingOfTheHill.solEtherscan地址:KingOfTheHill|0x4dc76cfc65b14b3fd83c8bc8b895482f3cbc150a蜜罐的完整代碼如下:

上市公司FRMO:XRP是加密領域最有趣的資產之一:上市風險管理公司FRMO Corp.在最近一封致股東的信中概述了其對加密市場的看漲立場,并特別指出XRP是加密領域最有趣的資產之一,因為它沒有挖礦,而且本質上是通貨緊縮的。此外,FRMO表示,其私人合伙投資目前持有按市值計算的前十大加密資產。該公司還在挖掘ETH、ETC、ZEC、LTC和BCH。(The Daily Hodl)[2020/12/5 14:04:39]

蜜罐合約KingOfTheHill只有38行代碼,邏輯很簡單,有回退函數和takeAll()函數,其中jackpot變量是傳入合約的所有代幣之和,每次有用戶調用回退函數后如果傳入的mag.value比jackpot大,就將owner的值賦值為msg.sender。當用戶獲得了合約所有者權限后,就可以調用takeAll()函數在延期時間到后將合約中所有余額轉走。接下來重點分析下這兩個函數。首先是回退函數,這是用戶參與合約「漏洞」的函數,其代碼如下:

接著是takeAll()函數,這是能轉走合約中所有余額的函數,其代碼如下:

通過對上面兩個函數的分析,感覺該合約并沒有什么問題,但是我們說了這是個蜜罐,那么它的陷阱到底在哪兒呢?回看下「有趣的智能合約蜜罐」中的TestBank蜜罐合約就能知道原因了,它們的原理類似,都是「誰是合約主人」的問題。KingOfTheHill中存在著Owned和KingOfTheHill兩個合約,KingOfTheHill繼承了Owned,為了方便理解,我們將KingOfTheHill改寫成一個單合約,代碼如下:

在改寫了合約代碼后很容易就可以看出問題所在,用于權限判斷的修飾器函數onlyOwner中判斷的變量是owner1,而回退函數中修改的是原來子類新定義的owner,也就是owner2,這就說明了合約所有者是不會被更改的,調用takeAll()函數的人只能是合約創建者。接下來我們通過代碼來復現一下。2.3.2代碼復現將蜜罐合約的代碼復制到RemixIDE中,為了方便我們復現,將回退函數中withdrawDelay=block.timestamp+5days;修改為withdrawDelay=block.timestamp+0days;,這樣我們在測試的時候就不用等待5天后再去嘗試取款操作了。使用地址0x5B3點擊「Deploy」部署KingOfTheHill合約,點擊owner查看當前值為0。

再使用0x5B3攜帶10eth調用回退函數,向合約中存入10個以太幣,此時jackpot為10eth,查看owned為0x5B3。

攻擊者0xAb8設置msg.value為20eth調用回退函數,查看owner為0xAb8。

攻擊者發現此時owner為自己的地址,符合了takeAll()函數的要求,所以去調用takeAll()函數,結果發現交易失敗,并且自己的余額仍然為80eth。

The Block創始人:DeFi是當今加密貨幣和數字資產中最有趣的事情:推特網友Trolly McTrollface表示,批評DeFi是沒有意義的,因為每個參與其中的人都知道這只是一堆名字聽起來很滑稽的傳銷騙局,并且這其中每個人都相信自己能成功登上頂峰。The Block創始人Mike Dudas對此反駁稱,這絕對不是真的,不要讓沒錢的人和永恒的懷疑論者使你相信這一點。DeFi是當今加密貨幣和數字資產中最有趣的事情(與CBDC/數字美元相比)。[2020/9/14]

蜜罐部署者0x5B3發現有人上鉤了,合約中已經有了30eth,此時雖然owner為攻擊者地址0xAb8,但是0x5B3調用takeAll()函數仍然將合約中的所有余額全部轉走,查看賬戶余額,的確增加了30eth。

與之類似的智能合約還有RichestTakeAll:GitHub地址:Solidlity-Vulnerable/RichestTakeAll.sol智能合約地址:RichestTakeAll|0xe65c53087e1a40b7c53b9a0ea3c2562ae2dfeb242.4以太幣競爭游戲:RACEFORETH

2.4.1蜜罐分析第四個要介紹的是RACEFORETH,它譯為「以太坊競爭游戲」。GutHub地址:Solidlity-Vulnerable/RACEFORETH.sol蜜罐的完整代碼如下:

蜜罐合約RACEFORETH中有一個SCORE_TO_WIN參數,其值為100finney,字面意思我們也可以知道該參數的作用是勝利的分數,然后合約還有兩個映射,其中racerScore是競爭者當前得分數,racerSpeedLimit是每步的限制。競爭者通過每次的轉賬金額來積累自己的分數racerScore,當自己的得分racerScore大于等于SCORE_TO_WIN時就能獲得勝利,取走合約創建者一開始存入的獎勵PRIZE。蜜罐合約的核心內容就是race()函數和endRace()函數,接下來我們分析下這兩個函數。首先是race()函數,其代碼如下:

用戶每次調用race()函數都會帶入msg.value,且msg.value需要大于1wei和小于步長限制,通過判斷后加到自己的總得分數racerScore上,接著將新的步長限制設置為當前步長限制的一半,只要總得分數大于等于了獲勝目標值就可以取走獎勵,初看合約會覺得每次增加的步數在減少,但總有一天會追上,但事實是這樣嗎?接著是endRace()函數,其代碼如下:

合約所有者在上一次競賽的3天后就可以轉走合約中所有的余額了。2.4.2代碼復現將蜜罐合約的代碼復制到RemixIDE中,為了方便我們復現,增加了一個publicnowScore,這樣我們在測試的時候就可以看到每次競賽后的分數了。使用地址0x5B3點擊「Deploy」部署RACEFORETH合約。

使用0xAb8作為攻擊者,根據代碼的要求,第一次最大只能為50Finney,所以將msg.value也設置為50Finney,之后查看當前分數為50Finney。

動態 | 英國查爾斯王子稱區塊鏈是非常有趣的發展:據ambcrypto報道,根據用戶@coindorado發布的視頻,英國王儲查爾斯王子在柏林被問及比特幣和加密貨幣時表示不太了解。但在被問及區塊鏈技術時,儲查爾斯王子稱其為”非常有趣的發展”。[2019/5/8]

攻擊者0xAb8第二次嘗試將msg.value設置為大于上一次競賽的50Finney一半的26Finney,調用race()函數后發現調用失敗,原因則是因為我們的26Finney不滿足require中小于等于上一次競賽一半的條件。

每次我們都傳入上一次最大值的一半,執行多次后發現仍然未到100Finney。因為如下的公式只能無限趨于100卻用于不能等于100。

其中:

永遠是小于2的,那么50乘上這個式子就永遠不可能等于100了,也就永遠無法到達終點,所以對于該蜜罐合約,即使我們多次調用race()函數,每次都轉入最大限制值,也不可能達到目標分數,那么我們就不能取出合約中的獎勵了。

3.黑客的漏洞利用

3.1僅僅是測試?(整數溢出):For_Test

3.1.1蜜罐分析第五個要介紹的是For_Test,它譯為「僅僅是測試?」。GutHub地址:Solidlity-Vulnerable/For_Test.solEtherscan地址:For_Test|0x2eCF8D1F46DD3C2098de9352683444A0B69Eb229蜜罐的完整代碼如下:

蜜罐合約For_Test的邏輯很簡單,核心函數只有Test()一個,在該函數中當傳入的msg.value大于0.1eth時,根據for循環的內容,最終會得到amountToTransfer的值,也就是說函數調用者會獲得4倍轉入金額的獎勵。接下來我們分析函數的主要內容。

仔細分析代碼邏輯可以發現for循環中if判斷中有個條件,當條件為真時會跳出循環,但是這個判斷條件很詭異,因為amountToTransfer初始為0,在跳出之前amountToTransfer=multi,而在下一次循環時multi變為2倍的i,這就意味著multi是永遠大于amountToTransfer的值,相應的這個判斷條件不是會永遠也不成立了嗎?在最終揭秘這個蜜罐合約前我們還需要了解下幾個知識。msg.value的單位是wei,而1eth=1018wei。當一個參數變量被定義為var時,其數據類型為uint8,其取值范圍為。再次看到Test()函數中的循環,msg.value的最小值為0.1eth,而msg.value*2的值就會超過uint8的取值范圍,也就是說此處會存在整形溢出,在i=255時再執行i++就會導致i上溢變為0,此時的multi為0從而小于amountToTransfer的值,這樣就滿足了if的判斷條件,循環也會提前結束。根據代碼內容,最終轉給調用者的金額為amountToTransfer=255*2=510wei,無論調用者傳入了大于0.1eth的任何金額,最后都只會得到510wei。3.1.2代碼復現將蜜罐合約的代碼復制到RemixIDE中,使用地址0x5B3點擊「Deploy」部署For_Test合約,此時0x5B3的賬戶余額為100eth。

選擇0xAb8作為攻擊者,將msg.value設置為10eth,調用Test()函數,調用成功后發現賬戶余額不但沒有增加反而減少了剛才傳入的10eth。

當攻擊者將代幣轉入合約后,合約所有者調用withdraw()函數進行取款,將剛才攻擊者調用Test()函數傳入的10eth轉走,賬戶余額增加到110eth。

與之類似的智能合約還有Test1:Github地址:smart-contract-honeypots/Test1.sol3.2股息分配:DividendDistributor

3.2.1蜜罐分析最后一個要介紹的是DividendDistributor,它譯為「股息分配」。GutHub地址:Solidlity-Vulnerable/DividendDistributor.solEtherscan地址:DividendDistributorv3|0x858c9eaf3ace37d2bedb4a1eb6b8805ffe801bba蜜罐的完整代碼如下:

蜜罐合約DividendDistributor的邏輯不算太難,主要有投資、取錢、計算股息等功能,合約中有一個結構體類型的investor,其作用為存儲投資人的投資信息包括投資額度和股息,并且該結構體通過mapping實現賬戶地址到investor的映射。通篇看來下合約并沒有任何的問題,并且如果編譯器版本設置正確的話合約也不會出現任何問題。看一下合約關鍵的函數,invest()、divest()、loggedTransfer()和payDividend(),接下來我們就對這4個函數進行詳細分析。先是invest()函數,其函數功能為用戶調用該函數進行投資,每次的投資數量不能小于要求的最低數量0.4eth,投資后更新相關的變量。完整代碼如下:

divest()函數作為和上面的函數剛好相反,是取出自己投資的金額,函數中一開始就要檢查調用者投資的數量或者調用函數傳入的參數不為0,接著減去該次取錢操作的金額數量,最后從合約所有者賬戶中轉走amount金額給調用者。完整代碼如下:

loggedTransfer()函數的功能非常簡單,就是轉賬和記錄轉賬操作。完整代碼如下:

payDividend()函數為獲得由合約所有者設置的股息。完整代碼如下:

通過分析上面的4個函數,我們發現該蜜罐合約的誘惑點在于投資者不僅能夠隨時存取投資,還可以通過payDividend()函數獲取股息,這樣的合約好像是有利可圖的,然而事實是這是一個陷阱,它利用的就是舊版本編譯器中的漏洞,在Solidity0.4.12之前存在一個漏洞,如果將空字符串作為函數調用時的參數那么編譯器就會跳過該參數。

而在上面的幾個核心函數中,divest()函數就是存在這樣的問題,根據漏洞說明,調用this.loggedTransfer(amount,"",msg.sender,owner);后會變成loggedTransfer(uintamount,bytes32msg.sender,addressowner,address空)最終給owner用戶轉賬owner.call.value(amount)()。下面我們就通過代碼來復現這個蜜罐合約,揭開它的真面目。3.2.2代碼復現

將蜜罐合約的代碼復制到RemixIDE中,將編譯器Solidity的版本設置為0.4.11。

選擇0x5B3作為合約部署者和所有者,點擊「Deploy」進行部署,隨后將VALUE設置為10eth并調用distributeDividends函數設置股息。

將0xAb8作為攻擊者,設置VALUE為10eth并調用invest()函數進行投資。

使用0xAb8調用下圖中的函數獲取該蜜罐合約的相關信息,包括計算股息,自己的投資數額,最小投資數額,合約所有者owner,總的股息和總的投資數額。

繼續使用0xAb8調用divest()函數并設置其傳入參數為5000000000000000000想要取出剛才投資的10eth的一半,發現該交易被確認,查看該交易的logs可以發現和上面我們分析的一樣,target參數變成了owner的地址,第二個參數也被msg.sender所取代,返回查看賬戶當前余額,發現剛才調用divest()函數取出的5eth被轉到了owner賬戶0x5B3中。

4.總結

通過對以太坊蜜罐智能合約的分析,我們可以發現在智能合約中這些有趣的蜜罐合約更像是釣魚,通過各種欺騙手法誘使他人將代幣轉入合約中從而進一步獲取這些代幣。當然蜜罐合約也不是完全沒有學習價值的,我們從蜜罐合約中可以看到合約的攻擊思路以及Solidity的很多新舊特性。在平時的合約審計中也需要考慮這些問題,否則這些合約就可能被黑客攻擊導致合約代幣被盜取。即使是現在,同樣有人編寫蜜罐合約進行誘騙,只是他們的思路不再僅限于那些想要靠天上掉餡餅獲取利益的人,各種機器人也成為了他們的誘騙目標。所以我們一定要重視合約的功能邏輯,防止合約因為功能邏輯被攻擊的同時還要防止合約所有者跑路等各種因素。5.文獻參考

蜜罐技術_百度百科(baidu.com)以太坊蜜罐智能合約分析(seebug.org)Solidity中文手冊

Tags:NUMMBEETHBERnum幣價格Harambe Protocol1X Short Ethereum TokenBlackBerry Network

比特幣
ITA:從品牌賦能與價值增值,一覽當下加密VC

加密風險投資在外界看來往往顯得很模糊,而且很多人認為它是加密空間中最具競爭力和最殘酷的分支之一.

1900/1/1 0:00:00
TOKE:Web3.0學習筆記 :我們需要一個新「Google」| 推薦閱讀

文章來源:轉載微信公眾號橙皮書報紙與搜索引擎的隱喻90年代早期,當web1.0還處于嬰兒期的時候,要發現并找到一個新網站,最主流的方法,是通過雅虎這樣的在線分類門戶網站.

1900/1/1 0:00:00
ING:全面解讀Flamingo DAO:規模最大的DAO用例是如何運作的?

注:DAO一直有點玄學,但今天這篇關于FlamingoDAO的研究報告是從DAO的歷史開始尋根溯源,闡述了最大的DAO用例是如何運作的?以及DAO可能未來發展趨勢等問題.

1900/1/1 0:00:00
IMG:2021年區塊鏈「沙雕新聞」大賞

永載史冊的2021年即將逝去,不管你在行業里是被割、被盜,還是被騙,2021一定讓你沒齒難忘。同樣,今年也有不少沙雕新聞,大家看看今年能不能超過去年的王牌「天氣太熱冷 錢包 變熱」.

1900/1/1 0:00:00
DAO:每周編輯精選 Weekly Editors'' Picks(0115-0121)

「每周編輯精選」是Odaily星球日報的一檔“功能性”欄目。星球日報在每周覆蓋大量即時資訊的基礎上,也會發布許多優質的深度分析內容,但它們也許會藏在信息流和熱點新聞中,與你擦肩而過.

1900/1/1 0:00:00
Polygon:NFT平臺的評級:你想在哪里建立你的數字品牌?

經過多年的發展和迭代,一個多方位的加密貨幣生態系統終于開始出現了。特別是對于像DeFi和NFT這樣的行業,一直都在進行創新。每個新的應用和用例都建立在之前的基礎上.

1900/1/1 0:00:00
ads