ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Ethernaut 풀이] 이더리움을 해킹해보자 - 8.Vault
    BlockChain/Technology 2021. 8. 12. 13:55

     


    오늘의 풀어볼 문제는 Vault 입니다.

     

    컨트랙트에서 변수를 private로 표시하면 다른 컨트랙트가 해당 변수에 엑세스하는 것을 

    방지할 수 있다는 점을 기억하는 것이 중요합니다. 하지만 private과 loacal로 표시된 상태 변수들은

    여전히 공개적으로 접근할 수 있습니다. zk-SNARK는 매개변수를 공개할 필요 없이 누군가가

    비밀 매개변수를 소유하고 있는지 여부를 판별하는 방법을 제공합니다. 

     

     

     

     

    ≪ Ethernaut 풀이 시리즈 

     

     

    [Ethernaut 풀이] 이더리움을 해킹해보자 - 4.Telephone

    [Ethernaut 풀이] 이더리움을 해킹해보자 - 6.Delegation

    [Ethernaut 풀이] 이더리움을 해킹해보자 - 7.Force


    1. 목표 확인

    이번 level의 목표는 금고를 여는 것입니다. 금고를 열기 위해서는 배포자가 설정해둔 비밀번호를 알아내야 합니다.

     

    Hint : getStorageAt

    web3 공식문서에서 찾아서 읽어보세요. 이번 문제의 키입니다 !

     

    2. 문제 풀

     

    먼저 코드를 확인합니다. 

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.6.0;
    
    contract Vault {
      bool public locked;
      bytes32 private password;
    
      constructor(bytes32 _password) public {
        locked = true;
        password = _password;
      }
    
      function unlock(bytes32 _password) public {
        if (password == _password) {
          locked = false;
        }
      }
    }


    ① private

    컨트랙트를 보면 passwordprivate으로 선언된 것을 볼 수 있습니다. 비밀번호는 constructor에서 함수가 배포될 때 처음 설정됩니다. 배포자만 알 수 있는 것이죠. locked = true이므로 배포된 후 금고는 잠겨 있습니다. 

     

    금고를 열기 위한 함수가 있습니다. unlock 함수입니다. 하지만 금고를 열기 위해서는 if의 조건을 만족해야 합니다.

     

    if (password == _password) 

    패스워드를 정확히 맞추어야만 if의 조건을 만족시킬 수 있습니다.

     

     

    ② getStorageAt

     

    Web3의 공식문서 확인하기

     

    getStorageAt은 주소의 특정 위치의 스토리지를 가져옵니다. 

     

    Storage 
    스마트 컨트랙트에서 선언한 변수들은 EVM내에 Storage에 저장이 됩니다. 사용자가 컨트랙트를 호출할 때 저장된 변수들의 값들을 Storage에서 꺼내와 사용합니다. EVM Storage에는 약 2의 256에 해당하는 메모리 슬롯이 존재합니다. 변수를 할당할 때 마다 슬롯에 기록이 됩니다.

    선언한 변수들은 slot0, slot1, slot2, slot3..에 저장공간을 최적화시키면서 저장됩니다.

     

    스토리지에 접근해서 슬롯에 저장된 내용을 보는 문법은 다음과 같습니다.

    web3.eth.getStorageAt(address, position [, defaultBlock] [, callback])

     

    파라미터

     

    1. String - 스토리지를 가져올 주소입니다.
    2. Number|String|BN|BigNumber - 스토리지의 인덱스 위치입니다.
    3. Number|String|BN|BigNumber - (선택적) web3.eth.defaultBlock으로 설정된 기본 블록이 아닌 "가장 이른", "최신", 및 "보류 중"으로 미리 정의된 블록 번호도 사용가능합니다.
    4. Function - (선택적) 선택적 콜백, 첫 번째 매개변수로 오류 객체를 반환하고 두 번째 매개변수로 결과를 반환합니다.

    Returns

    주어진 주소 주소의 데이터를 반환합니다. 반환된 타입은 헥사코드로 이루어져 있습니다.

     

     

    이제 getStorageAt을 사용하여 비밀번호를 알아내 보겠습니다. 주소는 Instance 컨트랙트의 주소를 입력하면 되지만 넘겨줄 postion의 값을 정해야 합니다. 다행히 저장되는 슬롯의 인덱스는 위에서부터 아래 방향으로 0, 1, 2...로 붙여집니다. passwrod는 2번째 이므로 position의 값은 1입니다.

     

    콘솔창에 명령을 입력하면 아래와 같이 아주 길다란 헥사 코드가 얻어집니다. 이 값을 unlock 함수의 파라미터로 전달하면 잠겨있던 금고가 풀리게 됩니다 !

     

    목표 달성 ! 금고를 열어라

     

    잠깐 아직 하나 더 재밌는 요소가 있습니다. Web3에서는 헥사 코드를 ASCII코드로 변환하는 기능을 제공합니다. ASCII 코드는 영문 알파벳을 사용하는 대표적인 문자 인코딩입니다. 

     

    얻어진 헥사코드 값을 다음과 같이 입력합니다.

     

    => await web3.utils.hexToAscii("0x412076657279207374726f6e67207365637265742070617373776f7264203a29")

    비밀 번호에는 이러한 내용이 숨어 있었습니다. 매우 강력한 비밀 번호라고 했지만 이번 level에서 뚫려 버렸습니다 :)

    Submit instance 버튼을 눌러 제출을 완료합니다. 수고하셨습니다.

    댓글

Designed by Tistory.