본문 바로가기

system/material

ethereum assembly analysis using remix DEBUGGER plugin

solidity assembly+remix

ethereum assembly analysis using remix DEBUGGER plugin

 

위의 테스트 코드를 사용하겠다.

 

remixDEBUGGER 플러그인을 이용하여 동적 디버깅을 진행한다. 이 과정으로 어셈블리를 익혀보자!

 

코드를 컴파일한 후 컨트랙트를 Deploy하면 transaction hash값을 얻을 수 있다. 이를 DUBUGGER 플러그인의 인자로 넣고 디버깅을 시작하자.

 

그러면 위와 같은 화면을 만날 수 있다.

어셈블리가 보이는 영역은 code 영역이며 그 밑에는 step over, step into와 같은 버튼이 존재하고 그 밑에는 메모리가 존재한다.

 

code: 이더리움의 기계어가 저장되는 공간이다.

storage: 상태 변수들이 저장되는 공간이다.

memory: 메모리형으로 선언된 변수들이 저장되는 공간이다.(아직까지는 잘 모르겠다.)

stack: 함수 내에 존재하는 로컬 변수들이 저장되는 공간이다.

이 외에도, call data가 존재한다. solidity 상에서는 msg.value에 해당하는 값이다.

 

위와 같이 되어있다.

스택에 값을 넣고, 이를 인자로 기계어를 실행하는 식이다. (상태 변수 값이 필요할 시 storage에서 stack으로 값을 가져와서 연산)

 

기계어에 대한 설명은 하나하나 설명하면 기억에도 안남으니 실습을 통해 이해해보자.

 

이더리움의 모든 어셈블리는 아래 링크에서 확인할 수 있다.

https://solidity.readthedocs.io/en/v0.4.24/assembly.html#opcodes

 

첫 번째로 나오는 어셈블리어이다.

여기서 80과 40은 각각 0x80, 0x40이다.

먼저 PUSH1 명령어로 0x80, 0x40을 스택에 집어 넣는다.

PUSHi x = stack top에 x를 ibyte 만큼 집어 넣는다. (ibyte만큼 값을 넣을 수 있는거지 패딩은 똑같이 32byte로 된다.)

 

이는 MSTORE(0x40, 0x80) 명령어를 뜻한다.

MSTORE = MEMORY STORE라고 생각하면 된다.

MSTORE(a, b) = a+0x10의 메모리 위치에 b를 저장한다.

 

실제로 메모리에 값이 들어갔다!

근데 왜 저런식으로 0이 많이 들어갈까?

EVM에서는 1 word = 32byte로 정의하고 있기 때문이다!

 

그 다음 어셈블리어를 보자.

먼저 DUP1 명령으로 스택에 값을 복사한다.

DUPi = 스택의 i-1번 째 행을 stack top에 집어 넣는다.

 

그 후, 복사한 값이 zero라면, 해당 값을 1로 바꾼다.

ISZERO(a) = a가 0이라면 값을 1로 바꾼다.

 

그 후, 값을 PUSH하고 조건부 점프를 진행한다.

JUMPI(a, b) = b가 zonzero라면, 어셈블리 영역의 a로 점프한다.

 

여기까지 진행되면, JUMPI(0x10, 1)이 실행될 것이므로 current pc: 016이 될 것이다.

 

그 다음 어셈블리를 보자.

0x40을 스택에 집어 넣고, MLOAD(0x40)을 실행한다.

MLOAD(x) = 메모리의 x+0x10에 존재하는 값을 stack top에 집어 넣는다.

 

그 후, 0x20을 집어 넣고 이 값을 DUP1으로 복사하며, 0189을 집어 넣고 MLOAD로 불러온 값을 DUP4를 이용하여 복사한다.

그리고! CODECOPY를 진행한다.

CODECOPY(a, b, c) = a 메모리에 call data의 b position부터 c만큼 복사한다.

즉, 우리가 함수를 실행할 때 보냈던 인자를 메모리로 복사하는 것이다.

우리의 경우는 CODECOPY(0x80, 0x189, 0x20)이 되어 0x80번 째 메모리에 call data + 0x189부터 0x20만큼 복사하게 되는 것이다.

 

이 뒤부터는 SWAP1 명령어가 나오는 것을 제외하고는 모두 알아봤던 명령어들이 나오므로 직접 해보길 바란다.. 재밌다^^;

SWAPi(x) = x와 stack i번 째 값을 서로 바꾼다.

 

직접 끝까지 해봤다면, 마지막으로 CODECOPY를 진행하고 RETURN을 하는 곳까지 디버깅을 진행했을 것이다.

근데 보면 그 바로 뒤에 STOP이 있고 코드가 쭉 있을 것이다.

이건 왜일까? 우리가 디버깅한 코드는 무엇일까?

를 생각해보면서 우리가 여태까지 디버깅한 코드의 중요한 지점들을 살펴보자.

어디일까?, SSTORE, 마지막 CODECOPY이다.

SSTORE은 컨트랙트 상에 정보를 영원히 저장한다.

그렇다면 마지막 CODECOPY는 무엇일까? 이 인스트럭션을 실행하고 나면 메모리가 다음과 같이 바뀌어 있을 것이다.

이것들은 무엇일까? msg.data에서 살펴보면 다음과 같다.

 

그럼 앞에 있는 코드는 무엇이고 뒤에 있는 코드는 무엇일까, 앞에 있는 코드는 constructor를 실행시키고, 뒤에 있는 코드를 메모리에 CODECOPY 한다. 즉, deploy하는 과정이라고 볼 수 있다.

뒤에 CODECOPY된 코드는 실제 contract 코드이다.

정말 신기하다 ㅎㅎ


'system > material' 카테고리의 다른 글

unsortedbinbin_attck died..  (0) 2019.11.05
linux file structure attack  (0) 2019.10.28
modern memory safety #1  (0) 2019.10.09
docker 간단한 사용법 정리  (0) 2019.08.25
19회 해킹캠프 발표자료 (tcache 동작 분석 및 exploit)  (0) 2019.02.19