본문 바로가기
aaa
블록체인

스마트컨트랙트에서 코인을 훔쳐보자

스마트컨트랙트에서 코인을 훔쳐보자

[요약]

이더리움을 받을 수 있는 간단한 스마트컨트랙트를 작성하고

취약점을 발견하여 스마트컨트랙트 내에 있는 이더리움을 탈취한다.

 

  • 사례1 [Test1] Full Script
pragma solidity 0.8.6;

contract Test1 {
    
    uint nonce;
    
    constructor(uint _nonce) payable {
        nonce = _nonce;   
    }
    
    function getNonce() public view returns (uint) {
        return nonce;
    }
    
    function withdraw(uint _nonce) public {
        require(nonce == _nonce);
        payable(msg.sender).transfer(address(this).balance);
    }
    
}

constructor(uint _nonce) payable {
        nonce = _nonce;   
    }

constructor: 생성시 호출하는 함수

payable: 스마트 컨트랙트가 이더를 주고 받을 수 있게 만듬

nonce: _nonce에 값을 대입함.

 

 function getNonce() public view returns (uint) {
        return nonce;
    }

getNonce 함수.

호출시 nonce값을 반환한다.

 

   function withdraw(uint _nonce) public {
        require(nonce == _nonce);
        payable(msg.sender).transfer(address(this).balance);

withdraw 함수. uint 값 _nonce를 파라미터로 받는다.

입력한 _nonce 값이 nonce와 일치하면

스마트컨트랙트 호출자에게

스마트컨트랙트가 갖고 있는 잔고 모두를 전송한다.

 

 

  • 스마트컨트랙트 배포 <= 해킹대상

이 스마트컨트랙트에는

0.0000000001 Ether = 100000000wei

를 갖고 있다.

 

스마트컨트랙트 배포시 Deploy에 nonce 값을 넣어준다.

이 값을 알게되면 스마트컨트랙트 내에 있는 이더를 탈취할 수 있다.

 

 

 

  • 사례1 해킹시도

리믹스 > DEPLOY & RUN TRANSACTIONS > At Address

에 해킹할 스마트컨트랙트 주소를 입력하여 호출한다.

 

getNonce를 클릭하여 호출. nonce 값을 알아낸다.

nonce 값은 31.

 

 

 

 

withdraw에 nonce 값 31을 넣고

 

 

   function withdraw(uint _nonce) public {
        require(nonce == _nonce);
        payable(msg.sender).transfer(address(this).balance);

 

 

트랜잭션을 날리면

 

위 조건을 충족하기 때문에

스마트컨트랙트에 있는 이더리움이 

호출자에게 지급된다.

 

 

해킹 전
해킹 후

 

해킹 트랜잭션 로그

스마트컨트랙트의 잔고가 0으로 변경되면서

스마트컨트랙트가 갖고 있던 이더리움이 호출자에게 지급되었다.

해킹완료.

 

 

 

 


loading