什么是ERC20

代币大家应该都很熟悉了,代币也叫 token, 他不是像比特币,以太坊等虚拟币这样建立在大量技术人员的辛苦工作基础之上,用于维持公链运行的虚拟货币。代币一般是依赖于以太坊平台,就是一个以太坊平台上面的一个智能合约里面记录的数字。

所以说token没有任何价值,每个人都可以在1分钟之类创建出无限的token。那么为什么现在有这么多的token价格这么高,还有这么多人去交易呢? 一般来说,发行token的人会将整个token绑定一个很有前途的项目,什么纳米科技,卫星技术,新型动力,怎么牛逼怎么往上面靠,然后找几个币圈有名气的人站台,然后通过各种渠道发布这个token很了不起的舆论,接下来就是上交易所收割韭菜了,至于他们当时标榜的跨时代的项目就不知道是不是能够真的完成了,毕竟钱已经收到口袋里面了。

不可否认,有些token确实很有良心,也真的按照设想的去做了事情。这里不深究发行token的对与错,这里我们讲下ERC20。

大家都来发token,那么这么多的token没有一个统一的标准,不好在以太坊平台进行通用的转让呀,为了便于token的流通,于是出现了一个token的标准叫做ERC20,简单点说,ERC20规定了token智能合约必须要实现的9个方法和2个事件。

具体的方法和事件名请看 ERC-20标准说明

Application Binary Interface(ABI)

这篇文章其实是讲ERC20攻击的,要想攻击ERC20,我们首先要知道怎么去跟以太坊虚拟机进行交互。在以太坊Ethereum 生态系统中, 应用二进制接口Application Binary Interface(ABI) 是从区块链外部与合约进行交互以及合约与合约间进行交互的一种标准方式。 数据会根据其类型按照约定的方法进行编码。

简单点说,一个ABI包括一个函数选择器和函数的参数。

函数选择器是一个函数调用数据的前 4 字节,指定了要调用的函数。这4个字节是函数签名通过 Keccak(SHA-3)哈希之后的前 4 字节。

函数的参数会被编码成32字节,不足32字节的将会补全。ERC20 Short Address Attack 就是在这个函数补全上面出现的。

ERC20 Short Address Attack

我们先看一个简单的token合约,用来转账。

pragma solidity ^0.4.11;

contract MyToken {
mapping (address => uint) balances; event Transfer(address indexed _from, address indexed _to, uint256 _value); function MyToken() {
balances[tx.origin] = 10000;
} function sendCoin(address to, uint amount) returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount;
balances[to] += amount;
Transfer(msg.sender, to, amount);
return true;
} function getBalance(address addr) constant returns(uint) {
return balances[addr];
}
}

很简单的一个智能合约, 这里我们看下sendCoin的方法,他接收2个参数,一个是接收token的地址,一个是数目。

如果想进行调用,那么生成的ABI可能是这样的:

0x90b98a11
00000000000000000000000062bec9abe373123b9aabbcce608f94eb8644163e
0000000000000000000000000000000000000000000000000000000000000004

其中:

0x90b98a11 是Keccak (SHA-3) 运算之后的方法标记 sha3(sendCoin(address,uint))。

00000000000000000000000062bec9abe373123b9aabbcce608f94eb8644163e 是 20字节的目标地址,被补全到32字节。

0000000000000000000000000000000000000000000000000000000000000004 是 1个字节的4被补全到32字节。

开始攻击

如果攻击者不按常理出牌,并不将参数补全到32字节,那么总的ABI长度会比预料的要小,那么会出现什么问题呢?

还是上面的例子,我们要发送4个token到62bec9abe373123b9aabbcce608f94eb8644163e。

但是我们把地址的最后1个字节“3e”去掉,那么ABI如下所示:

0x90b98a11
00000000000000000000000062bec9abe373123b9aabbcce608f94eb8644163e00
00000000000000000000000000000000000000000000000000000000000004
^^

我们可以看到,最后的04后面其实是少了一个字节的。

那么如果我们把这个ABI传给以太坊虚拟机,会出现什么问题呢?

以太坊虚拟机会将ABI补全,就是在04后面加一个字节00。

参数如下:

_from: 0x58bad47711113aea5bc5de02bce6dd332211aabb
_to: 0x62bec9abe373123b9aabbcce608f94eb8644163e00
_value: 2048

我们看到两个变化,第一目标地址变了,第二转移的数值变了:4<<8 = 2048。

这个就是ERC20 Short Address Attack。

怎么利用?

  1. 攻击者构建一个最后一个字节为0的地址A。
  2. 攻击者找到一个发行token的智能合约,在这个智能合约里面,向A存入500token。
  3. 攻击者从智能合约转出500token到地址A,但是将地址A最后一个字节的0去掉。
  4. 地址A最后1个字节会被补全,而转账的500token就变成了500<<8。

攻击防范

防范起来其实很简单,做好必要的参数校验即可。

下面的代码加了一个modifier onlyPayloadSize 。 在这个modifier里面,我们做了参数长度的校验。

pragma solidity ^0.4.11;

