Hundred Finance 攻击事件分析

背景知识

Hundred Finance 是 fork Compound 的一个借贷项目,在2023/04/15遭受了黑客攻击。攻击者在发起攻击交易之前执行了两笔准备交易占据了池子,因为发起攻击的前提是池子处于 empty 的状态(发行的 hToken 数量为 0)。

准备交易:

  1. https://optimistic.etherscan.io/tx/0xf479b1f397080ac01d042311ac5b060ceccef491867c1796d12ad16a8f12a47e

  2. https://optimistic.etherscan.io/tx/0x771a16e02a8273fddf9d9d63ae64ff49330d44d31575af3dff0018b04da39fcc

攻击交易:Phalcon || Tendery

交易分析

两次准备交易一共存入 63816 + 30000000 = 30063816 wei WBTC,获得 3190800 + 1499976495 = 1503167295 wei hWBTC

WBTC decimal = 8,hWBTC decimal = 8

执行攻击交易,首先从 AAVE V3 闪电贷出来 500 WBTC

通过 tendery 的模拟交易可以查询到,在攻击交易执行前,池子中存在 30064194 wei WBTC

首先 redeem 之前存入的所有 WBTC,将池子还原到 empty 的状态。

redeem 之后池子中存在 378 wei WBTC(其中1wei为留存资金,377wei为reserve资金),发行 0 hWBTC。empty状态仅代表 hWBTC 的 totalsupply 为 0。(如果先入为主地认为 WBTC的数量也为0,那么当你看到后面的时候会发现凭空多redeem出来了1 wei WBTC)

创建合约 0xd340 并往其中发送 50030063816 wei WBTC

合约 0xd340:

首先存入 4 WBTC,mint 200 hWBTC

redeem 19999999998 wei hWBTC,收到 4 WBTC。此时合约持有 2 wei hWBTC

向池子转入 50030063816 wei WBTC,然后借出 1021.915074492787011273 ETH

调用 redeemUnderlying 函数取出 50030063815 wei WBTC,消耗 1 wei hWBTC。此时合约持有 1 wei hWBTC。

攻击合约调用 liquidateBorrow 函数对创建的 0xd340 合约的债务进行清算。支付 0.000000267919888739 ETH,获得 1 wei hWBTC。

redeem 1 wei hWBTC,获得 2 wei WBTC,此时池子重新回到 empty 状态。这样做的目的是为了可以再次掏空其他池子。

把 50030063817 wei WBTC 转移走

随后攻击者又再进行了6次相同的操作来掏空其他的池子完成获利,文章篇幅有限就不再展开说明。

漏洞代码分析

合约 0xd340 在进行 redeem 操作时利用了精度丢失的漏洞,获取超额的 WBTC 。漏洞的发生在于 redeemFresh 函数中。

进入到 trace 分析,发现在 truncate 函数中进行了精度丢失。

跟进代码查看 truncate 函数的具体实现方法,在对输入参数 exp 除 1e18 的时候发生了精度丢失。

攻击细节分析

在分析攻击的过程中,对一些细节的部分存在着困惑,尝试着用生疏的技巧浅浅的分析一下。

为什么要先 mint 再 redeem,剩余 2 wei hWBTC

因为 mint 函数只能根据抵押物的数量来 mint hToken。也就是说在 initialExchange = 0.02 WBTC/hWBTC 的情况下,即使是传入 1 wei 的 WBTC,也会 mint 出 50 wei hWBTC。想要得到 2 wei hWBTC的剩余,没办法通过直接 mint 2 hWBTC 的方式(因为你无法提供 0.04 wei WBTC),所以只能先 mint 出大量的 hWBTC,然后再 redeem 使其剩余 2 wei。

所以按道理来说是不是先 mint 出 50 wei hWBTC,再 redeem 48 wei hWBTC 也可以?

为什么要剩余 2 wei hWBTC,而不是其他数量

剩余一定数量的 hWBTC 是为了后续构造精度丢失的攻击,使得合约从 hWBTC 的数量来计算抵押率是满足的,从而批准这笔 redeem,而实际上借出的 WBTC 数量是不满足抵押率要求的。而攻击者构造 2 wei 的这个数量就是为了通过精度丢失,是的超额借出的 WBTC 数量最大化。

假设在 2 wei 的情况下,borrow 了一半价值(1 wei)的资产:

赎回价值 1.99… wei hWbtc 的 WBTC,实际销毁 1 wei hWbtc。此时超额部分为 0.99… wei hWBTC,获得的 WBTC 占总资金的 1.99 / 2 。

在 20 wei 的情况下,borrow 了一半价值(10 wei)的资产:

赎回价值 10.99… wei hWbtc 的 WBTC,实际销毁 10 wei hWbtc。此时超额部分为 0.99… wei hWBTC,获得的 WBTC 占总资金的 10.99 / 20 。

通过上面两个例子我们可以得出,剩余的 hWBTC 数量越少,攻击者通过精度丢失所获得的超额 WBTC 比例就越大。

剩余的 hWBTC 数量可不可以为 1 wei 呢?

