相关信息

KaoyaSwap 是 BSC 链上的一个自动做市商 AMM。然后,现在他们的官网 https://www.kaoyaswap.com/ 已经打不开了(如果我打开方式没错的话)。所以就直接进行攻击事件的分析吧。

攻击交易:https://bscscan.com/tx/0xc8db3b620656408a5004844703aa92d895eb3527da057153f0b09f0b58208d74

攻击者在进行攻击之前,自己构建了两个代币协助完成攻击,下面将他们分别称为 TA 和 TB 。

TA address:0x74eF69Defe8bae1Fe660fB93265FC1bc79c9bDa8

TB address:0xD84379C4eeA25d05574f9F0B99E3Bf73500Ca4B4

交易流程

因为攻击是发生在 AMM 上的,所以我们可以根据代币的流向先大概分析一下攻击者在这笔交易中都做了些什么,看看能不能看出有什么奇怪的地方。下面绿色框图是 Tokens Transferred 的内容,红色框图的是 Internal Txns 的内容。

  1. 首先闪电贷 1800 BNB
  2. 调用 swapExactTokensForTokens 函数,用 672 BNB 换出 125023 KY
  3. 调用 swapExactTokensForTokens 函数,用 100 BNB 换出 6666 BUSD
  4. 调用 addLiquidity 函数,添加 1026 BNB 和 50 TA,获得 226 KALP 流动性代币

  1. 调用 addLiquidity 函数,添加 1 BNB 和 1 TB,获得 0.9 KALP 流动性代币
  2. 调用 addLiquidity 函数,添加 1 TA 和 1 TB,获得 0.9 KALP 流动性代币

  1. 调用 swapExactTokensForETHSupportingFeeOnTransferTokens 函数,其中 path 参数为 [TA, WBNB, TB, TA, WBNB] 的地址。这个函数还涉及到 BNB 的转账,但是函数 Output 中没有体现。(剧透一下,转出了 1019 BNB 给攻击地址。具体情况后面的代码分析会解释)。
Input:
"amountIn": "8000000000000000000000",
"amountOutMin": "1",
"path": [
"0x74ef69defe8bae1fe660fb93265fc1bc79c9bda8",
"0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c",
"0xd84379c4eea25d05574f9f0b99e3bf73500ca4b4",
"0x74ef69defe8bae1fe660fb93265fc1bc79c9bda8",
"0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c"
],
"to": "0xa722ca7bf032de8f7a675da75dfec661bc89ace9",
"deadline": "1661293930“ Output:
0x

  1. 调用 removeLiquidityETHSupportingFeeOnTransferTokens 函数,销毁 226 KALP,获得 8050 TA,Output "amountETH": "6392515470500594443"
  2. 调用 removeLiquidityETHSupportingFeeOnTransferTokens 函数,销毁 0.9 KALP,获得 0.0009 TB,Output "amountETH": "1020797089459256392608"

  1. 调用 removeLiquidity 函数,传入 0.9 KALP,获取 0.5 TA 和 1.9 TB
  2. 调用 swapExactTokensForTokens 函数,传入 83918 KY,获得 25170 BUSD

  1. 在 pancakeswap 中把 17740 KY 换成 5457 BUSD,把 23364 KY 换成 24 WBNB。
  2. 归还 1800 WBNB 闪电贷。
  3. 然后把 37294 BUSD 和 271 WBNB 转移到 0xd87f 地址中

总的来看,攻击者主要投入了 1026 BNB 到 WBNB 和 TA 的池子中,然后通过 swapExactTokensForETHSupportingFeeOnTransferTokens 函数以 8000 TA 获得 1019 BNB,并且通过 removeLiquidityETHSupportingFeeOnTransferTokens 函数移除 WBNB 和 TB 池子的流动性获得 1020 BNB。

投入 1026 BNB,获得 (1019 + 1020) BNB,其中必有蹊跷。

代码分析

