Skip to content
On this page

S1C9: Password Protected

1. 问题

合约有一个密码保护函数。需要找到正确的密码才能调用 mintFlag

2. 原因

密码存储在合约的 storage 中。由于区块链上的所有数据都是公开的,可以直接读取 storage 槽位获取密码。

3. 方案

  1. 使用 cast storage 读取合约的 storage 槽位
  2. 找到密码存储的槽位
  3. 使用该密码调用 mintFlag
bash
# 读取 storage 槽位(尝试不同 slot)
for slot in 0 1 2 3 4 5; do
  cast storage <CHALLENGE> $slot --rpc-url $RPC
done
# 使用找到的密码
cast send <CHALLENGE> "mintFlag(string)" "found_password"

4. 遇到的陷阱

密码格式: 密码可能存储在多个槽位中(如果超过 32 字节),需要正确拼接。

5. 陷阱的原因

Solidity 中 string 类型如果长度 ≤ 31 字节,存储在单个槽位中(短字符串优化)。如果更长,当前槽位存储长度,数据存储在 keccak256(slot) 开始的连续槽位中。

6. 如何解决

先检查槽位值的最右字节是否为长度 × 2(短字符串编码),如果不是则读取 keccak256(slot) 开始的连续槽位。

7. 技术要点

要点说明
区块链透明性所有 storage 数据都是公开可读的
短字符串编码长度 ≤ 31 字节直接存于槽位,> 31 字节使用 keccak256 寻址
Storage 槽位使用 cast storageeth_getStorageAt 读取

Built with AiAda