欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

区块链安全——以太坊智能合约静态分析

来源:本站整理 作者:佚名 时间:2019-01-10 TAG: 我要投稿
LT指令用来比较0x04和变量Id_size的大小,如果0x04小于变量Id_size则值为0,否则值为1。使用z3转换成表达式则为:If(ULE(4, Id_size), 0, 1)
JUMPI是条件跳转指令,是否跳转到0x3e地址处取决于上一步中LT指令的结果,即表达式If(ULE(4, Id_size), 0, 1)的结果。如果结果不为0则跳转,否则不跳转,使用z3转换成表达式则为:If(ULE(4, Id_size), 0, 1) != 0
至此,基本块1中的指令都已经使用z3转换成数学表达式。
4.2.2 执行数学表达式
执行上一节中生成的数学表达式的伪代码如下所示:
from z3 import *
Id_size = BitVec("Id_size",256)
exp = If(ULE(4, Id_size), 0, 1) != 0
solver = Solver()
solver.add(exp)
if solver.check() == sat:
    print "jump to BasicBlock3"
else:
    print "error "
在上面的代码中调用了solver的check()方法来判断此表达式是否有解,如果返回值等于sat则表示表达式有解,也就是说LT指令的结果不为0,那么接下来就可以跳转到基本块3。
观察3.4节中的控制流图我们得知,基本块1之后有两条分支,如果满足判断条件则跳转到基本块3,不满足则跳转到基本块2。但在上面的代码中,当check()方法的返回值不等于sat时,我们并没有跳转到基本块2,而是直接输出错误,这是因为当条件表达式无解时,继续向下执行没有任何意义。那么如何才能执行到基本块2呢,答案是对条件表达式取反,然后再判断取反后的表达式是否有解,如果有解则跳转到基本块2执行。伪代码如下所示:
Id_size = BitVec("Id_size",256)
exp = If(ULE(4, Id_size), 0, 1) != 0
negated_exp = Not(If(ULE(4, Id_size), 0, 1) != 0)
solver = Solver()
solver.push()
solver.add(exp)
if solver.check() == sat:
    print "jump to BasicBlock3"
else:
    print "error"
solver.pop()
solver.push()
solver.add(negated_exp)
if solver.check() == sat:
    print "falls to BasicBlock2"
else:
    print "error"
在上面代码中,我们使用z3中的Not函数,对之前的条件表达式进行取反,之后调用check()方法判断取反后的条件表达式是否有解,如果有解就执行基本块2。
4.3 总结
本章首先介绍了z3的基本用法,之后以基本块1为例,分析了如何使用z3把指令转换成表达式,同时也分析了如何对转换后的表达式进行约束求解。在下一章中我们将会介绍如何在约束求解的过程中加入对智能合约漏洞的分析,精彩不容错过。
 
第五章 常见的智能合约漏洞以及检测方法
在本章中,我们首先会介绍智能合约中常见的漏洞,之后会分析检测这些漏洞的方法。
5.1 智能合约中常见的漏洞
5.1.1 整数溢出漏洞
我们以8位无符号整数为例分析溢出产生的原因,如下图所示,最大的8位无符号整数是255,如果此时再加1就会变为0。

整数溢出
Solidity语言支持从uint8到uint256,uint256的取值范围是0到2256-1。如果某个uint256变量的值为2256-1,那么这个变量再加1就会发生溢出,同时该变量的值变为0。
pragma solidity ^0.4.20;
contract Test {
    function overflow() public pure returns (uint256 _overflow) {
        uint256 max = 2**256-1;
        return max + 1;
    }
}
上面的合约代码中,变量max的值为2^256-1,是uint256所能表示的最大整数,如果再加1就会产生溢出,max的值变为0。
5.1.2 重入漏洞
当智能合约向另一个智能合约转账时,后者的fallback函数会被调用。如果fallback函数中存在恶意代码,那么恶意代码会被执行,这就是重入漏洞产生的前提。那么重入漏洞在什么情况下会发生呢,下面我们以一个存在重入漏洞的智能合约为例进行分析。
pragma solidity ^0.4.20;
contract Bank {
    address owner;
    mapping (address => uint256) balances;
   
    constructor() public payable{
        owner = msg.sender;
    }
    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }
    function withdraw(address receiver, uint256 amount) public{
        require(balances[msg.sender] > amount);
        require(address(this).balance > amount);
        // 使用 call.value()()进行ether转币时,没有Gas限制
        receiver.call.value(amount)();
        balances[msg.sender] -= amount;
    }
    function balanceOf(address addr) public view returns (uint256) {
        return balances[addr];
    }
}
contract Attack {
    address owner;
    address victim;
    constructor() public payable {
        owner = msg.sender;

上一页  [1] [2] [3] [4] [5] [6] [7] [8] [9]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载