# Lendf.Me 攻击策略

![](https://pic3.zhimg.com/80/v2-16e9001808406d7614efcbeb5f1f05ce_720w.jpg)

\\

此次黑客攻击，共累计的损失约24,696,616美元，具体盗取的币种及数额为：

WETH:55159.02134,

WBTC:9.01152,

CHAI:77930.93433,

HBTC:320.27714,

HUSD:432162.90569,

BUSD:480787.88767,

PAX:587014.60367,

TUSD:459794.38763,

USDC:698916.40348,

USDT:7180525.081569999,

USDx:510868.16067,

imBTC:291.3471

攻击成功后，攻击者不断通过OneInchExchange、AugustusSwapper、Tokenlon等去中心化交易平台以及Compound 借贷平台将盗取的币进行兑换和转移。

#### 攻击过程复盘

本次针对 [http://Lendf.Me](https://link.zhihu.com/?target=http%3A//Lendf.Me) 实施攻击的攻击者地址为： 0xa9bf70a420d364e923c74448d9d817d3f2a77822，攻击者的合约地址为： 0x538359785a8d5ab1a741a0ba94f26a800759d91d ，攻击者通过此合约对 [http://Lendf.Me](https://link.zhihu.com/?target=http%3A//Lendf.Me) 进行攻击。如下图所示：

\\

![](https://pic3.zhimg.com/80/v2-6bb5265869ccecda495dbf8af58abec2_720w.jpg)

\\

下面我们以攻击者盗取 [http://Lendf.Me](https://link.zhihu.com/?target=http%3A//Lendf.Me) 账户中的 imBTC 资产为例，详细分析黑客攻击过程。

#### 第一笔攻击交易

发起的第一笔交易是：[https://cn.etherscan.com/tx/0xe49304cd3edccf32069dcbbb5df7ac3b8678daad34d0ad1927aa725a8966d52a](https://link.zhihu.com/?target=https%3A//cn.etherscan.com/tx/0xe49304cd3edccf32069dcbbb5df7ac3b8678daad34d0ad1927aa725a8966d52a)，

\\

![](https://pic1.zhimg.com/80/v2-3ffd078ede2a7960239bd96bac251b70_720w.jpg)

\\

通过bloxy查看调用过程，[https://bloxy.info/tx/0xe49304cd3edccf32069dcbbb5df7ac3b8678daad34d0ad1927aa725a8966d52a](https://link.zhihu.com/?target=https%3A//bloxy.info/tx/0xe49304cd3edccf32069dcbbb5df7ac3b8678daad34d0ad1927aa725a8966d52a)

\\

![](https://pic4.zhimg.com/80/v2-0ad5c0f14c6d3a33f1c0e82d5093a98f_720w.jpg)

\\

第一次调用[supply函数](https://www.zhihu.com/search?q=supply%E5%87%BD%E6%95%B0\&search_source=Entity\&hybrid_search_source=Entity\&hybrid_search_extra=%7B%22sourceType%22%3A%22article%22%2C%22sourceId%22%3A133881606%7D)攻击者存入0.00021594，正常执行调用过程

第二次调用supply函数攻击者存入0.00000001，此时进行重入攻击，合约执行流程进入[withdraw函数](https://www.zhihu.com/search?q=withdraw%E5%87%BD%E6%95%B0\&search_source=Entity\&hybrid_search_source=Entity\&hybrid_search_extra=%7B%22sourceType%22%3A%22article%22%2C%22sourceId%22%3A133881606%7D)，攻击者调用withdraw函数取出攻击者的余额记录0.00021594，然后合约执行流程在回到supply函数，完成存入操作

最后交易持续完成，攻击者的余额记录为0.00021594 + 0.00000001 = 0.00021595，手中已取走的0.00021594，可以看到这里攻击者已经获利，资产总和已经翻倍

#### 第二笔攻击交易

继续看第二笔交易，交易hash为：[https://cn.etherscan.com/tx/0xae7d664bdfcc54220df4f18d339005c6faf6e62c9ca79c56387bc0389274363b](https://link.zhihu.com/?target=https%3A//cn.etherscan.com/tx/0xae7d664bdfcc54220df4f18d339005c6faf6e62c9ca79c56387bc0389274363b)，

\\

![](https://pic1.zhimg.com/80/v2-713cff74b223fedd21d7c4dd16cbec14_720w.jpg)

\\

通过bloxy查看调用过程，[https://bloxy.info/tx/0xae7d664bdfcc54220df4f18d339005c6faf6e62c9ca79c56387bc0389274363b](https://link.zhihu.com/?target=https%3A//bloxy.info/tx/0xae7d664bdfcc54220df4f18d339005c6faf6e62c9ca79c56387bc0389274363b)

\\

![](https://pic1.zhimg.com/80/v2-c91c2aeadf06da69070db11ebb7d86e4_720w.jpg)

\\

第一次调用supply函数攻击者存入0.00021593，正常执行调用过程

第二次调用supply函数攻击者存入0.00000001，此时进行重入攻击，合约执行流程进入withdraw函数，攻击者调用withdraw函数取出攻击者的余额，第一笔交易的余额0.00021595 + 第一次调用supply存入的 0.00021593 = 0.00043188，然后合约执行流程在回到supply函数，完成存入操作

最后交易持续完成，攻击者的[余额](https://www.zhihu.com/search?q=%E4%BD%99%E9%A2%9D\&search_source=Entity\&hybrid_search_source=Entity\&hybrid_search_extra=%7B%22sourceType%22%3A%22article%22%2C%22sourceId%22%3A133881606%7D)记录为0.00021595 + 0.00021593 + 0.00000001 = 0.00043189，手中已取走

#### 第三笔攻击交易

继续看第三笔交易，交易hash为：[https://cn.etherscan.com/tx/0xa0e7c8e933be65854bee69df3816a07be37e108c43bbe7c7f2c3da01b79ad95e](https://link.zhihu.com/?target=https%3A//cn.etherscan.com/tx/0xa0e7c8e933be65854bee69df3816a07be37e108c43bbe7c7f2c3da01b79ad95e)，

\\

![](https://pic2.zhimg.com/80/v2-1eb834c00aac8a69956accb13e737191_720w.jpg)

\\

通过bloxy查看调用过程，[https://bloxy.info/tx/0xa0e7c8e933be65854bee69df3816a07be37e108c43bbe7c7f2c3da01b79ad95e](https://link.zhihu.com/?target=https%3A//bloxy.info/tx/0xa0e7c8e933be65854bee69df3816a07be37e108c43bbe7c7f2c3da01b79ad95e)

\\

![](https://pic4.zhimg.com/80/v2-1eecebd4b93bb5a937c8c6769c17a88f_720w.jpg)

\\

第一次调用supply函数攻击者存入0.00043187，正常执行调用过程

第二次调用supply函数攻击者存入0.00000001，此时进行重入攻击，合约执行流程进入withdraw函数，攻击者调用withdraw函数取出攻击者的余额，第二笔交易的余额0.00043189 + 第一次调用supply存入的 0.00043187 = 0.00086376，然后合约执行流程在回到supply函数，完成存入操作

最后交易持续完成，攻击者的余额记录为0.00043189 + 0.00043187 + 0.00000001 = 0.00086377，手中已取走的0.00086376

从上面的联系三笔交易已经可以很清楚的看到，攻击者的每一次攻击，资产总和都是翻倍的，利用滚雪球的方式不断进行攻击，盗取 imBTC 的最后一笔交易如下图：

\\

![](https://pic4.zhimg.com/80/v2-01ac648951109706ad1a04690acd5517_720w.jpg)

\\

从上图可以看到，最终在交易 [https://cn.etherscan.com/tx/0xced7ca813081fb594181469001a6aff629c5874bd672cca44075d3ec768db664](https://link.zhihu.com/?target=https%3A//cn.etherscan.com/tx/0xced7ca813081fb594181469001a6aff629c5874bd672cca44075d3ec768db664) 中，基本已达到 imBTC 的最大存量，此时将 [http://Lendf.Me](https://link.zhihu.com/?target=http%3A//Lendf.Me) 账户中的 imBTC 资产盗取一空。

整个攻击过程原理图如下：

\\

![](https://pic4.zhimg.com/80/v2-67693cba5418800bf03a54890c3f66f3_720w.jpg)

\\

#### [漏洞代码分析](https://www.zhihu.com/search?q=%E6%BC%8F%E6%B4%9E%E4%BB%A3%E7%A0%81%E5%88%86%E6%9E%90\&search_source=Entity\&hybrid_search_source=Entity\&hybrid_search_extra=%7B%22sourceType%22%3A%22article%22%2C%22sourceId%22%3A133881606%7D)

下面我们分析一下 [http://Lendf.Me](https://link.zhihu.com/?target=http%3A//Lendf.Me) 合约代码，攻击者是如何达到上面的攻击效果的。

首先看看 [http://Lendf.Me](https://link.zhihu.com/?target=http%3A//Lendf.Me) 合约代码，合约地址：0x0eee3e3828a45f7601d5f54bf49bb01d1a9df5ea

看一下 [http://Lendf.Me](https://link.zhihu.com/?target=http%3A//Lendf.Me) 合约的supply函数，在supply函数的开头，申请了[临时变量localResult](https://www.zhihu.com/search?q=%E4%B8%B4%E6%97%B6%E5%8F%98%E9%87%8FlocalResult\&search_source=Entity\&hybrid_search_source=Entity\&hybrid_search_extra=%7B%22sourceType%22%3A%22article%22%2C%22sourceId%22%3A133881606%7D)s，然后将用户的余额保存在 localResults.userSupplyCurrent中，如下图所示：

\\

![](https://pic1.zhimg.com/80/v2-4d93802507f187416ffe8187bbb998b8_720w.jpg)

\\

在supply函数的最后，用户存入成功后，将用户的余额进行更新，此时最后用户的余额为localResults.userSupplyUpdated，如下图所示：

\\

![](https://pic3.zhimg.com/80/v2-ec6afbdb737ec81195fa051e5f94d362_720w.jpg)

\\

在更新用户余额之前，supply调用了 doTransferIn 函数，跟进 doTransferIn 函数：

\\

![](https://pic4.zhimg.com/80/v2-c3a3a77104b8272c9d8ae28e72f5d9d7_720w.jpg)

\\

在 doTransferIn 函数中，调用了imBTC合约的transferFrom函数，imBTC合约地址：0x3212b29e33587a00fb1c83346f5dbfa69a458923，跟进imBTC合约的 transferFrom 函数：

\\

![](https://pic1.zhimg.com/80/v2-3e0fa08675f89baa89337150d75fe4f4_720w.jpg)

\\

imBTC合约的 transferFrom 函数中，接着调用 \_callTokensToSend 函数，跟进：

\\

![](https://pic1.zhimg.com/80/v2-d27c4d0db5a5d9a6960a91ab23cfa3e4_720w.jpg)

\\

在 \_callTokensToSend 函数中，通过ERC1820 注册 了\`ERC777Sender\` 实现接口， 因此这里必须调用用户的 \`tokensToSend\` [钩子函数](https://www.zhihu.com/search?q=%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0\&search_source=Entity\&hybrid_search_source=Entity\&hybrid_search_extra=%7B%22sourceType%22%3A%22article%22%2C%22sourceId%22%3A133881606%7D)，这里就是攻击者重入漏洞发生的地方，攻击者在这里调用了 [http://Lendf.Me](https://link.zhihu.com/?target=http%3A//Lendf.Me) 合约的 withdraw() 函数，此时合约执行流程从 supply 进入到了 withdraw 函数中。

在 withdraw() 函数执行完后，继续回到supply调用了 doTransferIn 函数的后面继续执行，虽然在 withdraw() 函数中，用户取出余额之后，进行了余额数量更新，但是回到supply之后，继续执行后面的内容，那么在supply的最后再次更新了用户的余额，导致覆盖了用户 withdraw 之后余额数量的值。

具体合约代码进行重入攻击的流程如下图：

\\

![](https://pic3.zhimg.com/80/v2-54d4580bba1a6a9124bed34188ed64be_720w.jpg)

\\

通过上面的攻击过程我们可以看到，攻击者的 withdraw() 调用是发生在第二次supply调用的 transferFrom 函数中，也就是在 [http://Lendf.Me](https://link.zhihu.com/?target=http%3A//Lendf.Me) 合约中通过 transferFrom 调用用户的 tokensToSend() 钩子函数的时，攻击者在这里通过重入的方式调用了withdraw函数，造成了重入攻击。

#### 事件总结

DeFi由于其高收益，去中心化等优势目前比较火爆，但仍处于发展初期，还有很多机制仍需不断去完善，DeFi项目很多，但是质量都是参差不齐，而且生态中组件众多，只要有一个模块出了问题，可能就会拖垮整个项目。

[零时科技](https://www.zhihu.com/search?q=%E9%9B%B6%E6%97%B6%E7%A7%91%E6%8A%80\&search_source=Entity\&hybrid_search_source=Entity\&hybrid_search_extra=%7B%22sourceType%22%3A%22article%22%2C%22sourceId%22%3A133881606%7D)安全团队针对本次攻击事件，在此建议：

1\. 遵守严格的合约安全开发规范，在进行外部调用时先修改[合约变量](https://www.zhihu.com/search?q=%E5%90%88%E7%BA%A6%E5%8F%98%E9%87%8F\&search_source=Entity\&hybrid_search_source=Entity\&hybrid_search_extra=%7B%22sourceType%22%3A%22article%22%2C%22sourceId%22%3A133881606%7D)状态再进行外部调用；

2\. 项目上线前可通过专业的第三方安全团队进行全面的安全审计，尽可能的发现潜在的安全问题；

3\. 合约中加入风控体系，比如设置暂停开关，出现不可控问题时可及时止损；
