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

360核心安全  2019-01-11  新手入门/区块链知识栏目  

  

作者:高峰 黄绍莽

摘要

  目前,以太坊智能合约的安全事件频发,从The DAO事件到最近的Fomo3D奖池被盗,每次安全问题的破坏力都是巨大的,如何正确防范智能合约的安全漏洞成了当务之急。本文主要讲解了如何通过对智能合约的静态分析进而发现智能合约中的漏洞。由于智能合约部署之后的更新和升级非常困难,所以在智能合约部署之前对其进行静态分析,检测并发现智能合约中的漏洞,可以最大限度的保证智能合约部署之后的安全。

  本文包含以下五个章节:

  1. 智能合约的编译

  2. 智能合约汇编指令分析

  3. 从反编译代码构建控制流图

  4. 从控制流图开始约束求解

  5. 常见的智能合约漏洞以及检测方法

智能合约的编译

本章节是智能合约静态分析的第一章,主要讲解了智能合约的编译,包括编译环境的搭建、solidity编译器的使用。

  1.1编译环境的搭建

我们以Ubuntu系统为例,介绍编译环境的搭建过程。首先介绍的是go-ETHereum的安装。
1.1.1 安装go-ethereum

通过apt-get安装是比较简便的安装方法,只需要在安装之前添加go-ethereum的ppa仓库。

完整的安装命令如下:

  sudo apt-get install software-properties-common
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereum

安装成功后,我们在命令行下就可以使用geth,evm,swarm,bootnode,rlpdump,abigen等命令。

当然,我们也可以通过编译源码的方式进行安装,但是这种安装方式需要提前安装golang的环境,步骤比较繁琐。

1.1.2 安装solidity编译器

目前以太坊上的智能合约绝大多数是通过solidity语言编写的,所以本章只介绍solidity编译器的安装。solidity的安装和go-ethereum类似,也是通过apt-get安装,在安装前先添加相应的ppa仓库。

完整的安装命令如下:

  sudo add-apt-repositoryppa:ethereum/ethereum

  sudoapt-get update
sudoapt-get install solc

执行以上命令后,最新的稳定版的solidity编译器就安装完成了。之后我们在命令行就可以使用solc命令了。

  1.2solidity编译器的使用


1.2.1 基本用法

我们以一个简单的以太坊智能合约为例进行编译,

智能合约代码(保存在test.sol文件)如下:

  pragma solidity ^0.4.25;

cONTract Test {
    
}

执行solc命令:solc --bin  test.sol

输出结果如下:

  ======= test.sol:Test ======= 

  Binary:  6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00a165627a7a72305820f633e21e144cAE24615a160fcb484c1f9495df86d7d21e9be0df2cf3b4c1f9eb0029

solc命令的--bin选项,用来把智能合约编译后的二进制以十六进制形式表示。和--bin选项类似的是--bin-runtime,这个选项也会输出十六进制表示,但是会省略智能合约编译后的部署代码。接下来我们执行solc命令:

solc --bin-runtime  test.sol

输出结果如下:

  ======= test.sol:Test ======= 

  Binary ofthe runtime part: 6080604052600080fd00a165627a7a72305820f633e21e144cae24615a160fcb484c1f9495df86d7d21e9be0df2cf3b4c1f9eb0029

对比两次输出结果不难发现,使用--bin-runtime选项后,输出结果的开始部分少了6080604052348015600f57600080fd5b50603580601d6000396000f300,为何会少了这部分代码呢,看完接下来的智能合约编译后的字节码结构就明白了。

1.2.2 智能合约字节码结构

智能合约编译后的字节码,分为三个部分:部署代码、runtime代码、auxdata。

1.部署代码:以上面的输出结果为例,其中6080604052348015600f57600080fd5b50603580601d6000396000f300 为部署代码。以太坊虚拟机在创建合约的时候,会先创建合约账户,然后运行部署代码。运行完成后它会将runtime代码 auxdata 存储到区块链上。之后再把二者的存储地址跟合约账户关联起来(也就是把合约账户中的code hash字段用该地址赋值),这样就完成了合约的部署。

2.runtime代码:该例中6080604052600080fd00 是runtime代码。

3.auxdata:每个合约最后面的43字节就是auxdata,它会紧跟在runtime代码后面被存储起来。

solc命令的--bin-runtime选项,输出了runtime代码和auxdata,省略了部署代码,所以输出结果的开始部分少了6080604052348015600f57600080fd5b50603580601d6000396000f300。


1.2.3 生成汇编代码

solc命令的--asm选项用来生成汇编代码,接下来我们还是以最初的智能合约为例执行solc命令,查看生成的汇编代码。

执行命令:solc--bin --asm test.sol

输出结果如下:

======= test.sol:Test =======
EVM assembly:
... */ "test.sol":28:52  contract Test {
  mSTOre(0x40, 0x80)
  callvalue
    /* "--CODEGEN--":8:17   */
  dup1
    /* "--CODEGEN--":5:7   */
  iszero
  tag_1
  jumpi
    /* "--CODEGEN--":30:31   */
  0x0
    /* "--CODEGEN--":27:28   */
  dup1
    /* "--CODEGEN--":20:32   */
  revert
    /* "--CODEGEN--":5:7   */
tag_1:
... */ "test.sol":28:52  contract Test {
  pop
  dataSize(sub_0)
  dup1
  dataOffset(sub_0)
  0x0
  codecopy
  0x0
  return
stop

sub_0: assembly {
... */  /* "test.sol":28:52  contract Test {
      mstore(0x40, 0x80)
      0x0
      dup1
      revert
   
auxdata: 

0xa165627a7a72305820f633e21e144cae24615a160fcb484c1f9495df86d7d21e9be0df2cf3b4c1f9eb0029

}

由1.2.2小节可知,智能合约编译后的字节码分为部署代码、runtime代码和auxdata三部分。同样,智能合约编译生成的汇编指令也分为三部分:EVM assembly标签下的汇编指令对应的是部署代码;sub_0标签下的汇编指令对应的是runtime代码;sub_0标签下的auxdata和字节码中的auxdata完全相同。由于目前智能合约文件并没有实质的内容,所以sub_0标签下没有任何有意义的汇编指令。


1.2.4 生成ABI

solc命令的--abi选项可以用来生成智能合约的ABI,同样还是最开始的智能合约代码进行演示。

执行solc命令:solc --abi test.sol

输出结果如下:

======= test.sol:Test =======
Contract JSON ABI 
[]

可以看到生成的结果中ABI数组为空,因为我们的智能合约里并没有内容(没有变量声明,没有函数)。

  1.3总结


本章节主要介绍了编译环境的搭建、智能合约的字节码的结构组成以及solc命令的常见用法(生成字节码,生成汇编代码,生成abi)。在下一章中,我们将对生成的汇编代码做深入的分析。

(未完)

点击下方[阅读原文],查看更多爱我请给我好看!
版权信息
作者:IceSword Lab
来源:360核心安全

关于我们

联系我们

作者进驻

手机版

Copyright © 2013 比特巴 www.btb8.com
始建于2013年,提供比特币 区块链及数字货币新闻、技术教程、测评、项目周报、人物等资讯
本页面提供的是新手入门教程资讯,提供入门级的比特币知识、区块链知识以及各类数字货币知识,是数字货币爱好者入门、精通的好导师。