首先来分析一下 swapExactTokensForETHSupportingFeeOnTransferTokens 函数,先调用 _transferIn 转入 TA,然后调用 _swapSupportingFeeOnTransferTokens 函数按照 path 进行一系列 swap 操作,计算 _pools[TA,WBNB][WBNB] 的变化,根据差值给 to 地址发送相等数量的 BNB。

需要关注的函数:_transferIn_swapSupportingFeeOnTransferTokens。这些函都涉及到了一个关键的变量 _pools ,它是这次攻击的关键点。

先来看 _transferIn 函数,它的作用是把 path 中的第一个代币转入合约中,并修改对应的 _pools 值。

_swapSupportingFeeOnTransferTokens 函数根据 path 所提供的代币地址进行 swap,并将对应的 _pools 变量进行修改。

其中 _transferOut 函数的作用就是向 to 地址发送 amount 数量的 token。

swapExactTokensForETHSupportingFeeOnTransferTokens 函数中 path = [TA, WBNB, TB, TA, WBNB] 时所发生的情况是(下面简称 [A, W, B, A, W]):

首先在 _transferrIn 函数中:

_pool[AW][A] + amountIn

然后在 _swapSupportingFeeOnTransferTokens 函数中(注意 _pool[AW][W] 做了两次减法操作):

i = 0 , _pool[AW][W] – amountOutput1, _pool[WB][W] + amountOutput1
i = 1 , _pool[WB][B] – amountOutput2, _pool[BA][B] + amountOutput2
i = 2 , _pool[BA][A] – amountOutput3, _pool[AW][A] + amountOutput3
i = 3 , _pool[AW][W] – amountOutput4

转账的金额只通过最后一对 pair_pool 数值 _pool[AW][W] 的减少量(从 AW 这个池子里换出了多少 W)来确定。正确的方法应该是只关注最后一步中 _pool[AW][W] 的减少量,而不是整个 swap 过程中 _pool[AW][W] 的总(累计)减少量。如果采用总(累计)减少量计算,则当 path 中有重复的 pair ([A, W])不连续出现时,会多次计算 _pool[AW][W] 的减少量,最终导致 balanceBefore.sub(balanceAfter) 的值大于实际值。

我们看到第 1 次 TA 换 WBNB 的时候,换出来 1019.797089459257413406 WBNB,第 2 次 TA 换 WBNB 的时候,换出来 0.000395070241992122 WBNB,累加得到 1019.797484529499405528 WBNB,吻合之前提到的值。而正常情况下应该转出的 WBNB 因该为 0.000395070241992122 WBNB,同时将 [WBNB, TB] 池子中 TB 的币价大幅提高(转入了大量 WBNB)。

综上所属,利用了 _pools 变量在整个 swap 过程中累计减少量的漏洞,攻击者用一笔钱,在提高了 [WBNB, TB] 池子中 TB 的币价的同时, swap 出了超量的 WBNB。然后再移除 [WBNB, TB] 池子的流动性, 获取大量的 BNB。

