Skip to content

Latest commit

 

History

History
45 lines (28 loc) · 2.04 KB

README.md

File metadata and controls

45 lines (28 loc) · 2.04 KB

Preservation

题目描述

原题 in Sepolia

获得Preservation合约的owner权限

运行

根据Foundry 官方文档配置好运行环境后,于本项目下执行下列命令:

$ cd WTF-CTF

$ forge test -C src/Ethernaut/Preservation -vvvvv

功能简述

Preservation 合约使用 delegatecall 时只会使用 LibraryContract合约的代码逻辑。

LibraryContract合约寻找变量时会按照 LibraryContract合约变量所在的插槽寻找 Preservation合约对应插槽中的变量。

首先调用 Preservation合约的 setFirstTime函数,函数参数为:Attack合约的地址。此时,Preservation合约中的timeZone1Library变量就修改为了Attack合约的地址。

Preservation(preservation).setFirstTime(uint256(uint160(attack)));

然后再调用 Preservation合约的 setFirstTime函数,函数参数为:我的账户地址。因为Attack合约寻找变量时会按照 Attack合约变量所在的插槽寻找 Preservation合约对应插槽中的变量。从而改变owner账户的地址。

Preservation(preservation).setFirstTime(uint256(uint160(address(this))));

所以,在使用代理调用delegatecall时,需要保证proxy合约和implementation合约的内存插槽不要有冲突,如果proxy合约中有变量,implementation合约中就不要使用proxy合约中变量占据的插槽位置。另一个解决办法是proxy合约存储变量时尽量指定插槽位置,不使用默认从0开始的插槽排布

assembly {
	param.slot := slot
}

具体,可以查看ERC-1967: Proxy Storage Slots或openzeppelin对代理合约的实现文档,另外ERC-2535: Diamonds, Multi-Facet Proxy 可以同时代理多个合约。