相关信息

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. 19.Tomcat多实例部署及负载均衡、动静分离

    Tomcat多实例部署及负载均衡.动静分离 目录 Tomcat多实例部署及负载均衡.动静分离 Tomcat多实例部署 安装jdk 设置jdk环境变量 安装tomcat 配置 tomcat 环境变量 修 ...

  2. Redis基础与性能调优

    Redis是一个开源的,基于内存的结构化数据存储媒介,可以作为数据库.缓存服务或消息服务使用. Redis支持多种数据结构,包括字符串.哈希表.链表.集合.有序集合.位图.Hyperloglogs等. ...

  3. key可重复的Map

    在正常的map操作中,key是不能重复的,如果希望key的内容可以重复,可以用IdentityHashMap 举个栗子 输出结果: public static void main(String[] a ...

  4. ppt/word公式LaTeX环境配置

    PPT使用Latex说明 一.下载IguanaTex_v1_57 http://www.jonathanleroux.org/software/iguanatex/download.html Inst ...

  5. Burnside 引理与 Pólya 定理

    群 群的定义 在数学中,群是由一种集合以及一个二元运算所组成的,符合"群公理"的代数结构. 一个群是一个集合 \(G\) 加上对 \(G\) 的二元运算.二元运算用 \(\cdot ...

  6. C语言中限定符的作用

    C语言中常用的一般包括const.static.extern.register和volatile这几个.这些是C语言标准中规定的关键词,所有的编译器都必须支持这些关键词,它们的作用如下: 1.cons ...

  7. CF989C A Mist of Florescence 题解

    因为 \(1 \leq a,b,c,d \leq 100\) 所以每一个颜色都有属于自己的联通块. 考虑 \(a = b=c=d=1\) 的情况. AAAAAAAAAAAAAAAAAAAAAAAAAA ...

  8. 史上最全学习率调整策略lr_scheduler

    学习率是深度学习训练中至关重要的参数,很多时候一个合适的学习率才能发挥出模型的较大潜力.所以学习率调整策略同样至关重要,这篇博客介绍一下Pytorch中常见的学习率调整方法. import torch ...

  9. 挑战30天写操作系统-day4-C语言与画面显示的练习

    目录 获取源码关注公众号<猿小龙> 1.用C语言实现内存写入(harib01a) C语言中如果使用了write_mem8函数,就会跳转到_write_mem8,此时参数指定的数字就存放在内 ...

  10. linux 运行.sh出现 Permission denied

    执行.sh脚本时提示如下错误: [root@Dolen2021 redis]# ./startRedis.sh -bash: ./startRedis.sh: Permission denied [r ...