contract MyToken {
mapping (address => uint) balances; event Transfer(address indexed _from, address indexed _to, uint256 _value); function MyToken() {
balances[tx.origin] = 10000;
} modifier onlyPayloadSize(uint size) {
assert(msg.data.length == size + 4);
_;
} function sendCoin(address to, uint amount) onlyPayloadSize(2 * 32) returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount;
balances[to] += amount;
Transfer(msg.sender, to, amount);
return true;
} function getBalance(address addr) constant returns(uint) {
return balances[addr];
}
}

更多教程请参考flydean的博客

ERC20 Short Address Attack的更多相关文章

  1. Identifying a distributed denial of service (DDOS) attack within a network and defending against such an attack

    The invention provides methods, apparatus and systems for detecting distributed denial of service (D ...

  2. 【转】zigbee终端无法重连的问题解决

    zigbee终端无法重连的问题解决 1.zigbee重连的原因 (1)zigbee由于各种原因的干扰导致信号太差而掉线. (2)协调器重启. 2.zigbee终端重连的处理 (1)zigbee掉线后会 ...

  3. 【转】ZigBee终端入网方式深入分析

    前述 继之前对终端Direct Join的分析,发现很多东西还很模糊,存在很多问题.终于找到时间继续深入挖下去,这次应该比较完整地搞清了终端的入网机制,并纠正之前的几个认识偏差. 由于Z-Stack网 ...

  4. Masonry使用注意事项

    1 理解自身内容尺寸约束与抗压抗拉 自身内容尺寸约束:一般来说,要确定一个视图的精确位置,至少需要4个布局约束(以确定水平位置x.垂直位置y.宽度w和高度h).但是,某些用来展现内容的用户控件,例如文 ...

  5. 第1章 ZigBee协议栈初始化网络启动流程

    作者:宋老师,华清远见嵌入式学院讲师. ZigBee的基本流程:由协调器的组网(创建PAN ID),终端设备和路由设备发现网络以及加入网络. 基本流程:main()->osal_init_sys ...

  6. Ztack学习笔记(4)-系统网络分析

    协调器的组网,终端设备和路由设备发现网络以及加入网络 //第一步:Z-Stack 由 main()函数开始执行,main()函数共做了 2 件事:一是系统初始化,另外一件是开始执行轮转查询式操作系统 ...

  7. 关于NuDaqPci 数据采集

    最近在做公司一个fct的测试及调试软件 设计到的比较多的通信问题 1,Gpib通信(调用ADL-GPIB) 2,串口通信 3,Usb通信(调用USBXpress) 4,Pci通信(调用PCIS-DAS ...

  8. CodeForces250B——Restoring IPv6(字符串处理)

    Restoring IPv6 DescriptionAn IPv6-address is a 128-bit number. For convenience, this number is recor ...

  9. sockaddr_u详解

    struct sockaddr { unsigned short sa_family;     /* address family, AF_xxx */ char sa_data[14];       ...

随机推荐

  1. J. Justifying the Conjecture(规律——整数拆分)

    题目链接 五校友谊赛终于开始了,话不多说A题吧. 从前从前有一个正整数n,你需要找到一个素数x和一个合数y使x+y=n成立,这样就可以双剑合并了. 素数是一个大于1的自然数,它的因数只有1与它自己本身 ...

  2. XXE白盒审计 PHP

    XXE与XML注入的区别 https://www.cnblogs.com/websecurity-study/p/11348913.html XXE又分为内部实体和外部实体.我简单区分为内部实体就是自 ...

  3. preg_replace突然感觉好强大啊

    <p><img align="absmiddle" src="https://img.alicdn.com/imgextra/i1/1696415374 ...

  4. ThinkPHP3.2.3发送微信模板消息

    一.开通模板消息功能 所有服务号都可以在功能->添加功能插件处看到申请模板消息功能的入口,但只有认证后的服务号才可以申请模板消息的使用权限并获得该权限:需要选择公众账号服务所处的2个行业,每月可 ...

  5. 学习《深入应用c++11》2

    &&   universal references(未定的引用类型),它必须被初始化,它是左值还是右值取决于它的初始化,如果&&被一个左值初始化,它就是一个左值;如果它 ...

  6. qad progress数据库启动出错解决

    1. 启动时报:SYSTEM ERROR: Wrong dbkey in block. Found 0, should be 6342528 in area 36.  (439) ** Save fi ...

  7. OSI 七层模型以及TCP/IP模型

    OSI 七层模型 定义 OSI(Open System Interconnection)即开放式系统互联通信参考模型.该模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一 ...

  8. stand up meeting 12/01/2015

    part 组员 今日工作 工作耗时/h 明日计划 工作耗时/h UI 冯晓云   赶工sprint3,各部分要合在一起时出现各种问题,各种修改测试:UI本身的功能继续实现完善    6 UWP对控件的 ...

  9. Ignatius and the Princess IV HDU 1029

    题目大意: n个数字,找出其中至少出现(n+1)/2次的数字,并且保证n是奇数. 题解:这道题数组是不能用的,因为题目没有明确输入的数据范围,比如输入了一个1e9,数组肯定开不了这么大.所以要用map ...

  10. The equation SGU - 106

    题目链接:https://codeforces.com/problemsets/acmsguru/problem/99999/106 这个题是关于EXGCD特别好的一个题目.题目大意:有一个等式ax+ ...