搜索
NFT元宇宙Web3
近期热门

a16z:检测变形智能合约的工具

波动

智能合约安全系列文章之反编译篇- 安全客,安全资讯平台

以太坊安全性的前提就是假设智能合约是不可变的。智能合约的代码一旦部署在区块链上就无法更改。但是在实践中,一些智能合约可能会发生变化——即使它们已经部署。通过一些巧妙的技巧,你可以创建“变形”的变形智能合约,通过了解这种变形的原理,则可以反向检测出它们。

变形智能合约是可变的,这意味着开发人员可以更改其中的代码。web3 用户他们信任代码,希望代码可以保持绝对一致性的运行,所以这些可变形的智能合约给 web3 用户带来了严重的风险,特别是当不良行为者拥有了编写变形智能合约的能力时。想象一下,攻击者使用该技术“欺骗”那些在智能合约中质押代币的人,他们没有意识到这是变形的。这种破坏力是巨大的,可变形的只能合约使诈骗者有能力捕食他人,并且通常会破坏对去中心化系统的全部承诺的信任。

为了分析智能合约是否包含变形属性,我构建了一个简单的变形合约检测器(受 Jason Carver、0age和其朋友的原创作品启发和构建)。任何人都可以使用该工具来检查给定的合约是否显示出可能表明可能发生变形的危险信号。该方法并非万无一失:仅仅因为智能合约显示了一个标志,并不意味着它一定是变形的;仅仅因为它没有,并不意味着它是安全的。检查器仅提供一个快速的初步评估:根据可能的指标 ,合约可能会变形。

Web3 用户应该熟悉变形合约带来的威胁,以便能够留意并避免可能的攻击。钱包和区块链索引器可以通过在用户与可能包含变形属性的智能合约交互之前警告用户来提供帮助。该工具旨在帮助教育人们了解这种潜在威胁……并防御它。

检测变形智能合约

我构建的Metamorphic Contract Detector分析了六个属性,这些属性可能表明智能合约是否是变形的。

  1. 是否用于部署合约的已知变形代码?如果已知的变形字节码——通常用 Solidity 编写的以太坊智能合约在编译后变成的较低级别的虚拟机可读代码——出现在给定智能合约部署的交易中,这是一个主要的危险信号。在接下来的部分中,我们将讨论一个由 0age 开发的变形字节码示例。一个重要的警告:变形字节码可能存在无数种变体,检测所有变体是非常困难的。但是,通过扫描众所周知的实例,检测器消除了那些攻击者容易得到的仅仅复制和粘贴现有示例的结果。
  2. 智能合约代码可以自毁吗?要替换合约中的代码(创建变形合约的关键步骤),开发人员首先需要删除预先存在的代码。做到这一点的唯一方法是使用SELFDESTRUCT 操作码,该命令的作用与听起来完全一样——它会擦除给定合约地址的所有代码和存储。合约中存在自毁代码并不能证明它是变形的;但是,它提供了一个线索,即合约有可能是变形的,无论如何,了解你所依赖的合约是不是有自我毁灭代码是很重要的。
  3. 智能合约是否从其他地方调用代码?如果有问题的智能合约不能直接自毁,它仍然可以通过使用DELEGATECALL 操作码来擦除自己。此操作码允许智能合约动态加载和执行存在于另一个智能合约中的代码。即使智能合约不包含 SELFDESTRUCT 操作码,它也可以使用 DELEGATECALL 从其他地方加载自毁代码。虽然 DELEGATECALL 功能并不能直接指示智能合约是否是变形的,但这是一个可能的线索——一个潜在的安全问题——值得注意。请注意,该指标有可能引发许多误报。
  4. 是否有另一个合约部署了这个合约?变形合约只能由其他智能合约部署。这是因为变形合约由另一个操作码启用,只能由其他智能合约使用,称为 CREATE2。(我们将在后面的部分中讨论 CREATE2是如何工作的以及为什么它很重。)这个特征是可能变形的最不显眼的指标之一。这是一个必要但不充分的先决条件。扫描此特征可能会引发许多误报——但这是有价值的信息,因为它可能会引起怀疑并提供进一步审查合约的理由,特别是如果智能合约包含下面描述的操作码。
  5. 部署者合约是否包含 CREATE2 操作码?如上所述,通过 CREATE2 部署是变形的必要前提。如果部署者合约包含 CREATE2 操作码,这可能表明它使用 CREATE2 来部署相关合约。 如果部署者确实使用 CREATE2 来部署所述合约,虽然这并不意味着合约一定是变形的,但这确实意味着它可能是变形的,谨慎行事并进一步调查可能是明智的。再次提醒您注意误报:CREATE2有很多合法用途,包括支持“第 2 层”扩展解决方案,以及更容易创建可以改进 web3 的智能合约钱包用户加入和密钥恢复选项。
  6. 代码变了吗?这是最明显的说法,但只有在变形合约已经变形后才会出现。 如果智能合约的代码哈希(一个唯一的加密标识符)与合约最初部署时的不同,那么很可能代码已被删除、替换或更改。如果哈希不再匹配,则代码的某些内容发生了变化,并且合约可能会变形。该标志是变形最可靠的指标,但这一条检测对预测或先发制人没有任何帮助,只能检查变形是否已经发生。