假设剩余 1 wei hWBTC,攻击者可以借出 100% 价值的资产,此时赎回价值 0.99… wei hWBTC 的 WBTC,利用精度丢失实际 burn 0 hWBTC。这样构造最大的好处是借出的资产可以达到 100%,而 2 wei 的方案借出资产只能借出 50%。

攻击者是如何构造获利场景的

攻击者只消耗 1 wei hWBTC ,然后 redeemUnderlying 出了 50030063815 wei WBTC

攻击者先 deposit 50030063816 wei WBTC,然后 redeem 50030063815 wei WBTC,希望通过 redeem (deposit amount - 1) 的方式构造精度丢失的场景:redeem 出价值 1.999… wei hWBTC 的 WBTC,最终会 burn 1 wei hWBTC,超额收益 0.999... hWBTC。

但是由于在攻击执行前池子里剩余有 1 wei WBTC,所以攻击者直接 redeem 50030063816 wei WBTC 也是可以达到 burn 1 wei hWBTC 的目的的。也就是说只有当 redeem 50030063817 wei WBTC 的时候才会 burn 2 wei hWBTC。

这个精度缺失攻击的前提是池子中 WBTC 的数量大于 hWBTC 的数量

假设 3 WBTC,2 hWBTC,可得 exchangeRateStoredInternal = 3 / 2 = 1.5

赎回 2 WBTC,计算需要 burn 的 hWBTC 数量:2 / 1.5 = 1.333… → 1 hWBTC

可以通过一个公式来计算出攻击者持有部分 hWBTC 的情况下通过精度丢失得到最大获利的情况吗?

  1. 假设池子持有 x WBTC,总共发行了 y hWBTC。攻击者持有 z hWBTC (z < y),赎回 kx WBTC (0 < k < 1)

  1. exchangeRateStoredInternal = x / y

  1. 由 1 和 2 可得,要 burn 的 hWBTC 数量 = kx / (x / y) = ky

  1. 攻击者为了获取尽可能大的超额收益,需要通过精度丢失漏洞构造 burn z + 0.999… hWBTC → burn z hWBTC

  1. 由 3 和 4 可得,ky = z + 0.999 → k = (z + 0.999) / y

举例说明:

  1. 假设池子持有 20000 WBTC,总共发行了 100 hWBTC,exchangeRateStoredInternal = 200。攻击者持有 50 hWBTC

  2. k = (z + 0.999) / y = (50 + 0.999) / 100 = 0.5099

  3. 赎回 kx = 0.5099 * 20000 = 10198 WBTC

  4. burn 的 hWBTC 数量为 kx / (x / y) = 10198 / 200 = 50.99 → 50

如何计算出清算所需要的 token 数量

通过 liquidateCalculateSeizeTokens 函数,计算得出提供 267919888739 wei ETH,能够清算获得 1 wei hWBTC

然后攻击者执行 liquidateBorrow 函数,提供 267919888739 wei ETH 进行清算,获得 1 wei hWBTC 。具体的计算过程以及涉及的参数如下图所示:

文章转载自: 阿菜种菜的菜园子

原文链接:https://www.cnblogs.com/ACaiGarden/p/17810494.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/183847.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

技术分享 | 使用 cURL 发送请求

cURL 是一个通过 URL 传输数据的&#xff0c;功能强大的命令行工具。cURL 可以与 Chrome Devtool 工具配合使用&#xff0c;把浏览器发送的真实请求还原出来&#xff0c;附带认证信息&#xff0c;脱离浏览器执行&#xff0c;方便开发者重放请求、修改参数调试&#xff0c;编写脚…

【GO】项目import第三方的依赖包

目录 一、导入第三方包 1.执行命令 2.查看go环境变量参数 3.查看go.mod文件的变化情况 二、程序里如何import 1. import依赖包 2. 程序编写 本次学习go如果依赖第三方的包&#xff0c;并根据第三方的包提供的接口进行编程&#xff0c;这里需要使用go get命令。下面将go…

个性化联邦学习-综述

介绍阅读的三篇个性化联邦学习的经典综述文章 Three Approaches for Personalization with Applications to Federated Learning 论文地址 文章的主要内容 介绍了用户聚类&#xff0c;数据插值&#xff0c;模型插值三种个性化联邦学习的方法。 用户聚类&#xff1a; 目的&a…

快速解决mfc140u.dll丢失问题,找不到mfc140u.dll修复方法分享

在计算机使用过程中&#xff0c;我们可能会遇到各种问题&#xff0c;其中之一就是某些dll文件丢失。最近&#xff0c;我就遇到了一个关于mfc140u.dll丢失的问题。mfc140u.dll是Microsoft Foundation Class&#xff08;MFC&#xff09;库中的一个动态链接库文件&#xff0c;它包…

Tomcat,jdk下载配置(发布项目)

Tomcat&#xff0c;jdk下载&#xff0c; 远程连接 启动以下服务 高级设置 允许别人连接进来 网上搜索jdk下载即可 双击下一步即可 下一步 输入java&#xff0c;看有没有安装成功 这是安装成功的 Tomcat就可以安装了 和以上操作一样&#xff0c;在网上下载安装包&#xff0c;…

