智能合约的超快速混合模糊测试工具

作者:Sec-Labs | 发布时间:

项目地址

https://github.com/fuzzland/ityfuzz

ItyFuzz 🍦

ItyFuzz 是一款快速的混合模糊测试工具,用于 EVM、MoveVM(WIP)等。

7c0a0dbb86000800

 

使用 UI 运行 ItyFuzz

安装 Docker,然后运行我们的 Docker 镜像(仅支持 x86,在非 x86 平台上运行会显著降低性能):

docker run -p 8000:8000 fuzzland/ityfuzz

然后,您可以在 http://localhost:8000 访问UI。

统计

发现漏洞/生成攻击所花费的时间:

项目名称 漏洞 Mythril SMARTIAN Slither ItyFuzz
AES 业务逻辑 Inf 不支持 No 4小时
Carrot 任意外部调用 17s 11s Yes 1s
Olympus 访问控制 36s Inf Yes 1s
MUMUG 价格操纵 Inf 不支持 No 18小时
Omni 重入 Inf 不支持 Yes* 22小时
Verilog CTF-2 重入 Inf 不支持 Yes* 3s

* Slither 仅发现重入位置,而不是如何利用重入来触发最终的错误代码。输出还包含大量的误报。

测试覆盖率:

数据集 SMARTIAN Echidna ItyFuzz
B1 97.1% 47.1% 99.2%
B2 86.2% 82.9% 95.4%
Tests 不支持 52.9% 100%

* B1 和 B2 包含 72 个合约。Tests 是 tests 目录中的项目。覆盖率计算为 (覆盖的指令)/(总指令 - 无效代码)

开发

构建

您需要安装libssl-dev(OpenSSL)和libz3-dev

# 下载依赖
git submodule update --recursive --init
cd cli/
cargo build --release

运行

编译智能合约:

cd ./tests/multi-contract/
solc *.sol -o . --bin --abi --overwrite --base-path ../../

运行Fuzzer:

cd ./cli/
./cli -t '../tests/multi-contract/*'

Demo

Verilog CTF Challenge 2 tests/verilog-2/

合约有闪电贷款攻击+重入漏洞。攻击目标是到达Bounty.sol中的第34行。

具体漏洞利用过程:

0. 借k MATIC,使得 k > balance() / 10
1. 用k MATIC 调用 depositMATIC()
2. redeem(k * 1e18) --重入合约--> getBounty()
3. 返还k MATIC

使用ItyFuzz检测漏洞并生成具体漏洞利用过程(需要0-200秒):

# 在tests/verilog-2/中构建合约
solc *.sol -o . --bin --abi --overwrite --base-path ../../
# 运行fuzzer
./cli -f -t "./tests/verilog-2/*"

-f标志启用自动闪电贷款,它会hook所有ERC20外部调用,使任何用户都具有无限余额。

离线Fuzz一个项目

您可以通过提供项目目录的路径(glob)来Fuzz一个项目。

./cli -t '[DIR_PATH]/*'

ItyFuzz将尝试将目录中的所有工件部署到没有其他智能合约的区块链中。 项目目录中应当包含[X].abi[X].bin文件。例如,要fuzz一个名为main.sol的合约,您应该 确保项目目录中存在main.abimain.bin。 ItyFuzz将自动检测目录中的合约之间的关联(参见tests/multi-contract), 并fuzz它们。

如果ItyFuzz无法推断合约之间的关联,您 也可以添加一个[X].address,其中[X]是合约名称,以指定合约的地址。

注意事项:

  • ItyFuzz在无任何合约的区块链上进行fuzz, 因此您应该确保在fuzz之前将所有相关合约(例如,ERC20令牌,Uniswap等)都将部署到 ItyFuzz 的区块链中。
  • 您还需要覆盖智能合约中的所有constructor(...)使它没有参数。 ItyFuzz假定构造函数没有参数。

在线Fuzz一个项目

(可选)启用 flashloan_v2 重新构建以获得更好的结果。

sed -i 's/\"default = [\"/\"default = [flashloan_v2,\"/g' ./Cargo.toml
cd ./cli/
cargo build --release

您可以通过提供地址,块和链来fuzz一个项目。

./cli -o -t [TARGET_ADDR] --onchain-block-number [BLOCK] -c [CHAIN_TYPE] 

示例: 在以太坊主网最新区块上fuzz WETH合约(0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2)。

./cli -o -t 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 --onchain-block-number 0 -c ETH

ItyFuzz将从Etherscan拉取合约的ABI并fuzz它。如果ItyFuzz遇到Storage中未知的槽,它将从RPC同步槽。 如果ItyFuzz遇到对外部未知合约的调用,它将拉取该合约的字节码和ABI。 如果它的ABI不可用,ItyFuzz将使用heimdall对字节码进行反编译分析ABI。

代理

为了有效地缓存昂贵的RPC调用,第三方API和Etherscan,我们创建了一个代理。

运行代理:

python3 proxy/main.py

然后请将--onchain-local-proxy-addr http://localhost:5003附加到您的CLI命令中。

标签:工具分享, 扫描工具, 模糊测试