可信链攻防ctf——决赛solidity题解

Posted by Thomas_Xu on 2022-11-23

author:Thomas_Xu

中国可信区块链攻防大赛——决赛solidity题解

前一段时间没有更新,其实是去参加中国可信链攻防大赛了,作为本届大赛唯一的本科生队伍,我们已经做得足够好了,初赛满分,决赛一天时间 9个题解出5个题。如果时间足够,我认为是有可能全解的。

这里我只分析我做的两个chanllenge

ApproveMain

漏洞点:grant导致任意的slot覆盖

题意分析:

此题的Cert是一个实现了所有基础功能的代币合约,在创建此token时,自动获得100ETH

目标是使cert.balanceOf(address(this))==0

此合约还有一个getToken公开函数,每次只能向调用者发送自己一半的余额。(没用)

而Cert函数里面有一个admin参数,没有在任意一个地方被赋值,但是却有地方使用admin作为权限检查。

这给了我一个很大的思路,也许我们可以通过某种方式获得admin权限?

漏洞分析

这里定义了一个safeCheek的修饰符,用于approve函数的权限管理。但这里的判断明显是个弱检查,并且使用了tx.orgin作为身份验证(检查是否以0x5B38Da开头),这样的做法相当危险,我们不仅可以通过Create2跑靓号,也可以使用钓鱼攻击来绕过这个权限。巧合的是remix本地节点的第一个账户就以“0x5B38Da”开头。省去了做题时不必要的麻烦。

如果不满足条件,就会执行一个有巨大权力的grant函数,这也是此题薄弱点所在。

让我们看看grant函数到底干了什么

这里的逻辑使用了slot来给变量赋值,但是并没有进行任何的检查,也就是说我们可以通过此函数,覆盖任何我们想要覆盖的变量,只需要绕过require即可。

那么现在此题的关键就来到了怎么绕过这个require

1
require(spender.code.length>0&&spender.code.length<10);

这里要求spender地址的编译时字节码需要在0~10之间

这个条件其实是十分苛刻的,spender既不能是EOA账户,也不能是普通的合约账户

  • try

    我们发现即使是一个空合约,也有至少18的字节码长度。于是尝试使用EVM低级语言写一个简单合约:

    我尝试使用Huff语言写一个空合约,

​ 让我很失望的是即使是这样,字节码长度任然大于10

  • ​ 最后我在无比绝望当中尝试着直接删除中间部分的字节码强行使长度小于10,编译,通过!!

​ 没想到这样可以直接生成一个指定字节码长度的地址

Exploit

按照以上的分析思路,我们可以知道,第一次执行approve的时候只要想办法进去到grant然后就可以覆盖任意slot位置的值。

那我们的传参如下:

address:刚刚生成的字节码长度小于10的地址,和admin参数所在的slot位置。

uint256: admin参数的slot地址

由于题目中的transferfrom要求to的地址必须是EOA账户,所以我们只能在最后手动调用transferfrom函数掏空合约的token。

第四题:

漏洞点:cheapswap缺少k值检查

漏洞分析

这个题实现了一个简单的DEX,重写的Uniswapv2部分代码,并提供了一个闪电贷。

这个题的漏洞是出现在pair合约中改写了uniswapv2中的swap基础函数,实现了一个cheapswap。

但是这个cheapswap没有进行k值检查,他是通过onlyRouter来防止有人直接调用cheapswap从而直接获利。

这个合约最大的问题就是改写swap的同时,没有把以前的swap给删掉

通过以上分析我们可以知道攻击者在一次代币兑换过程中分别通过调用 swap 函数与 cheapSwap 函数进行两次代币兑换操作,理论上每次兑换操作都将导致 K 值的变化,最终使得用户无法获得预期的代币。但是这个cheapswap并没有进行k值检查,导致我们可以在一次兑换中获得额外的token。

攻击过程

1 、先通过 config的 闪电贷借出 TTtoken

2、创建恶意的代币合约 Mytoken,并在 Dex 中添加了 Mytoken 代币与 ttToken 代币流动性。

3、通过 Mytoken -> TTtoken -> USDT 路径进行 Mytoken 代币到 USDT 代币的兑换,并在 Mytoken 代币转入 Pair 合约兑换成 TTtoken 代币的过程中进行了一次 TTtoken 代币与 USDT 的兑换操作,随后再进行正常的 cheapSwap 操作。最终获得了额外的token。

顺带提一句,这个题其实是真实的攻击事件Impossible token的bsc被盗的改编。


notice

true

This is copyright.

...

...

00:00
00:00