除了为 Metamorphic Contract Detector 构建一个简单的命令行工具外,我还构建了一些示例智能合约来演示一个骗局的变形合约抵押场景,我将在下一节中对此进行描述。所有代码都可以在这个GitHub 存储库中找到。

恶意行为者如何使用变形合约窃取人们的资金

以下是有人可能如何使用变形智能合约作为骗局的一部分。

首先是设置阶段。攻击者使用两种工具在区块链上的特定地址部署智能合约:变形字节码和 CREATE2 操作码。(稍后我们将扩展这两个概念。)变形字节码然后按照其名称的含义进行“变形”。在这里,它变成了一个质押合约,用户可以在其中质押 ERC-20 代币。(同样,我们稍后会讨论这个变形技巧的细节。)

接下来是诱饵和开关。毫无戒心的用户将他们的代币押在这份合约中,被赚取收益或其他一些好处的可能性所吸引。然后,攻击者使用上一节中讨论的SELFDESTRUCT 操作码删除此智能合约地址上的所有质押代码和“状态”——区块链存储或内存。(应该注意的是,作为单独的 ERC-20 合约的一部分存在的代币会持续存在,不受自毁合约的影响。)

最后,Rug Pull 就是一个卷包跑路的大动作。攻击者重用在设置阶段使用的相同变形字节码来“重新部署”一个新合约。这个新合约部署到最近被自毁合约腾出的同一个地址。然而,这一次,字节码“变形”(同样,我们将在稍后解释)变成一个恶意合约,可以窃取合约地址上的所有代币。骗局完毕。

变形智能合约带来的风险现在显而易见。但是你可能仍然想知道,这种变形技巧实际上是如何工作的?要理解这一点,必须更深入字节码级别地探索。

CREATE2如何开启变形的可能性

CREATE2是 2019 年 2 月引入以太坊的操作码升级,它提供了一种部署智能合约的新方法。

CREATE2 让开发人员能够比以前更好地控制智能合约的部署。原始的 CREATE 操作码使开发人员难以控制要部署的智能合约的目标地址。使用 CREATE2,人们可以在将特定智能合约实际部署到区块链之前,提前控制和了解特定智能合约的地址。这种预知——加上一些巧妙的技巧——使人们能够创建变形的智能合约。

CREATE2如何预测未来?操作码的计算是确定性的:只要输入不改变,CREATE2 确定的地址就不会改变。(即使是最小的更改也会导致部署发生在其他地方。)

更详细地说,CREATE2 是一个将几个元素组合并散列在一起的函数。首先,它包含部署者(或发送者)的地址:启动智能合约,充当要创建的合约的父合约。接下来,它添加发送者提供的任意数字(或“salt”),这允许开发人员将相同的代码部署到不同的地址(通过更改 salt)并防止覆盖现有的相同合约。最后,它使用一些智能合约初始化(“init”)字节码的 keccak256 哈希,这是变成新智能合约的种子。这种哈希组合确定了一个以太坊地址,然后将给定的字节码部署到该地址。只要字节码保持完全相同,CREATE2 将始终将给定的字节码部署到区块链上的相同地址。

下面是 CREATE2 公式的样子。(注意:在下面的示例中,你会注意到另一个元素,“0xFF”。这只是 CREATE2 用于防止与前面的 CREATE 操作码发生冲突的常量。)

既然我们有办法将代码部署到确定性地址,那么如何更改同一地址的代码呢?起初,这似乎是不可能的。如果你想使用 CREATE2 部署新代码,则字节码必须更改,因此 CREATE2 将部署到不同的地址。但是,如果开发人员以这样一种方式构建字节码,当 CREATE2 部署智能合约时它可以“变形”成不同的代码呢?

变形合约实际上是如何运作的

将智能合约转变为变形合约的秘诀总共需要三个智能合约,每个合约都扮演着独特的角色。

这些必要的组成部分之一是变形合约工厂,它是操作的大脑。这个“工厂”负责部署 Metamorphic Contract 以及另一个名为 Implementation Contract 的智能合约,之所以如此命名是因为它的代码最终会在 Metamorphic Contract 中实现。这三个合约之间的微妙编排导致了变形,如下图所示。

让我们详细讨论 1-7 的每个步骤,以阐明工作中的操作。

第 1 步:开发人员让一切运转起来