【漏洞分析】KaoyaSwap 安全事件分析的更多相关文章

  1. CVE-2013-2551漏洞成因与利用分析(ISCC2014 PWN6)

    CVE-2013-2551漏洞成因与利用分析 1. 简介 VUPEN在Pwn2Own2013上利用此漏洞攻破了Win8+IE10,5月22日VUPEN在其博客上公布了漏洞的细节.它是一个ORG数组整数 ...

  2. CVE-2014-0322漏洞成因与利用分析

    CVE-2014-0322漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存,对指定内存处的值进行了加1.其特点在于攻击者结合flash实现了 ...

  3. CVE-2013-3897漏洞成因与利用分析

    CVE-2013-3897漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存.攻击者可以利用此类漏洞实现远程代码执行.UAF漏洞的根源源于对对 ...

  4. 漏洞分析:OpenSSH用户枚举漏洞(CVE-2018-15473)分析

    漏洞分析:OpenSSH用户枚举漏洞(CVE-2018-15473)分析 漏洞分析:OpenSSH用户枚举漏洞(CVE-2018-15473)分析 - FreeBuf互联网安全新媒体平台 https: ...

  5. 常用 Java 静态代码分析工具的分析与比较

    常用 Java 静态代码分析工具的分析与比较 简介: 本文首先介绍了静态代码分析的基 本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBu ...

  6. Memcached源代码分析 - Memcached源代码分析之消息回应(3)

    文章列表: <Memcached源代码分析 - Memcached源代码分析之基于Libevent的网络模型(1)> <Memcached源代码分析 - Memcached源代码分析 ...

  7. mysql 分析3使用分析sql 性能 show profiles ;

    show variables like '%profiling%';    查看状态  查看时间去哪了``` set  profiling=1;// 打开 show profiles;  查看执行过的 ...

  8. [转载] 常用 Java 静态代码分析工具的分析与比较

    转载自http://www.oschina.net/question/129540_23043 简介: 本文首先介绍了静态代码分析的基本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代 ...

  9. x264源代码简单分析:宏块分析(Analysis)部分-帧间宏块(Inter)

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

随机推荐

  1. 4.怎么理解相互独立事件?真的是没有任何关系的事件吗? 《zobol的考研概率论教程》

    1.从条件概率的定义来看独立事件的定义 2.从古典概率的定义来看独立事件的定义 3.P(A|B)和P(A)的关系是什么? 4.由P(AB)=P(A)P(B)推出"独立" 5.从韦恩 ...

  2. 【主流技术】ElasticSearch 在 Spring 项目中的实践

    前言 ElasticSearch简称es,是一个开源的高扩展的分布式全文检索引擎. 它可以近乎实时的存储.检索数据,其扩展性很好,ElasticSearch是企业级应用中较为常见的技术. 下面和大家分 ...

  3. LayUI+SSM实现一个简单的后台管理系统

    该后台管理系统是用于管理视频网站数据的,目前分5个菜单项,这篇博客主要讲述[影片管理]的具体功能和实现 后台代码结构和[影片管理]的界面如下图 该界面分为上下2部分,[搜索条件]和[影片列表],2部分 ...

  4. React技巧之检查元素是否可见

    原文链接:https://bobbyhadz.com/blog/react-check-if-element-in-viewport 作者:Borislav Hadzhiev 正文从这开始~ 总览 在 ...

  5. 从Hadder看蛋白质分子中的加氢算法

    技术背景 PDB(Protein Data Bank)是一种最常用于存储蛋白质结构的文件.而我们在研究蛋白质构象时,往往更多的是考虑其骨架,因此在很多pdb文件中直接去掉了氢原子.但是在我们构建蛋白质 ...

  6. leetcode题解#3:无重复字符的最长子串

    leetcode题解:无重复字符的最长子串 题目 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: s = "abcabcbb"输出: 3 解释 ...

  7. 编写可维护的webpack配置

    为什么要构建配置抽离成npm包 通用性 业务开发者无需挂住配置 统一团队构建脚本 可维护性 构建配置合理的拆分 README文档, chan 构建配置管理的可选方案 通过多个配置管理不同环境的构建, ...

  8. Spring和SpringMVC整合及关系

    SpringMVC扼要的讲,就是控制请求和处理.有必要将Spring和SpringMVC整合,否则仅配置SpringMVC并完成Spring的功能,会造成业务逻辑混乱. 简要总结:①原理:采用监听器, ...

  9. python虚拟环境(python+conda)

    python的不同虚拟环境就相当于在电脑上装了很多个python.下面写python创建虚拟环境.conda创建虚拟环境和在pycharm中配置一下. python -m venv (要创虚拟环境的路 ...

  10. 07 MySQL_SQL数据类型

    数据类型 整数类型: int(m) 对应java中的int bigint(m) 对应java中的long m代表显示长度,需要结合 zerofill使用 create table t_int(id i ...