在本篇文章中,我将通过一个攻击事件引出 Reflection Token 攻击事件的一个通用分析思路。

关于 Reflection Token 的其他案例分析,可以参考BEVO代币攻击事件分析及复现一文。

TomInu 攻击事件

TomInu Token 是一个反射型代币 reflection token,于2023-01-26遭到黑客攻击,攻击者获利35577美元。

TomInu(被攻击合约): 0x2d0e64b6bf13660a4c0de42a0b88144a7c10991f

攻击交易: https://phalcon.blocksec.com/tx/eth/0x6200bf5c43c214caa1177c3676293442059b4f39eb5dbae6cfd4e6ad16305668

攻击过程较为简单,攻击者通过几个常规操作就完成获利。

  1. 攻击者借出闪电贷
  2. 用 WETH swap 出 1465904852700232013011 TINU
  3. deliver 1465904852700232013011 TINU
  4. skim 得到 1733770910894426471783 TINU(在这一步已经完成了获利)
  5. 把 TINU swap 为 WETH
  6. 归还闪电贷

本次攻击事件通过推文告警并且进行了分析,但是很可惜分析的结论略显含糊的。红框标注的部分并不是攻击者获利的真正原因。(为什么不是真的)

推文:https://twitter.com/QuintenDes/status/1618730379447508998

并且,目前在在网络上搜索到的所有关于 reflection token 攻击事件的成因分析中提到:“由于攻击者 deliver 了一笔 token ,导致了 pair 中的 token 升值,从而能够 skim 出更多的 token 进行获利”。这类分析大多是理所当然地下结论,没有通过实际的计算推导,妄下结论误导读者。(为什么这么说)

攻击过程很简单,先 deliver 然后 skim,就能够获利了。根据这个攻击过程的特征,我们直接找 rToken增发代码,定位漏洞点。(为什么可以这么做)

以上的几个为什么都将会在后面“为什么”这一章节进行解释,读者可以先带着疑问进行阅读。

漏洞分析

_transferStandard 函数中可以看出,TomInu 代币在进行转账 rAmount 时需要收取 teamfee 两种手续费,并将扣除了手续费后的 rTransferAmount 转给收款人。

其中 team 手续费 rteam 留存在本合约中,fee 手续费 rfee 则是直接销毁。

此时他们的数量关系应该为:rTransferAmount = rAmount - rteam - rfee

问题出现在 _getRValues 函数中,该函数在计算 rTransferAmount 的过程中忽略了 rteam 参数,计算 rTransferAmount = rAmount - rfee 得到的结果比实际结果要大,造成了 rToken 的增发。也就是说,因为这个计算问题,市场上实际流通的 rAmount 总和是要大于 rTotal 的值的。

代币合约在执行 _transfer() 函数的时候,会将本合约的代币 swap 成 ETH,这个操作使得增发的代币一直累计在 pair 中。

为什么

在这个章节中,会对前面的暴言暴论进行解释

  1. 为什么推文中的关于漏洞成因的结论是含糊的不准确的。
  2. 什么说关于 reflection token 攻击事件的成因分析中提到“由于攻击者 deliver 了一笔 token ,导致了 pair 中的 token 升值,从而能够 skim 出更多的 token 进行获利”的分析结论都是错误的。
  3. 为什么看到攻击过程先 deliver 然后 skim 就完成获利之后,我得出的结论是直接找 rToken增发代码定位漏洞点。

首先我将举几个例子来模拟整个 deliver-skim 的过程,为了使得这个例子尽可能的简单,这个过程中将不考虑任何手续费的收取。

场景1:

只有 attacker 和 pair 持有所有的 token

rTotal 1000, tTotal 100, rate 10

pair: rAmount 500, tAmount 50
attacker: rAmount 500, tAmount 50

attacker deliver 500 rAmount

rTotal 500, tTotal 100, rate 5

pair: rAmount 500, tAmount 100
attacker: rAmount 0, tAmount 0

此时,pair 的 tAmount 从 50 变成了 100。接下来 attacker 将调用 skim 来获利了是不是?

attacker calls pair.skim()

rTotal 500, tTotal 100, rate 5

pair: rAmount 250, tAmount 50
attacker: rAmount 250, tAmount 50

attacker 如愿以偿获利了吗?没有,attacker 和 pair 又回到了最初的 50 tAmount,并不能通过这个操作来进行获利。

场景2:

attacker, pair 以及一些其他用户共同持有所有的 token

rTotal 1000, tTotal 100, rate 10

pair: rAmount 250, tAmount 25
attacker: rAmount 500, tAmount 50
others: rAmount 250, tAmount 25

