ce安全网绿色资源分享

教程资讯|常用软件|安卓下载|下载排行|最近更新

软件
软件
文章
当前位置:首页网络安全安全新闻 → 黑客用一行代码蒸发了 6,447,277,680 人民币

黑客用一行代码蒸发了 6,447,277,680 人民币

时间:2018-04-23 00:00:00人气:作者:本站作者我要评论

美图董事长蔡文胜曾在三点钟群,高调的说出了这句话,随即被大众疯传。

在他发表完言论没多久,2月美链(BEC)上交易所会暴涨4000%,后又暴跌。尽管他多次否认,聪明的网友早已扒出,他与BEC千丝万缕的关系。

黑客用一行代码蒸发了 6,447,277,680 人民币

庄家坐庄操控币价,美图的股价随之暴涨,蔡文胜顺利完成了他的韭菜收割大计。

但在币圈,割人者,人恒割之。

随着BEC智能合约的漏洞的爆出,被黑客利用,瞬间套现抛售大额BEC,60亿在瞬间归零。

而这一切,竟然是因为一个简单至极的程序Bug。

背景

今天有人在群里说,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

黑客用一行代码蒸发了 6,447,277,680 人民币

下面我来带大家看看,黑客是如何实现的!

我们可以看到执行的方法是 batchTransfer

那这个方法是干嘛的呢?(给指定的几个地址,发送相同数量的代币)

整体逻辑是

你传几个地址给我(receivers),然后再传给我你要给每个人多少代币(value)

然后你要发送的总金额 = 发送的人数* 发送的金额

然后 要求你当前的余额大于 发送的总金额

然后扣掉你发送的总金额

然后 给receivers 里面的每个人发送 指定的金额(value)

从逻辑上看,这边是没有任何问题的,你想给别人发送代币,那么你本身的余额一定要大于发送的总金额的!

但是这段代码却犯了一个很傻的错!

代码解释

黑客用一行代码蒸发了 6,447,277,680 人民币

这个方法会传入两个参数

  1. _receivers
  2. _value

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

0x0e823ffe018727585eaf5bc769fa80472f76c3d7

0xb4d30cac5124b46c2df0cf3e3e1be05f42119033

_value 的值是 8000000000000000000000000000000000000000000000000000000000000000

是获取 _receivers 里面有几个地址,我们从上面可以看到 参数里面只有两个地址,所以 cnt=2,也就是 给两个地址发送代币

uint256 amount = uint256(cnt) * _value;

uint256

首先 uint256(cnt) 是把cnt 转成了 uint256类型

那么,什么是uint256类型?或者说uint256类型的取值范围是多少...

uintx 类型的取值范围是 0 到 2的x次方 -1

也就是 假如是 uint8的话

则 uint8的取值范围是 0 到 2的8次方 -1

也就是 0 到255

那么uint256 的取值范围是

115792089237316195423570985008687907853269984665640564039457584007913129639935

python 算 2的256次方是多少

那么假如说 设置的值超过了 取值范围怎么办?这种情况称为 溢出

举个例子来说明

因为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,所以当前用户代币的余额没有变动

  1. for (uint i = 0; i < cnt; i++) {
  2. balances[_receivers[i]] = balances[_receivers[i]].add(_value);
  3. Transfer(msg.sender, _receivers[i], _value);
  4. }

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

balances[_receivers[i]] = balances[_receivers[i]].add(_value); _receivers中的地址 的余额 = 原本余额+value

57896044618658097711785492504343953926634992332820282019728792003956564819968 个代币!!!

Transfer(msg.sender, _receivers[i], _value); } 这句则只是把赠送代币的记录存下来!!!

总结

那么 我们如何避免这种问题呢?

我个人看法是

  1. 只要涉及到计算,一定要用safeMath
  2. 代码一定要测试!
  3. 代码一定要review!
  4. 必要时,要请专门做代码审计的公司来 测试代码

黑客用一行代码蒸发了 6,447,277,680 人民币

这件事后需要如何处理呢?

目前,该方法已经暂停了(还好可以暂停)所以看过文章的朋友 不要去测试了...

相关文章

猜你喜欢

  • 深入解析浅谈《快3单双准确率方法》成功方案

    2022-09-28 /

  • 全网首发《快3单双大小必中方法技巧》思路汇总

    2022-09-28 /

  • 资深攻略《快3大小必中技巧》上岸方法

    2022-09-28 /

  • 【最准确的玩法】《回血上岸计划导师QQ》操作系列

    2022-09-28 /

  • 经验教程《导师一分快三计划》最新窍门

    2022-09-28 /

  • 高手教你《大小单双最安全的打法》三期必中

    2022-09-28 /

网友评论

验证码:

请自觉遵守互联网相关政策法规,评论内容只代表网友观点,与本站立场无关!

最新评论

已有人参与,点击查看更多精彩评论

本类推荐

关于CE安全网 | 联系方式 | 发展历程 | 版权声明 | 下载帮助(?) | 广告联系 | 网站地图 | 友情链接

Copyright 2019-2029 cesafe.com 【CE安全网】 版权所有 琼ICP备2021004244号-1| 琼ICP备2021004244号-1

声明: 本站为非赢利性网站 不接受任何赞助和广告 所有软件和文章来自互联网 如有异议 请与本站联系 技术支持:ce安全网