[ethernaut] MagicNumber

wooz3k.eth·2023년 1월 6일
0
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract MagicNum {

  address public solver;

  constructor() {}

  function setSolver(address _solver) public {
    solver = _solver;
  }

  /*
    ____________/\\\_______/\\\\\\\\\_____        
     __________/\\\\\_____/\\\///////\\\___       
      ________/\\\/\\\____\///______\//\\\__      
       ______/\\\/\/\\\______________/\\\/___     
        ____/\\\/__\/\\\___________/\\\//_____    
         __/\\\\\\\\\\\\\\\\_____/\\\//________   
          _\///////////\\\//____/\\\/___________  
           ___________\/\\\_____/\\\\\\\\\\\\\\\_ 
            ___________\///_____\///////////////__
  */
}

이 문제를 해결하려면 런타임 코드가 opcode 10개 이하로 42를 return 해주는 컨트렉트를 만들어야 한다.

그 전에 짚고 넘어가야할 개념이 있는데 바로 배포 코드와 런타임 코드이다. 런타임 코드는 CA에 존재하는 코드이고, 배포 코드는 배포할 때만 사용되고 CA에 저장되지 않는 코드이다. 생성자가 배포 코드에 해당한다.

그렇다면 우리는 런타임 코드가 opcode 10개 미만으로 이루어지고 42를 return 해주는 컨트렉트만 작성하면 문제가 해결될 것이다.

42를 return 해주려면 일단 먼저 stack에 42를 push를 해주어야할 것이다. push1 42는 opcode로 0x602a이다. 이후 stack에 있는 값을 return 하려면 memory에 올려야 한다. mstore(offset, value)를 실행해야하는데 value는 이미 stack에 존재하기 때문에 offset만 push하고 mstore를 실행시키면 된다. 그게 0x608052이다. offset은 0x80으로 지정해주었다. 이후 return(offset, size)를 호출하면되는데 memory에 한 slot은 크기가 32바이트이고, offset은 0x80으로 저장하였기 때문에 push를 해주면 된다. 0x60206080f3이다. 이를 합쳐주면 다음과 같다. 0x602a60805260206080f3

이제 배포 코드를 작성해주어야 하는데 다음과 같은 구조로 이더리움 tx가 요청될 것이다.

{
  "to": null,
  "value": 0,
  "data": "<init_code><runtime_code><constructor_args (option)>"
}

이렇게 요청이되면 배포 코드 뒤에 런타임 코드가 위치하는 것을 알 수 있을 것이고, 배포 코드에 존재 이유는 EVM에 런타임 코드를 return해주는 것이 목표이기 때문에 런타임 코드를 메모리에 올리고 return 해주도록 구현해야하는 것을 알 수 있다. 그 부분을 작성하면 다음과 같다. 0x600a600c600039600a00F3602a

그러면 결론적으로 0x600a600c600039600a00F3602a60805260206080f3를 배포하여 setSolver(address)에 등록하면 풀릴 것이다.

하지만 배포 코드와 constructor에 대해 이해를 완벽히 하고 있다면 배포코드를 작성할 필요가 없다는 것을 알 것이다.

contract attack {
    constructor() {
        assembly {
            mstore(0, 0x602a60805260206080f3) 
            return(0x16, 0x0a)
        }
    }
}

실제 배포된 CA 코드영역에는 0x602a60805260206080f3 만 존재할 것이다.

profile
Theori ChainLight Web3 Researcher

0개의 댓글