// 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
*/
}
locked를 false로 바꾸면 된다.
unlock함수에서 locked=false를 해주는데 이를 위해서 key값을 알아내야 한다.
key값은 bytes16(data[2])이기 때문에 data[2]를 알아내고 앞의 16바이트만 갖고오면 된다.
각 변수당 slot의 위치는 다음과 같다.
bool public locked => 0번째
uint 256 public ID => 1번째
uint8 private flattening => 2번째 1바이트
uint8 private denomination => 2번째 2바이트
uint16 private awkwardness => 2번째 3~4바이트
bytes32[3] private data => 3번째, 4번째 ,5번째
한 슬롯의 크기는 32바이트이다. 이때, data가 2번째 5바이트부터 시작하지 않는 이유는 data는 bytes32로 선언되어있기에 2번째 슬롯에 모두 못들어가므로 3번째 슬롯부터 시작하는 것이다.
ID가 0번째부터가 아닌 1번째부터 시작하는 것도 마찬가지이다. (uint256은 32바이트, uint8은 1바이트)
먼저 값이 잘 들어가있나 확인하기 위해 2번째 slot값을 가져와봤다.
from web3 import Web3, utils
from solc import * # 솔리디티 컴파일러 모듈
account_address = '0x0454D4DAd937d831c98cCD8ef9c4035B34c7F22C'
private_key = '0e509f02347afe4620c78bea35a72fb3f41058347f6fe87c8f7574c2c9cf585a'
contract_address = '0x00cB5A9FA382fa22bb7B302A23786f6B0909dee8'
w3 = Web3(Web3.HTTPProvider('https://sepolia.infura.io/v3/57db54396b784ae38a9b70581c7d93cc')) # 내 지갑 네트워크 연결
storage_position = 2
storage_value = w3.eth.get_storage_at(contract_address, storage_position)
print(storage_value.hex())
0000000000000000000000000000000000000000000000000000000024a8ff0a
여기서 주의해야할 점이
string, bytes는 big-endian이고 나머지는 little-endian이라고 한다.
따라서 flattening과 denomination은 uint기 때문에 little-endian이므로 오른쪽부터 읽어줘야 한다.
0a는 10 이므로 flattening값이 맞고
ff는 256으로 denomination이 맞다.
그다음 key값은 data[2]기에 5번째 값을 갖고왔다.
3e5aeffcdd3afa0148e10483b324750380d3891f11be56d7151c23f3a9ae6db0
요거 앞 16바이트 넣으면 된다.
await contract.unlock('0x3e5aeffcdd3afa0148e10483b3247503')
끝
'Web3 > The Ethernaut' 카테고리의 다른 글
[The Ethernaut] Gatekeepr Two (0) | 2025.01.31 |
---|---|
[The Ethernaut] Gatekeeper One (0) | 2025.01.31 |
[The Ethernaut] Elevator (0) | 2025.01.28 |
[The Ethernaut] Re-entrancy (1) | 2025.01.28 |
[The Ethernaut] King (0) | 2025.01.23 |