手把手教你搭建属于自己的服务器

最近总是想搭建自己的网站&#xff0c;奈何皮夹里空空如也&#xff0c;服务器也租不起&#xff0c;更别说域名了。于是我就寻思能否自己搭建个服务器&#xff0c;还不要钱呢&#xff1f; 还真行&#xff01;&#xff01;&#xff01; 经过几天的冲浪&#xff0c;我发现有两个…

SpringBoot文件上传

SpringBoot文件上传 上传文件是互联网中常常应用的场景之一&#xff0c;最典型的情况就是上传头像等&#xff0c;今天就带着带着大家做一个 Spring Boot 上传文件的小案例。 1、pom依赖 <?xml version"1.0" encoding"UTF-8"?> <project xml…

pytest中的pytest.ini

[pytest] filterwarnings ignore::DeprecationWarning addopts -v -s markers uat:1 smok:2 log_cli1 xfail_strict True filterwarnings ignore::DeprecationWarning 这个的功能就是 test_login.py::Test_login::test_login_correct_password PASSEDwarnings summary …

[答疑]大老二和德州扑克-属性值没变,状态怎么变了

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 邬俊杰 2023-10-31 21:20 课上说状态是由属性值决定的&#xff0c;比如身高>170算高&#xff0c;某人身高175&#xff0c;算高。如果规则改了&#xff0c;身高>180算高&#xf…

C语言——循环结构

C语言提供了while&#xff0c;do...while&#xff0c;for三种语句构成循环结构。循环语句是程序中的一个基本语句&#xff0c;在编程中&#xff0c;如果我们需要对某些操作对象进行相同的操作&#xff0c;那么&#xff0c;使用循环语句&#xff0c;就能让计算机反复执行&#x…

【渗透测试】垂直越权(高危)、水平越权(中危)

目录 一、简介1.1 水平越权&#xff08;中危&#xff09;1.2 垂直越权&#xff08;高危&#xff09;1.3 方便记忆方法 二、修复方案2.1 水平越权修复2.2 垂直越权修复 一、简介 1.1 水平越权&#xff08;中危&#xff09; 漏洞危害&#xff1a; 水平越权 是相同级别&#xff0…

修改iframe生成的pdf的比例

如图想要设置这里的默认比例 在iframe连接后面加上#zoom50即可&#xff0c;50是可以随便设置的&#xff0c;设置多少就是多少比例 <iframe src"name.pdf#zoom50" height"100%" width"100%"></iframe>

算法打卡01——求两数之和

题目&#xff1a; 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你…

macOS 下 starUML 软件激活方案

starUML每次打开都弹出提示其实挺烦的&#xff0c;于是研究了一下如何 po 解(激活)它。记录一下方法以便以后使用。 我觉得这个软件很好用&#xff0c;大型项目的所有图我都是用这个软件画的。 直接上步骤&#xff01;先关掉starUML 1、安装 asar&#xff0c;以便可以打开 asa…

Python万圣节礼物

文章目录 系列文章前言小海龟快速入门万圣节蝙蝠万圣节南瓜头万圣节礼物尾声 系列文章 序号文章目录直达链接1浪漫520表白代码https://want595.blog.csdn.net/article/details/1306668812满屏表白代码https://want595.blog.csdn.net/article/details/1297945183跳动的爱心http…

(附源码)springboot学生宿舍管理系统 毕业设计 211955

摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运用中&#xff0c;应用软件的工作…

如何实现Word文档中的书签双向定位

工作中&#xff0c;经常需要拟定合同&#xff0c;一般都有固定的模板&#xff0c;在特定的位置填写内容。通过zOffice编辑合同文件时&#xff0c;可以在模板需要填写的位置预设书签&#xff0c;配合zOffice SDK使用&#xff0c;利用zOffice书签双向定位的特性&#xff0c;更方便…

C++基础——类与对象

1 概述 C是面向对象的语言&#xff0c;面向对象语言三大特性&#xff1a;封装、继承、多态。 C将万事万物抽象为对象&#xff0c;对象上有其属性和行为。 2 封装 2.1 封装的意义 封装是面向对象的三大特性之一&#xff0c;封装将属性和行为作为一个整体&#xff0c;对属性和…

设计模式——建造者模式

目录 建造者模式盖房项目需求基本介绍四个角色实例代码注意事项和细节抽象工厂模式 VS 建造者模式 建造者模式 盖房项目需求 传统方式&#xff1a;打地基&#xff0c;砌墙&#xff0c;封顶 盖房子步骤 public abstract class AbstractHouse {// 地基public abstract void b…

运行java命令出现 Error: Invalid or corrupt jarfile XXX.jar

朋友 我当你一秒朋友 朋友 我当你一世朋友 奇怪 过去再不堪回首 怀缅 时时其实还有 运行java命令出现 Error: Invalid or corrupt jarfile XXX.jar 基本可以断定&#xff0c;是jar不完整导致的。不完整&#xff01;&#xff01;&#xff01;记住关键字 检查1&#xff1a; …