您好,欢迎您来到林间号!
官网首页 小额贷款 购车贷款 购房贷款 抵押贷款 贷款平台 贷款知识 手机租机

林间号 > 区块链 > lme合约,合约if

lme合约,合约if

区块链 岑岑 本站原创

在智能合约领域,& # 8221;以太坊虚拟机EVM & # 8221;它的算法和数据结构是首要原则。

基于为什么要对合同进行分类,并结合每个场景可能面临的恶意攻击,本文最终给出了一套实现相对安全的合同分类分析算法。

虽然技术含量高,但也可以作为杂七杂八的读物,看看集权制之间博弈的黑暗森林。

1.为什么要对合同进行分类?因为太重要了,可谓是Dapp的基石,交易所,钱包,区块链浏览器,数据分析平台等等!

交易是ERC20传输,因为其行为符合ERC20标准,并且至少:

交易状态为成功。

要解决的是符合ERC20标准的合同。

调用转移函数,其特征在于该事务的CallData的前四位是0xa9059cbb。

在执行之后,在To地址发出传送事件。

如果分类错误,交易行为就会被误判。

以交易行为为基石,地址是否可以准确分类,对其CallData的判断会有完全不同的结论。对于Dapp来说,链与链之间的信息沟通高度依赖于对交易事件的监控,同样的事件代码只有在标准合约中发出才能可信。

如果分类错误,交易就会进入黑洞。

如果用户对合约进行代币转账,如果合约没有预设代币转账的功能方法,资金就会像烧钱一样被锁定失控。

而且现在大量项目开始增加内置钱包支持,所以为用户管理钱包是必然的。需要时刻从链条上实时梳理最新部署的合同,是否能达到资产标准。

2.分类有什么风险?链条是一个没有身份,没有法治的地方。你不能停止一个正常的交易,即使它是恶意的。

他可以是一只伪装成奶奶的狼,做大多数符合你预期的奶奶的行为,但目的是抢房子。

标准的陈述,但可能不符合实质内容

常见的分类方法是直接用EIP-165标准读取地址是否支持ERC20等。当然,这是一种高效的方法,但毕竟合同是被对方控制的,所以伪造声明终究是有可能的。

165标准查询只是链条上有限的操作码中,防止资金转入成本最低的黑洞的方法。

这也是为什么我们之前分析NFT的时候,特别提到了会有一种SafeTransferFrom标准,其中Safe指的是用165标准来判断对方声称自己拥有NFT的传送能力。

只有从契约字节码出发,在源代码层面做静态分析,才能更准确的从契约的预期行为出发。

3.合同分类方案设计接下来,我们将对整体方案进行系统分析,关注“准确性”和“效率”这两个核心指标。

要知道,就算方向对了,大洋彼岸的路也不清楚。字节码分析的第一站是获取代码。

3.1.如何获取代码?从缠绕后的角度来看,有getCode这种RPC方法,可以从链中指定的地址获取字节码。读取它的速度非常快,因为codeHash位于EVM帐户结构的顶部。

但这种方法相当于单独获取一个地址,想进一步提高准确性和效率?

如果是部署契约的事务,如何在刚执行完甚至还在内存池的时候获取部署的代码?

如果事务是契约工厂模型,那么在事务的Calldata中有源代码吗?

最后,我的方法是分类,进行一个类似筛子的模型。

对于非合同交易,所涉及的地址由getCode直接获取进行分类。

对于最新内存池的事务,过滤掉地址为空的事务,其CallData为带构造函数的源代码。

对于契约工厂模式下的事务,由于可能是该契约部署的契约回收其他契约来执行部署,所以递归分析该事务的子事务,并记录每个类型为CREATE或CREATE2的调用。

我做demo实现的时候发现现在rpc版本比较高,因为整个过程最难的就是执行3的时候如何递归找到指定类型的调用,最低级的方式就是通过opcode还原上下文。我吃了一惊!

好在目前的geth版本中有debug_traceTransaction方法,可以帮助解决通过opcode梳理每次调用的上下文信息,整理核心字段的问题。

最后可以得到各种部署模式(直接部署、工厂模式单次部署、工厂模式批量部署)的原始字节码。

3.2.如何从代码分类?最简单但不安全的方法是直接匹配代码字符串。以ERC20为例,符合标准的功能有

在函数名之后,是函数的函数签名。正如在分析中提到的,事务依赖于匹配调用数据的前4位数字来找到目标函数。阅读更多信息:

因此,这六个函数的签名必须存储在契约字节码中。

当然这个方法很快,六个都能找到,但是不安全的因素是如果我用solidity契约单独设计一个变量,存储值是0x18160ddd,那么他会认为我有这个功能。

