// 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
*/
}
The creator of this contract was careful enough to protect the sensitive areas of its storage.
Unlock this contract to beat the level.
Things that might help:
Understanding how storage works
Understanding how parameter parsing works
Understanding how casting works
Tips:
Remember that metamask is just a commodity. Use another tool if it is presenting problems. Advanced gameplay could involve using remix, or your own web3 provider.
locked를 false로 만들면 풀리는 문제이다. locked는 unlock 함수를 통해서 false로 바꿀 수 있다. byte16 타입의 데이터를 인자로 받고 data[2]와 비교를 하고 맞게 된다면 false로 바꿔주게 된다.
Ethernaut 풀었던 문제 중에서 private으로 데이터 타입을 설정해도 web3 API로 변수의 값을 읽을 수 있는 것을 해본적이 있다. 그렇다면 byte32 data[2]는 몇번째 인덱스의 위치하였는지 알아야 할 필요가 있다.
단순히 변수의 7번째라서 6이라고 치고 막상 검색해보면 안 나오는 것을 알 수 있다.
//index 0 (bool은 최대 32바이트 차지)
bool public locked = true;
//index 1 (uint256은 최대 32바이트 차지)
uint256 public ID = block.timestamp;
//index 2 (uint8은 최대 1바이트 차지)
uint8 private flattening = 10;
//index 2 (uint8은 최대 1바이트 차지)
uint8 private denomination = 255;
//index 2 (uint8은 최대 2바이트 차지)
uint16 private awkwardness = uint16(block.timestamp);
//index 3 (bytes32는 최대 32바이트 차지 => data[0]:3, data[1]:4, data[2]:5)
bytes32[3] private data;
하나의 인덱스에는 최대 32바이트를 저장할 수 있으므로 위와 같은 계산 방식으로 data[2]는 인덱스 5번째 위치에 존재하는 것을 알 수 있다.
data[2]의 값을 구했다.
function unlock(bytes16 _key) public {
require(_key == bytes16(data[2]));
locked = false;
}
해당 함수는 bytes32 타입인 data[2]의 값을 bytes16으로 형변환을 시켜주고 인자로 들어오는 key의 값과 비교를 해준다. 그렇다면 해당 값을 bytes16으로 형변환 시켜주고 해당 함수의 인자로 넣어준 뒤에 호출해주면 문제가 풀릴거 같다.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Find_key {
bytes32 public key = 0x93615177f13477ffb05e3f834e066be1adab311848b161000a0e751b9cc4e82a;
function find_key() public view returns (bytes16) {
return bytes16(key);
}
}
구한 값을 위의 코드로 형변환 시켜주고 해당 값을 인자로 함수를 호출한다.
그럼 locked의 값이 false로 바뀌게 되면서 문제를 풀 수 있었다.
🚩
'Write Up > Ethernaut - 블록체인 워게임' 카테고리의 다른 글
Ethernaut - 14단계 (Gatekeeper Two) (2) | 2023.11.21 |
---|---|
Ethernaut - 13단계 (Gatekeeper One) (1) | 2023.11.20 |
Ethernaut - 11단계 (Elevator) (2) | 2023.11.17 |
Ethernaut - 10단계 (Re-entrancy) (0) | 2023.11.16 |
Ethernaut - 9단계 (King) (0) | 2023.11.08 |