极客秀
搜索

因为一行代码,蒸发了¥6,447,277,680…程序员又要背锅了!!

背景

今天有人在群里说,Beauty Chain美蜜代码里面有bug,已经有人利用该bug获得了:

57,896,044,618,658,100,000,000,000,000,000,000,000,000,000,000,000,000,000,000.792003956564819968
个BEC
那笔操作记录 是
0xad89ff16fd1ebe3a0a7cf4ed282302c06626c1af33221ebe0d3a470aba4a660f

下面我来带大家看看,黑客是如何实现的!
我们可以看到执行的方法是 batchTransfer
那这个方法是干嘛的呢?(给指定的几个地址,发送相同数量的代币

代码解释


这个方法会传入两个参数

_receivers

_value
_receivers 的值是个列表,里面有两个地址

  • 0x0e823ffe018727585eaf5bc769fa80472f76c3d7
  • 0xb4d30cac5124b46c2df0cf3e3e1be05f42119033
    _value 的值是 8000000000000000000000000000000000000000000000000000000000000000
    我们再查看代码(如下图)

    举个例子来说明
    因为uint256的取值太大了,所以用uint8来 举例。。。
    从上面我们已经知道了 uint8 最小是0,最大是255
    那么当我 255 + 1 的时候,结果是啥呢? 结果会变成0
    那么当我 255 + 2 的时候,结果是啥呢? 结果会变成1
    那么当我 0 – 1 的时候,结果是啥呢? 结果会变成255
    那么当我 0 – 2 的时候,结果是啥呢? 结果会变成254
    那么 我们回到上面的代码中,

amount = uint256(cnt) * _value

amount = 2* _value
但是此时 _value 是16进制的,我们把他转成 10进制
(python 16进制转10进制)

可以看到 _value = 57896044618658097711785492504343953926634992332820282019728792003956564819968
那么amount = _value*2 = 115792089237316195423570985008687907853269984665640564039457584007913129639936
可以在查看上面看到 uint256取值范围最大为 115792089237316195423570985008687907853269984665640564039457584007913129639935
此时,amout已经超过了最大值,溢出 则 amount = 0
下一行代码 require(cnt > 0 && cnt <= 20); require
语句是表示该语句一定要是正确的,也就是 cnt 必须大于0 且 小于等于20
我们的cnt等于2,通过!
require(_value > 0 && balances[msg.sender] >= amount);
这句要求 value 大于0,我们的 value是大于0 的 且,当前用户拥有的代币余额大于等于 amount,因为amount等于0,所以
就算你一个代币没有,也是满足的!
balances[msg.sender] = balances[msg.sender].sub(amount);

这句是当前用户的余额 – amount
当前amount 是0,所以当前用户代币的余额没有变动

for ( uint i = 0 ; i < cnt ; i ++ ) {

balances [ _receivers [ i ]] = balances [ _receivers [ i ]].
add ( _value );

Transfer ( msg . sender , _receivers [ i ], _value );

}

这句是遍历 _receivers中的地址, 对每个地址做以下操作

balances[_receivers[i]] = balances[_receivers[i]].add(_value);
_receivers中的地址的余额 = 原本余额+value
所以 _receivers 中地址的余额
则加了57896044618658097711785492504343953926634992332820282019728792003956564819968
个代币!!!
Transfer(msg.sender, _receivers[i], _value); }
这句则只是把赠送代币的记录存下来!!!
文转自网络,版权归原作者,如有侵权,请联系我们删除!

1.转载请保留原文链接谢谢!
2.本站所有资源文章出自互联网收集整理,本站不参与制作,如果侵犯了您的合法权益,请联系本站我们会及时删除。
3.本站发布资源来源于互联网,可能存在水印或者引流等信息,请用户擦亮眼睛自行鉴别,做一个有主见和判断力的用户。
4.本站资源仅供研究、学习交流之用,若使用商业用途,请购买正版授权,否则产生的一切后果将由下载用户自行承担。
5.联系方式(#替换成@):pm#vimge.com

  相关内容