背景
今天有人在群里说,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);
}
这句则只是把赠送代币的记录存下来!!!
文转自网络,版权归原作者,如有侵权,请联系我们删除!