Ethernaut: 12. 프라이버시
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract Privacy {
bool public locked = true;
uint256 public ID = block.timestamp;
uint8 private flattening = 10;
uint8 private denomination = 255;
uint16 private awkwardness = uint16(now);
bytes32[3] private data;
constructor(bytes32[3] memory _data) public {
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
*/
}
이는 EVM 저장소를 읽는 8단계Vault와 유사합니다. 여기에 추가로 a small optimization of EVM 및 how casting works 에 대해 알아봅니다.
EVM은 상태 변수를 32바이트 청크로 저장합니다. 연속 변수가 32바이트 공간을 구성하는 경우(예: 이 경우 8 + 8 + 16 = 32) 동일한 청크에 저장됩니다. 다른 곳에 작성했다면 이 최적화가 발생하지 않았을 수 있습니다.
await web3.eth.getStorageAt(contract.address, i)
의 다음 값에 대해 i
의 결과를 확인합니다.0: 0x0000000000000000000000000000000000000000000000000000000000000001
이것은 1로 저장된 bool public locked = true
입니다. 1: 0x0000000000000000000000000000000000000000000000000000000062bc6f36
이것은 uint256 public ID = block.timestamp
이며 16진수로 된 UNIX 타임스탬프입니다. 62bc6f36
2: 0x000000000000000000000000000000000000000000000000000000006f36ff0a
이것은 6f36ff0a
에서 모두 캡처한 3개 변수의 32바이트 청크입니다.uint8 private flattening = 10
즉 0a
uint8 private denomination = 255
즉 ff
uint16 private awkwardness = uint16(now)
는 6f36
입니다.음, 그
awkwardness
변수는 16비트로 캐스팅된 block.timestamp
일 뿐입니다. 우리는 이미 위의 타임스탬프의 실제 256비트(32바이트) 값을 알고 있습니다: 62bc6f36
. 16비트로 변환하면 6f36
(4 x 4비트 16진수)가 됩니다. 3: 0x0ec18718027136372f96fb04400e05bac5ba7feda24823118503bff40bc5eb55
이것은 data[0]
입니다. 4: 0x61a99635e6d4b7233a35f3d0d5d8fadf2981d424110e8bca127d64958d1e68c0
이것은 data[1]
입니다. 5: 0x46b7d5d54e84dc3ac47f57bea2ca5f79c04dadf65d3a0f3581dcad259f9480cf
이것은 data[2]
입니다. 이제
data[2]
를 bytes16
로 캐스팅하면 됩니다. 아주 짧은 단어로 캐스팅이 작동하는 방식은 다음과 같습니다.uint32 -> uint16
) uint16 -> uint32
) bytes32 -> bytes16
) bytes16 -> bytes32
) 따라서
data[2]
를 캐스팅하면 '0x46b7d5d54e84dc3ac47f57bea2ca5f79c04dadf65d3a0f3581dcad259f9480cf'.slice(0, 2 + 32)
와 await contract.unlock('0x46b7d5d54e84dc3ac47f57bea2ca5f79')
의 왼쪽 절반을 얻게 됩니다. 그게 다야! 읽기 저장에 대한 좋은 기사는 다음과 같습니다. block .
Reference
이 문제에 관하여(Ethernaut: 12. 프라이버시), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/erhant/ethernaut-12-privacy-3b2l텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)