WF曲速未来消息:在8月 22 日,一个名不见经传的游戏God.Game发出通告,声称遭遇黑客攻击,游戏内的以太币被黑客全部转走。
前言:
WF曲速未来消息:在8月 22 日,一个名不见经传的游戏God.Game发出通告,声称遭遇黑客攻击,游戏内的以太币被黑客全部转走。盗走ETH的黑客地址为:0xC30E89DB73798E4CB3b204Be0a4C735c453E5C74。
God.Game简单规则如下:GOD股份购买的所有数量的10%被征税并且作为被动的ETH收入分配给所有GOD所有者。
通过游戏官网规则,以及合约源码分析,不少人会认为God.Game是PoWH3D的直接仿品,安比(SECBIT)实验室仔细分析后发现,它其实是综合“借鉴”PoWH3D 和Zethr的混合仿品。
PoWH3D是最近大热的Fomo3D游戏团队上一款作品。而Zethr则是在PoWH3D基础上进一步开发优化,新增不同玩法的另一款热门游戏。
然后对其进行了详细的分析,得出其根本原因是由于某处关键数据整型溢出漏洞导致...
上面提到,God.Game游戏代码重度参考了PoWH3D和Zethr。而与漏洞相关的关键函数名transferFromInternal()只在Zethr合约代码中有出现。
上图所示问题代码,“创新”地增加了一组关于转账双方是合约、还是普通账户的分支情况处理。面对这一串冗长的代码,只要清楚PoWH3D工作原理,就很容易能发现此处代码逻辑根本说不通,也无法在游戏实际规则中找到适配点。并且这种根据账户类型分别处理账本的逻辑在原版PoWH3D和Zethr中根本没有出现。
攻击手法:
黑客地址:0x2368beb43da49c4323e47399033f5166b5023cda。
黑客的攻击步骤:
1.攻击者购买少量token;
2.创建攻击合约;
3.把token转给攻击合约;
4.调用攻击合约的withdraw函数
5.调用攻击合约的transfer函数
6.调用攻击合约的reinvest函数
7.调用攻击合约的sell函数
8.调用攻击合约的transfer函数
这便是该黑客一系列的攻击步骤,乍一看,充满迷雾,攻击合约也没开源,只能靠逆向,经过层层分析,该攻击合约只是相当于一个“代理”,举个例子,攻击者若调用攻击合约的withdraw函数,那么该攻击合约就会去调用godgame的withdraw函数,然后再把结果返回给攻击者。
那攻击者为何要使用攻击合约间接调用而不直接调用godgame合约,为何要调用这些函数呢?这便是本文的重点了,以下会对攻击者的每个步骤进行剖析。
分析
在理解漏洞之前我们需要先了解一下该合约中几个重要变量,方便后续理解:
1.payoutsTo变量,该变量是用于存储某个用户消费了多少分红;
2.profitPerShare,该变量用于存储当前God代币所能产生的分红比例,非固定,是浮动的;
3.tokenBalanceLedger,该变量用户存储某个用户的代币余额;
4.mydi vidends,获取当前用户的分红余额;
PS:看到上面几个变量,有些人应该会很熟悉,没错,说得就是PoWH3D,这个合约代码和风靡一时的PoWH3D极其相似,熟悉PoWH3D的应该很容易理解。
那么:这些变量之间的有何关联?
profitPerShare和tokenBalanceLedger的乘积便是某个用户所能得到的分红,但不是mydi vidends(最终的分红余额),因为有payoutsTo(分红支出),所以最终用户的分红余额的简化版计算方式为:
从上面的公示能够得到一个结论,那就是profitPerShare * tokenBalanceLedger是必须大于payoutsTo的,否则,在计算最终分红余额的过程中就会发生溢出,将导致显示的分红余额数值非常大。
然后再进一步推导,在没做容错的情况下(该合约确实没对计算最终分红进行容错处理),当profitPerShare * tokenBalanceLedger减少时,payoutsTo的值也需要进行一定量的减少,否则便会出现上述溢出的情况。
再进一步分析,在检查profitPerShare变量所有可能的更改情况,发现了该变量不会减少,只会增加,所以就可以再进一步得出:
当tokenBalanceLedger减少时,payoutsTo也需要进行一定量的减少,否则会产生溢出。
根据合约代码,就会发现只有transfer系列的函数会导致tokenBalanceLedger减少
根据如上代码,transfer函数最终都回调用transferFormInternal函数来进行实际转账,我们继续来看。
太冗长了,我们挑其中的重点看一下:
重点一
通过这一段可以看到,在tokenBalanceLedger_[_from]减少时,payoutsTo_[_from]也会进行相应的减少,这是没问题的,但是我们注意到了“human to human”这个注释,难道contract to human还会有不同的情况?紧接着往上看contract to human的部分。
重点二
注意!在这段代码里面很明显没有对payoutsTo_[_from]有任何减少操作,通过我们上面推导出来的理论,这里没对payoutsTo做处理很可能导致计算最终分红余额的时候产生溢出。
好了,我们再回头看黑客的攻击手法:
前面的不重要,我们直接从黑客的第4个步骤,调用withdraw来解释,先看代码:
上面的代码中我们自行加了一段注释,调用这个函数的目的很明显,增加payoutsTo的值,使计算最终分红余额的时候有溢出的条件。
然后是第5个步骤,调用transfer函数,通过上面的讲解,这里意义也很明确,减少tokenBalanceLedger的值,因为transfer对contract to human的处理不当,导致tokenBalanceLedger的值减少了,而payoutsTo的值没减少,满足溢出条件。
第6个步骤,调用reinvest函数,因为在第5个步骤中已经使分红余额溢出了,调用reinvest将分红转换成token。
第7个步骤,调用sell函数,因为调用reinvest产生了大量的token,godgame一个游戏机制是,流通的token那么token的价格就越高,产生这批token已经导致token的购买价格为天价,于是攻击者调用sell函数来销毁一部分token让token的价格降到正常,以便自己能顺利提款。
第8个步骤,调用transfer函数,将token转移到另外的账户,然后另外的账户直接将token兑换成分红后提现。
总结:
WF曲速未来建议:对于合约的转账数量,一定要需要进行严密逻辑验证。
领取专属 10元无门槛券
私享最新 技术干货