[Stack] 메모리 구조 : 간단한 동적분석

메모리 구조를 찾아보면 Computer Architecture, Operating System에서 많이 다루는걸 볼 수 있다.

CS에서 가장 기초적이고 중요한 부분이기도 하다.

 

바쁜 사람들을 위한 표 정리

segment 역할 권한 예시
Code 실행 가능한 코드가 저장된 영역 읽기 실행 main() 등의 함수 코드
Data 초기화된 전역 변수, 상수가 위치하는 영역 읽기 쓰기 / 읽기 초기화된 전역 변수, 전역 상수
BSS 초기화되지 않은 데이터가 위치하는 영역 읽기 쓰기 초기화되지 않은 전역 변수
Heap 실행중에 동적으로 사용되는 영역 읽기 쓰기 malloc(), calloc() 등으로 할당 받은 메모리
Stack 임시 변수가 저장되는 영역 읽기 쓰기 지역 변수, 함수의 인자 등

* Stack의 경우 NX 보호기법이 없을 경우 실행 권한도 갖고 있는 경우가 있음

 

 

동기부여

왜 이걸 자세히 알아야할까?

컴퓨터는 CPU, 메모리로 구성되어있고, 작성한 코드를 실행시키기 위해 메모리에 적재, CPU에서는 메모리에 있는 데이터를 처리합니다.  

 

그러면 얼마나 자세히 알고 있어야할까?

일반 컴퓨터 사이언스를 공부하는 친구들은 아래 사진을 직접 그릴 수 있을 정도로 알고 있으면 될 거 같습니다.
공격자는 어떠한 경우 메모리를 악의적으로 조작할 수 있는데 이 경우 여러 취약점들이 시스템 해킹으로 이루어질 수 있습니다. 우리가 PWNABLE을 더 쉽고 빠르게 익히기 위해선 직접 동적분석을 하는걸 추천드립니다.

 

 

자 그러면 아주 쉽고 빠르게 익혀보자. 핵심만 읽으면 됩니다.

 

인터넷엔 높은 주소, 낮은 주소 거꾸로된 사진들이 많이 돌아다녀서 그냥 2개를 만들었다. 편한거로 외우자.

 

자 실제로 이런지 확인해볼까?

(해당 실행파일은 PIE가 제거되었으므로 code의 시작부분이 고정되어있다.)

 

 

단순히 생각해보자. 우리가 작성된 코드를 실행시키려면

1. 코드가 메모리에 올라가야한다.

2. 코드에서 동작되는 정보들을 저장하는 곳이 있어야한다.

3. 코드를 실행하는데 중간 정보들을 저장하는 곳이 있어야한다.

 

 

 

Code Segment = Text Segment

코드(텍스트) 세그먼트는 실행 가능한 기계 코드를 담고 있다.

왼쪽은 특정 프로그램에 OBJDUMP한 결과이고 오른쪽은 실제로 돌아가는 프로그램의 Code Segment 부분이다.

이렇게 코드 세그먼트는 코드를 실행할 수 있게 메모리에 올라간다.

중요한건 코드를 메모리에서 실행해야하므로 읽기 권한과 실행 권한이 부여된다. 쓰기 권한은 제거된다.

 

 

 

 

 

Data Segment

데이터 세그먼트는 컴파일 시점에 값이 정해진 전역 변수 및 전역 상수들이 위치한다. 

 

데이터 세그먼트는 읽기만 가능한 세그먼트 (RODATA), 읽기/쓰기가 가능한 세그먼트 (data)로 나누어진다.

권한을 자세히 보자

RODATA는 사진을 못 찍었지만, mutable한 data_num, data_rwstr 등이 data segment 범위에 있는걸 확인할 수 있다.

 

 

 

 

 

BSS Segment

BSS(Block Started By Symbol Segment) 세그먼트는 컴파일 시점에 값이 정해지지 않은 전역 변수가 위치한 메모리 영역이다. data segment의 mutable한 영역과 같이 읽기/쓰기 권한이있다.

bss 또한 data section 주소 범위에 있음을 확인할 수 있다.

 

 

 

 

Stack Segment

함수 호출과 관계되는 지역 변수, 매개변수가 저장되는 영역이다. 값을 읽고 쓸 수 있어야 하므로 읽기/쓰기 권한이 부여된다. 하지만 사진을 보면 실행권한까지 있는걸 볼 수 있는데, 이건 No-eXecute(NX)라는 보호기법을 꺼놨기 때문에 그렇다.

스택 영역에 저장되는 함수의 정보를 Stack Frame이라고 한다.

stack의 주소를 출력하는 프로그램을 동적분석해보면 STACK 주소영역 (노란색) 부분에 값을 확인할 수 있다.

 

 

 

 

Heap Segment

힙 데이터가 위치하는 세그먼트이다. 일반적으로 읽기/쓰기 권한 부여

 

프로그램이 실행 중 동적 할당이 되면 segment가 생긴다.

31337 (0x7a69)가 Heap segment에 저장된걸 확인할 수 있다.

 

heap segment는 프로그램 처음 시작시 할당되지 않다가, 할당 이후로 생기는걸 확인할 수 있다.

 

 

 

 

Heap & Stack Segment 주의점

Heap과 Stack은 서로 반대 방향으로 자란다.

Heap은 낮은 주소에서 높은 주소로, 스택은 거꾸로 높은 주소에서 낮은 주소로 자라는걸 확인할 수 있다.

두 세그먼트가 동일한 방향으로 자라면, Heap Segment와 Stack Segment는 충돌할 수 있다.
간단히 Stack은 끝에서 시작부분으로, Stack은 시작에서 끝 부분으로 서로 마주보고 반대로 자라게 하면 최대한 자유롭게 확장이 가능하며 충돌 문제로부터 자유롭다.