attacker deliver 500 rAmount

rTotal 500, tTotal 100, rate 5

pair: rAmount 250, tAmount 50
attacker: rAmount 0, tAmount 0
others: rAmount 250, tAmount 50

attacker calls pair.skim()

rTotal 500, tTotal 100, rate 5

pair: rAmount 125, tAmount 25
attacker: rAmount 125, tAmount 25
others: rAmount 250, tAmount 50

pair 回到了原始的 25 tAmount,而 attacker 由原来的 50 亏损到了 25 tAmount。坚定持有的 others 由 25 上涨到了 50 tAmount。

通过上面的两个例子,我们可以得出结论,只有当 attacker 和 pair 所持有的代币份额合计 100% 的情况下,deliver-skim 的操作 attacker 才不会亏损。而两者份额不足 100% 的情况下,deliver-skim 的操作反而会导致 attacker 遭受损失。也就是说 attacker 通过 deliver-skim 的操作无论怎么样都是不赚的,最好的情况是 attacker 和 pair 所持有的代币份额合计 100% 的情况下才不至于亏损。

那么…有没有更好的情况呢?好到…两者持有的代币份额合计起来…超过100%

比如,发生了代币增发?

场景3:

由于代码存在 rToken 相关的计算错误,导致代币增发的发生,具体表现为 rToken 的实际流通量大于 rTotal 的数量。

rTotal 1000, tTotal 100, rate 10

pair: rAmount 400, tAmount 40
attacker: rAmount 800, tAmount 80
others: rAmount 400, tAmount 40 sum_rAmount = 1600 > rTotal = 1000
pair.rAmount + attacker.rAmount = 1200 > rTotal = 1000

attacker deliver 800 rAmount

rTotal 200, tTotal 100, rate 2

pair: rAmount 400, tAmount 200
attacker: rAmount 0, tAmount 0
others: rAmount 400, tAmount 200

attacker calls pair.skim()

rTotal 200, tTotal 100, rate 2

pair: rAmount 80, tAmount 40
attacker: rAmount 320, tAmount 160
others: rAmount 400, tAmount 200

至此,attacker 从原来的 80 tAmount,通过 deliver-skim 操作获利达到 160 tAmount。

通过这个场景,也就可以解释为什么看到攻击过程中通过 deliver-skim 操作获利时,首先想到的就是去找代码中使得 rAmount 增发的计算操作。因为只有 rAmount 发生了增发,pair 和 attacker 的份额大于 100%,且增发部分需要留存在 pair 合约中,才能够满足通过 deliver-skim 操作进行获利的基础条件。

后记

在 TomInu 攻击事件发生的4个月后,存在相同漏洞的 ADU token 再次被攻击。

ADU token attack tx:https://explorer.phalcon.xyz/tx/bsc/0xc6f6b70e9e35770b699da9b60244d461d02db66859df42319c3207d76931423c

为什么会写这篇文章,因为当我想对这些攻击事件进行学习与分析的时候,我查看了网络上的分析文章,他们给出的漏洞成因含糊不清毫无根据。我读了很多篇分析文章,说辞都是大同小异地糊弄。还没分析清楚就胡乱指点,最终被忽悠的就是真心想研究清楚的人。走了不少弯路,把弯路总结成这篇文章,感谢你的阅读。

