본문 바로가기

REVERSING

[SWING] Reversing 07

메모리 구조

 

프로그램이 실행되기 위해서는,

먼저 프로그램이 메모리에 로드(load)되어야 하고,

프로그램에서 사용되는 변수들을 저장할 메모리도 필요하다.

 

따라서 컴퓨터의 운영체제는 프로그램의 실행을 위해 다양한 메모리 공간을 할당하고 있다.

 

1. 코드(code) 영역

2. 데이터(data) 영역

3. 스택(stack) 영역

4. 힙(heap) 영역

 

 

 

코드(code) 영역

실행할 프로그램의 코드가 저장되는 영역으로 텍스트(code) 영역이라고도 부른다.

CPU는 코드 영역에 저장된 명령어를 하나씩 가져가서 처리한다.

 

데이터(data) 영역

프로그램의 전역 변수와 정적(static) 변수가 저장되는 영역이다.

데이터 영역은 프로그램의 시작과 함께 할당되며, 프로그램이 종료되면 소멸한다.

 

스택(stack) 영역

함수의 호출과 관계되는 지역 변수와 매개변수가 저장되며 프로그램이 자동으로 사용하는 임시 메모리 영역이다.

함수의 호출과 함께 할당되며, 함수의 호출이 완료되면 소멸한다.

후술하겠지만 이렇게 스택 영역에 저장되는 함수의 호출 정보를 스택 프레임(stack frame)이라고 한다.

 

 

프로세스에서 스택 포인터(ESP)의 초기 값은 Stack Bottom쪽에 가깝다.

푸시(push) 동작으로 데이터를 위쪽으로 Stack Top을 향해 저장하고,

팝(pop) 동작으로 데이터를 아래쪽으로 Stack Bottom을 향해 인출한다.

 

이러한 스택은 후입선출(LIFO, Last-In First-Out) 방식에 따라 동작하므로, 가장 늦게 저장된 데이터가 가장 먼저 인출된다.

메모리의 높은 주소에서 낮은 주소의 방향으로 할당된다.

그래서 스택이 거꾸로 자라난다는 표현을 쓰기도 한다.

애초에 스택이라는 단어가 무언가를 쌓는다는 의미이기 때문에 아래에서 위로 올라오는 방향이라고 이해하면 쉽다.

 

힙(heap) 영역

사용자가 직접 관리할 수 있고 해야만 하는 메모리 영역이다.

사용자에 의해 메모리 공간이 동적으로 할당(Dynamic Memory Allocation)되고 해제된다.

메모리의 낮은 주소에서 높은 주소의 방향으로 할당된다.

 

 

위의 HEAP과 STACK영역은 사실 같은 공간을 공유한다.

HEAP이 메모리 위쪽 주소부터 할당되면 STACK은 아래쪽부터 할당되는 식이다.

그래서 각 영역이 상대 공간을 침범하는 일이 발생할 수 있는데,

이를 각각 HEAP OVERFLOW, STACK OVERFLOW라고 칭한다.

Stack 영역이 클수록 Heap 영역이 작아지고,

Heap 영역이 클수록 Stack 영역이 작아진다.

 

 

 

스택 프레임

 

 

ESP(스택 포인터)가 아닌 EBP(베이스 포인터) 레지스터를 사용하여

스택 내의 로컬 변수, 파라미터, 복귀 주소에 접근하는 기법을 말한다.

 

ESP레지스터의 값은 프로그램 안에서 수시로 변경되기 때문에

스택에 저장된 변수, 파라미터에 접근하고자 할 때 EPS 값을 기준으로 하면

프로그램을 만들기 힘들고, CPU가 정확한 위치를 참고할 때 어려움이 있다. 

 

따라서 어떤 기준 시점(함수 시작)의 ESP값을 EBP에 저장하고 이를 함수 내에서 유지해주면,

ESP 값이 아무리 변하더라도 EBP를 기준으로 안전하게 해당 함수의 변수, 파라미터, 복귀 주소에 접근할 수 있다.

 

PUSH EBP 		; 함수 시작(EBP를 사용하기 전에 기존의 값을 스택에 저장) 
MOV EBP, ESP		; 현재의 ESP(스택 포인터)를 EBP에 저장

. . .			; 함수 본체
			; 여기서 ESP가 변경되더라도 EBP가 변경되지 않으므로 
         	  	; 안전하게 로컬변수와 파라미터를 액세스할 수 있음 
                
MOV ESP, EBP		; ESP를 정리(함수 시작했을 떄의 값으로 복원시킴)
POP EBP			; 리턴되기 전에 저장해 놓았던 원래 EBP 값으로 복원 
RETN			; 함수 종료

 

스택 프레임을 이용해서 함수 호출을 관리하면,

아무리 함수 호출 depth가 깊고 복잡해져도 스택을 완벽하게 관리할 수 있다. 

 

참고)

최신 컴파일러는 최적화 옵션을 가지고 있어서 간단한 함수 같은 경우 스택 프레임을 생성하지 않는다.
스택에 복귀 주소가 저장된다는 점이 보안 취약점으로 작용할 수 있다.

buffuer overflow 기법을 사용하여 복귀 주소가 저장된 스택 메로리를 의도적으로 다른 값으로 변경할 수 있다. 

'REVERSING' 카테고리의 다른 글

[SWING] Reversing 09  (0) 2023.05.13
[SWING] Reversing 08  (0) 2023.04.30
[SWING] Reversing 06  (0) 2023.03.26
[SWING] Reversing 05  (0) 2022.08.26
[SWING] Reversing 04  (0) 2022.08.22