程序员设计了一些智能合约代码——实施合约字节码——最终将出现在变形合约中。开发人员将此代码发送到 Metamorphic Contract Factory,这是一个智能合约,其主要目的是部署其他智能合约。这个动作启动了整个变形合约的创建过程。

接下来的一切都是这个初始步骤的结果。事实上,步骤 1 到 6 发生在区块链上的一个原子交易中,这意味着几乎同时完成。这些步骤可以一遍又一遍地重复,直到无限期地替换变形合约中的代码并使其不断变形。

第 2 步:工厂部署实施合约

Factory 部署的第一个合约是实施合约,其中包含实施代码。(非常有创意的办法)将实施合约想象成一个装卸码头或航路点,它在运送到最终目的地之前保存一些代码,在这种情况下,在变形合约内。

第三步:工厂门店实施合约地址

部署到区块链后,实施合约必然存在于某个区块链地址。工厂将此合约地址存储在自己的内存中(稍后在步骤 5 中使用)。

第 4 步:工厂部署 Metamorphic Contract

工厂使用 CREATE2 和变形字节码部署变形合约。你可以在此处找到有关变形字节码如何工作的技术性、深入的演练,但只要说变形字节码执行时,它会将代码从其他链上位置(在本例中是从实施合约)复制到变形契约。正如我们在上一节中谈到的,由于 CREATE2 是确定性的——只要使用相同的发送者、盐和字节码——那么无论这些步骤重复多少次,变形合约地址都保持不变。

下面是变形字节码的示例,来自0age的变形存储库。这只是变形字节码的一个例子——可能存在无数的变化,极大地复杂化了变形合约的检测。

第五步:变形字节码查询工厂实现合约地址

变形字节码向Factory询问实施合约地址(存储在步骤 3 中)。只要请求地址的变形字节码保持不变,实现合约的地址是否发生变化都没有关系。事实上,如果开发人员稍后部署一个新的实施合约——例如旨在窃取代币的恶意合约——它必然会按照第 2 步部署在不同的区块链地址。这对 Metamorphic Contract 的创建没有影响。

第 6 步:将实施合约代码复制到变形合约中

使用在第 5 步中学习到的区块链地址,变形字节码在实施合约中定位代码,并将该代码复制到变形合约的本地存储中。这就是 Metamorphic Contract 变形的方式:通过从 Implementation Contract 复制代码。

第 7 步:冲洗并重复这个操作

开发人员可以一遍又一遍地重复步骤 1 到 6,并通过新的实施合约将变形合约中的代码替换为他们喜欢的任何内容。所需要的只是使用 SELFDESTRUCT 操作码——或者,更狡猾的是,最终导致 SELFDESTRUCT 的 DELEGATECALL 操作码——来删除 Metamorphic Contract 中预先存在的代码。通过使用新的实施合约字节码重复循环,变形合约就会像魔术一样变形!

使用这种技术来创建变形合约,聪明的开发人员可以不断地在 web3 用户的脚下移动。例如,再次考虑诈骗场景。开发人员可能首先使用代币质押代码部署实施合约,该代码通过图形中描述并在上述步骤中详细说明的迂回路径,最终形成变形合约。诈骗者稍后可以自毁此代码并通过部署包含令牌窃取代码的新实施合约来替换它。

无论在实施合约中部署什么,最终都会在变形合约中结束。这就是精髓。

***

变形智能合约打破了web3 社会契约中隐含的“所见即所得的”。类似于使用三个移动的杯子来隐藏一个球的空壳游戏,三个合约在创建变形合约时的相互作用使这个合约得很难遵循合约的真实功能。空壳游戏是一个特别恰当的比较,因为自信的骗子经常会使用诡计和误导来确保他们获胜。在 web3 中,变形合约编写者同样可以使“球”——即实现代码——消失(也就是自毁),他们可以用任何东西替换它。

变形合约的存在意味着 web3 用户签订的很可能是可以随意更改的合约——这就是为什么理解和防御这种威胁如此重要。我的 Metamorphic Contract Detector只是技巧来识别变形合约的第一步。未来有几种方法可以改进检测器。例如,通过递归检查创建 Metamorphic Contract 的 Factory(或部署者合约),可以查看 Factory 本身是否是变形的。此功能将是对 Detector 升级版本 2 的有用补充。

值得再次重申:此检测器工具并非万无一失。它捕捉到的标志并不都是变形的迹象,但确实提供了一些甄别的线索。识别这些标志只是进行更彻底调查的开始。这就是为什么我们扩展检测器来搜索容易产生误报的原因,例如存在 CREATE2 或 DELEGATECALL 操作码。

编辑于 2022-06-24 22:19
「 真诚赞赏,手留余香 」
赞赏

发表评论已发布0

手机APP 意见反馈 返回顶部 返回底部