【漏洞分析】Reflection Token 反射型代币攻击事件通用分析思路的更多相关文章

  1. 以太坊钱包开发系列4 - 发送Token(代币)

    以太坊去中心化网页钱包开发系列,将从零开始开发出一个可以实际使用的钱包,本系列文章是理论与实战相结合,一共有四篇:创建钱包账号.账号Keystore文件导入导出.展示钱包信息及发起签名交易.发送Tok ...

  2. Go-Ethereum 1.7.2 结合 Mist 0.9.2 实现代币智能合约的实例

    目录 目录 1.什么是 Mist 2.Mist 在哪里下载? 3.Mist 有哪些依赖? 4.如何安装 Mist? 4.1.安装 Mist 依赖工具包 4.2.安装 Mist 4.3.启动 Mist, ...

  3. AMR无限增发代币至任意以太坊地址的漏洞利用及修复过程

    AMR无限增发代币至任意以太坊地址的漏洞利用及修复过程 0x00 项目简述 Ammbr主要目标是打造具有高度弹性且易于连接的分布式宽带接入平台,同时降低上网相关成本.Ammbr打算创建具有人工智能和智 ...

  4. Facebook币Libra学习-6.发行属于自己的代币Token案例(含源码)

    在这个简短的概述中,我们描述了我们在eToro标记化资产背后实施技术的初步经验,即MoveIR语言中的(eToken),用于在Libra网络上进行部署. Libra协议是一个确定性状态机,它将数据存储 ...

  5. STO(Security Token Offering)证券型通证、代币发行介绍

    STO(Security Token Offering)证券型通证.代币发行介绍:STO(Security Token Offering)是一个新的融资概念.通过证券化的通证进行融资.早在2017年年 ...

  6. 通过以太坊发行代币(token)

    2017年开始,区块链ICO项目层出不穷,市场热度一波更胜一波,很多ICO都是通过以太坊智能合约发行自己的代币(token),具体怎样才能发行代币呢?本文进行具体详细的介绍. 准备工作 以太坊官网ER ...

  7. 区块链代币(Token)笔记 — — 术语

    前言 接触区块链和数字货币差不多有大半年时间,一直在赶项目进度,现在有空整理补习一下相关的知识,只谈代币不谈区块链

  8. 证券化代币的时代已经到来,STO将引爆区块链经济

    STOs 似乎会在 2019 年取代 ICOs,即使不是完全取代,但置换的比例也会相当大.所有在美上市的公司都将按照 SEC 制定的相关规定进行交易.Vellum Capital 的 CEO 兼管理合 ...

  9. MakerDAO 代币解释:DAI, WETH, PETH, SIN, MKR(一)

    Maker DAO Token Maker DAO 系统是由多个智能合约 ( Sai Tap, Sai Tub, Vox, Medianiser, etc.), 和 ERC-20 代币组成. 他们一起 ...

  10. 【在 Nervos CKB 上做开发】Nervos CKB 脚本编程简介[3]:自定义代币

    原文作者:Xuejie 原文链接:https://xuejie.space/2019_09_06_introduction_to_ckb_script_programming_udt/ Nervos ...

随机推荐

  1. DASCTF 2023 & 0X401七月暑期挑战赛

    比赛只出了一道,小菜不是罪过-_- controlflow 这个题动调到底就行 for i in range(40): after_xor[i]=inp[i]^0x401 after_xor[i] + ...

  2. Java应用堆外内存泄露问题排查

    问题是怎么发现的 最近有个java应用在做压力测试 压测环境配置: CentOS系统 4核CPU 8g内存 jdk1.6.0_25,jvm配置-server -Xms2048m -Xmx2048m 出 ...

  3. 银河麒麟SP2 auditd服务内存泄露问题

    这几天遇到基于海光服务器的银河麒麟V10 SP2版本操作系统出现内存无故增长问题. 排查发现auditd服务,占用了大量内存. 我的环境是银河麒麟V10 SP2 524,audit版本audit-3. ...

  4. O2OA(翱途)开发平台 V8.1正式发布

    尊敬的O2OA(翱途)平台合作伙伴.用户以及亲爱的开发小伙伴们,平台 V8.1版本已正式发布.正值8月的最后一周,我们以更安全.更高效.更好用的崭新面貌迎接9月的到来. O2OA开发平台v8.1版本更 ...

  5. Socket.io入门

    Socket.io入门 根据官方文档socket.io使用必须客户端根服务端一致,socket.io不兼容webSocket或者其他模块,因为socket.io在连接时做了自定义处理, 所以不同的长连 ...

  6. Python从0到1丨详解图像锐化的Sobel、Laplacian算子

    本文分享自华为云社区<[Python从零到壹] 五十八.图像增强及运算篇之图像锐化Sobel.Laplacian算子实现边缘检测>,作者: eastmount . 一.Sobel算子 So ...

  7. Solidity-变量和数据类型[复合类型_1]

    复合类型的数据包括:array(数组).struct(结构体)和mapping(映射),其中array和struct也称为引用类型. 复合类型 数组(array) 数组(array)是一种用于存储相同 ...

  8. Solution -「BZOJ 3779」重组病毒

    Description Link. Given is a tree. Every node initially has a color which is different from others'. ...

  9. 深入解析枚举(Enum):在程序设计中的应用与优势

    深入解析枚举(Enum):在程序设计中的应用与优势 引言 在程序设计中,我们经常需要用到一组具名的常量,这些常量表示一些有限的离散状态或取值范围.例如,表示方向(上.下.左.右).星期几.性别等.为了 ...

  10. mysql学习之数据备份和恢复

    一.使用mysqldump进行备份 如:将test数据库备份到/tmp/mysql_back/目录下 [root@localhost tmp]# mysqldump -uroot -p111 -l - ...