3.3、准确性提升1-反编译更准确的方法是反编译操作码!反编译是将得到的字节码转换成操作码的过程,更高级的反编译是将其转换成伪代码,更有利于人们的阅读。这次不需要了。反编译的方法列在文末的附录里。

Solidity(高级语言)->;字节码->;操作码

我们可以清晰的发现一个特点,函数签名会被PUSH4的操作码执行,那么更进一步的方法就是从全文中提取PUSH4之后的内容,并与函数标准进行匹配。

我还做了一个简单的性能实验。不得不说Go语言的效率非常强大,1 w反编译只需要220ms。

下面的内容会比较难。

3.4、提高准确率2-查找上面的代码块准确率有所提高,但还不够,因为是全文搜索PUSH4,因为我们还可以构建一个变量,这个变量是byte4的类型,它也会触发PUSH4的指令。

我在苦恼的时候,就想到一些开源项目的实现。ETL是一个读取链中数据进行分析的工具,其中ERC20和721的转移会在单独的表中进行分析,所以我必须具备合同分类的能力。

经过分析可以发现,它是基于代码块的分类,只处理第一个basic_blocks[0]中的push4指令。

那么问题来了,如何准确判断码块?

代码块的概念来源于两个连续的操作码,REVERT+JUMPDEST,这里必须有两个连续的操作码,因为如果整个函数选择器的操作码区间内函数太多,就会出现翻页的逻辑,也会出现指令Jumpstest。

3.5.准确性的提升3-查找函数选择器函数选择器用于读取本次事务的Calldata的前4个字节,并与代码中预置的契约函数签名进行匹配,以辅助指令跳转到函数方法指定的内存位置。

让我们尝试一个最小模拟执行

这部分是两个函数的选择器store(uint 256)和retrieve(),签名可以计算为2e64cc1,6057361d。

反编译后会得到下面的操作码字符串,可以说分为两部分。

第一部分:

在编译器中,只有函数选择器部分会获取契约中callData的内容,也就是说获取其CallData的函数调用签名,如下图所示。

我们可以通过模拟EVM的内存池变化来看效果。

第二部分:

判断它是否与选择器的值匹配的过程。

1.将retrieve()的4字节函数签名(0x2e64cec1)传递到堆栈中。

2.EQ操作码从堆栈区弹出两个变量,分别是0x2e64cec1和0x6057361d,检查是否相等。

3.PUSH2将2个字节的数据(这里是0x003b,十进制59)发送到堆栈中。堆栈区有一个程序计数器,它指定字节码中下一个执行命令的位置。这里我们设置59,因为这是retrieve()字节码的起始位置。

4.JUMPI代表& # 8221;如果& # 8230;,然后跳转到& # 8230;”它从堆栈中弹出两个值作为输入。如果条件为真,程序计数器将更新为59。

这就是EVM如何根据契约中的函数调用来确定它需要执行的函数的字节码的位置。

实际上,这只是契约中每个函数及其跳转位置的一组简单的“if语句”。

4.该计划的总体概述如下

每个契约地址都可以通过rpcgetcode或者debug_traceTransaction获得部署的字节码,并使用GO中的VM和A库获得反编译后的操作码。

在EVM的运作原则中,契约具有以下特征。

REVERT+JUMPDEST是两个连续操作码,用于区分代码块。

契约必须有函数选择器的功能,而且这个功能也必须在第一个代码块中。

在函数选择器中,PUSH4用作其所有函数方法的操作码。

在选择器包含的操作码中,会有一个连续的PUSH1 00CALLDATALOADPUSH1 e0SHRDUP1,核心函数是加载callDate数据并进行置换运算,其他文法不会从契约函数中生成。

3.eip中定义了相应的函数签名,明确说明是必选的,也是可选的。

4.1.唯一性证明到这里,可以说已经基本实现了高效率、高精度的契约分析方法。当然,既然严谨了这么久,我们不妨再严谨一点。在上述方案中,我们基于REVER+JUMPDEST区分代码块,并结合不可避免的调用数据加载和位移进行唯一性判断。是否存在,我是否也可以用solidity契约实现类似的操作码序列?

我做了一个对比实验。虽然从solidity文法中获取CallData有一些方法,但是编译后操作码的实现方法是不一样的。

本网站声明:网站内容来源于网络。如有侵权,请联系我们,我们会及时处理。

温馨提示:注:内容来源均采集于互联网,不要轻信任何,后果自负,本站不承担任何责任。若本站收录的信息无意侵犯了贵司版权,请给我们来信,我们会及时处理和回复。

原文地址"lme合约,合约if":http://www.ljycsb.cn/qukuailian/215023.html

微信扫描二维码投放广告
▲长按图片识别二维码