在本篇文章中,我将通过一个攻击事件引出 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 时需要收取 team 和 fee 两种手续费,并将扣除了手续费后的 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. P3874 砍树 题解

    前置 树形 dp,二分. 题意 本质上是一个树上背包,需要选不少于 \(k\) 个物品,每个物品有一个重量 \(w\) 和价值 \(v\),求性价比最大值. 分析 既然是性价比,显然是分数规划. 先介 ...

  2. 我是如何使用Spring Retry减少1000 行代码

    本文翻译自国外论坛 medium,原文地址:https://levelup.gitconnected.com/how-i-deleted-more-than-1000-lines-of-code-us ...

  3. 【微信自动化】使用c#实现微信自动化

    引言 上个月,在一个群里摸鱼划水空度日,看到了一个老哥分享的一个微信自动化的一个类库,便下载了他的Demo,其本意就是模拟鼠标来操作UI,实现UI自动化:然后自己在瞎琢磨研究,写了一个简单的例子,用来 ...

  4. 算术逻辑单元的实现(ALU)

    一.实验目的 掌握Vivado集成开发环境 掌握Verilog语言基本知识. 掌握并理解算术逻辑单元ALU的原理和设计 二.实验预习 1.ALU(算术逻辑单元)的16种运算的编码 三.模块接口设计 A ...

  5. 算法笔记_python

    目录 算法 概念 时间复杂度 空间复杂度 递归原理 顺序查找 二分查找 列表排序 LowB 三人组 冒泡排序 选择排序 插入排序 NB三人组 快速排序 堆排序 归并排序 NB三人组小结 总结 其他排序 ...

  6. 《Python魔法大冒险》004 第一个魔法程序

    在图书馆的一个安静的角落,魔法师和小鱼坐在一张巨大的桌子前.桌子上摆放着那台神秘的笔记本电脑. 魔法师: 小鱼,你已经学会了如何安装魔法解释器和代码编辑器.是时候开始编写你的第一个Python魔法程序 ...

  7. Row Major

    Smiling & Weeping ----昨天, 别人在我身旁大声说出你的名字, 这对于我, 像从敞开的窗口扔进了一朵玫瑰花. 思路:不客气地说,这是一道令人费解的题目,要求构造一个字符串, ...

  8. 使用C#发送邮件支持 Implicit SSL

    安装Package: Install-Package AIM 使用下面的代码发送: class Mail { private static string mailAddress = "{yo ...

  9. ⭐volatile⭐ 用volatile关键字则会从内存中直接读取变量的值

  10. 其它——windows提示缺少VCRUNTIME140.dll错误

    文章目录 一 原因 二 解决方法一 三 解决方法二 缺少了Microsoft.Net.Framework的安装 一 原因 最新在系统安装一些软件发现提示 这是因为缺少了一下windows运行需要的库 ...