Appearance
S1C9: Password Protected
1. 問題
コントラクトにはパスワード保護関数があります。mintFlag を呼び出すには正しいパスワードを見つける必要があります。
2. 原因
パスワードはコントラクトの storage に保存されています。ブロックチェーン上のすべてのデータは公開されているため、storage スロットを直接読み取ってパスワードを取得できます。
3. 解法
cast storageを使用してコントラクトの storage スロットを読み取ります- パスワードが保存されているスロットを見つけます
- そのパスワードを使用して 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 storage または eth_getStorageAt を使用して読み取ります |