作者:启明星辰ADLab
公众号:区块链智能合约控制流识别的大规模实验研究
一、 背景介绍
启明星辰ADLab联合电子科技大学计算机学院(网络空间安全学院)陈厅副教授首次对以太坊区块链智能合约控制流的识别进行大规模研究,研究成果《A Large-Scale Empirical Study on Control Flow Identification of Smart Contracts》于2019年发表在中国计算机学会(CCF)推荐的B类学术会议International Symposium on Empirical Software Engineering and Measurement上。该研究分析了当前6个主流的智能合约静态分析工具,通过对以太坊区块链上已部署的全部合约(约500万)实施执行跟踪来评估他们的静态控制流识别能力。实验证明,一些典型的问题会导致上述流行工具都无法识别全部的控制流(如:不完备的代码模式)。同时,实验发现通过执行跟踪可以有效增强这些工具对控制流的识别。我们通过在OYENTE中引入执行跟踪,实现了把静态控制流分析误报率降低百分之三十。同时,该研究获得了最佳论文提名奖。
二、 研究方法
2.1 智能合约收集
在以太坊区块链中,每个智能合约都有唯一地址(下文中如无特殊说明,都默认为以太坊区块链上的智能合约)。在已知该地址的条件下,可以通过钱包的编程接口web3.eth.getCode()来获取该合约的字节码。通过这种方式收集智能合约存在两大问题:
1)无法获得所有智能合约的地址,Etherscan等开放平台也仅仅对外开放了部分合约的地址;
2)智能合约可动态删除,在不知道智能合约的区块编号时,该方法就无法获得已删除智能合约的字节码。
为了获得链上所有智能合约的字节码,我们对客户端进行了插桩扩展。具体来说,通过监控evm.Create()来获得智能合约的地址,通过监控evm.StateDB.SetCode()来获得智能合约的字节码。最后通过监控链上智能合约的历史部署活动,从而获得了从2015年7月30日(以太坊启动)到2018年2月10日期间部署的约500万智能合约的字节码。
2.2 主流智能合约分析工具
尽管有一些工具能识别智能合约的控制流,但它们大多不开源或者无法处理字节码形态的智能合约,而实际智能合约绝大部分都不开放源码。最大的etherscan平台也仅仅收录了很小的一部分智能合约的源码。我们的研究选择了如下六款主流面向字节码智能合约的分析工具:
工具名称 | 特性 | 异常合约数量 |
---|---|---|
OYENTE | 漏洞挖掘,符号执行,路径敏感 | 27,131 (0.5%) |
MAIAN | 漏洞挖掘,符号执行,路径敏感 | 115,286 (2.3%) |
Mythril | 漏洞挖掘,符号执行,路径敏感 | 0 |
evmdis | 反汇编器,路径不敏感 | 0 |
Miasm | 反汇编器,模式识别,路径不敏感 | 0 |
Porosity | 反汇编器,模式识别,路径不敏感 | 0 |
上述六款工具中,路径敏感的工具可能比路径不敏感的工具发现更多的控制转移路径,因为它们不会检查在实际条件下的路径可达性。其中OYENTE和MAIAN在处理某些合约时会触发异常,我们分析发现有三类原因:恶意无效字节码、不支持的操作和求解器异常。为了深入比较,我们修复了这三类导致异常的软件缺陷。
2.3 智能合约控制流分析
以太坊区块链智能合约包含一系列虚拟机(EVM)操作,目前支持130+的EVM操作,其中8种操作可以导致控制流转移,具体来说:
1) 2种合约内跳转操作,EVM指令为JUMP/JUMPI,导致在同一个合约内的控制转移;
2) 6种合约间跳转操作,EVM指令为CREATE/CALL/CALLCODE/DELEGATECALL/ STATICCALL/SELFDESTRUCT,导致控制转移到另外一个地址的智能合约内。
通过对约500万智能合约的分析,我们发现其中绝大部分都是合约内控制转移,因此本次研究集中分析合约内的控制流转移,JUMP和JUMPI指令的含义如下:
指令 | 类型 | 解释 |
---|---|---|
JUMP | 无条件跳转 | 栈顶元素为转移目标地址 |
JUMPI | 条件跳转 | 栈顶元素为转移目标地址,栈顶下一元素不为0则转移 |
同传统x86二进制逆向分析相比,智能合约存在一些显著的差异。
1)目标地址都存储在堆栈上,增加了识别难度;
2)合约类函数调用没有传统的call指令,统一编译为JUMP指令,增加了函数识别难度。
我们总结了如下的6种智能合约的控制转移模式:
显然,模式a可以快速静态识别,模式b必须要模拟堆栈操作,模式c则必须模拟运算,模式d则必须模拟pc,模式e则必须模拟内存读写,模式f则更加复杂。为了统一分析当前流行工具的智能合约控制流识别分析能力,我们定义控制转移记录为
1)每个工具各自发现的控制转移记录
2)上述工具输出控制转移记录都相同的合约,
3)上述工具都发现的控制转移记录
三、 研究结果
我们采用上述工具对全部智能合约进行实验,对每个工具发现的控制转移记录数量进行了统计,如下图所示。其中,MAIAN工具发现的数量最少。通过分析MAIAN的源码发现根源是其一旦发现漏洞就会停止,导致很多路径未被分析。进一步分析该工具发现,是因为其只针对三种类型智能合约漏洞的挖掘。OYENTE比Mythril能发现更多漏洞,分析工具源码发现它们都是基于符号执行,但是前者支持更深层次的代码路径。Mythril/ evmdis发现的路径数量都比Porosity少,因为前两者都是递归式的反汇编处理。发现1:由于采用的技术或者配置不同,所以当前主流工具识别的智能合约控制流数量差别较大;线性反汇编比递归反汇编能识别更多控制流,因为递归分析在识别到非法转移目标时就停止工作。
针对基于符号执行的三个分析工具(OYENTE/ MAIAN/ Mythril),我们采用这些工具统计每个智能合约的JUMP数量和发现的控制转移记录平均数量如下图所示。实验发现,JUMP数量200以下时,控制转移记录数量跟JUMP数量保持线性关系。JUMP数量能够表示智能合约的复杂度,显然随着合约复杂度上升,合约的控制转移数量也就更多。但是这个线性关系在JUMP数量超过200时就不再保持,进一步分析发现这是因为这些工具都设置了不同的符号执行结束条件。我们对另外三个反汇编器(evmdis/ Miasm/ Porosity)进行实验,同样发现了相似的结论,在JUMP数量300以下同样保持良好的线性关系。进一步分析发现,这三个工具在分析结束条件上同样也存在较大差异。发现2:不同分析工具在分析复杂智能合约控制流时能力差异较大,典型原因有路径爆炸、提前结束条件和不完备的代码模式。
为了分析智能合约的复杂性变化,我们跟踪了从以太坊区块链启动以来每周新建合约的字节平均数量和JUMP操作平均数量如下图所示,发现智能合约的体积和复杂度都在持续增长。这显然对智能合约分析工具的能力提出了更高的要求。
为了研究上述工具的控制流分析差异,我们统计了在不同工具处理结果中都相同的合约的占比如下表所示。无论是符号执行工具还是反汇编工具,控制流分析输出相同的合约都占比很小。进一步针对工具的相互比对分析如下图所示,发现只有evmdis跟Porosity的分析能力比较接近,但也仅针对46%的智能合约才具备相似的控制流分析结果。发现3:上述的6款主流分析工具仅针对1.7%的智能合约才能识别出相同的控制流转移。
类别 | 输出相同的合约占总合约比率 | 详情 |
---|---|---|
基于符号执行的工具 | 7% | OYENTE/ MAIAN/ Mythril |
基于反汇编的工具 | 5% | evmdis/ Miasm/ Porosity |
全部工具 | 1.7% | 上述全部 |
针对上述路径敏感性类型的三种合约分析工具(OYENTE/ MAIAN/ Mythril),我们通过实验收集了控制流输出相同的全部合约,然后对它们进行了复杂度分析,结果如下图所示。显然,随着合约复杂度增加,三种工具分析结果相同的合约数量在减少。
针对路径不敏感的三种工具(evmdis/ Miasm/ Porosity),我们分别计算每个合约中它们发现的控制转移记录并集和合集,同时计算每个合约的复杂度,然后得到如下图的分析。显然,针对任何一个合约,如果其复杂度越高,这三种工具发现的相同控制转移记录就越少。发现4:合约的复杂度越高,不同分析工具得到一致结果越困难。
为了提升合约分析工具的控制流分析能力,我们提出了基于执行trace的控制流识别增强。智能合约执行trace的一种获取方式是通过标准编程接口 web3.debug.traceTransaction(),但该接口需要提供合约执行的交易哈希值。同时,该接口的运行效率很低,通过分析源码发现其在获取trace之前需要做:运行环境初始化、构建正确状态和重放交易记录,同时web3编程接口是RPC调用过程。因此,效率难以提升。最终,我们选择了对以太坊区块链终端进行插桩,因为该终端能执行全部的历史合约操作。具体来说,我们对JUMP和JUMPI操作进行了插桩,最终得到了6300万的执行trace。同时,我们也对这些trace进行了切割,因为合约的执行trace记录会包括合约内的控制转移和合约间的控制转移。然后我们对上述工具识别的控制流和执行trace获得的控制流进行了分析,发现执行trace可以提升上述工具的控制流识别能力,尤其是对于MAIAN和Miasm工具,提升能力皆超过百分之八十。即使是最优秀的控制流发现工具Porosity,提升能力也有百分之十。发现5:执行trace可以有效提升上述工具的智能合约控制流识别能力,能发现这些工具不能发现的控制转移。
为了验证基于执行trace的有效性,我们选择了OYENTE工具进行增强实现和验证,增强的具体算法如下图所示。我们对OYENTE的源码进行修改以嵌入该增强算法,然后对OYENTE能识别的四种合约漏洞进行了实验,结论见下表。针对交易顺序依赖、时间依赖和重入类型的漏洞,增强OYENTE能检测更多的漏洞。针对未处理异常漏洞,增强OYENTE不能提升检测能力。对OYENTE源码分析发现,这是因为这类漏洞是直接用合约字节码扫描来检测的,与控制流分析无关。
OYENTE | OYENTE(增强) | |
---|---|---|
Transaction-Ordering Dependence | 460,626 | 521,330 |
Timestamp Dependence | 154,871 | 183,668 |
Mishandled Exceptions | 115,731 | 115,731 |
Reentrancy Vulnerability | 81,931 | 57,392 |
四、 研究总结
此次针对以太坊区块链智能合约控制流识别的大规模深度研究,我们取得了多项新的发现。通过插桩以太坊客户端,收集了全部的智能合约并还原了全部的执行trace。实验证明,执行trace可以提升当前主流的智能合约分析工具的控制流识别能力,该发现将有助于以太坊用户、开发者和研究分析人员开展更深入的智能合约研究。
本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1072/