Home [Study] Memory Layout
Post
Cancel

[Study] Memory Layout

Memory Layout?


: 메모리 레이아웃(Memory Layout)이란 프로그램이 실행될 때 운영체제는 프로세스가 사용 가능한 가상 메모리(Virtual Memory) 공간을 할당 받는데, 이 가상 메모리의 구성을 메모리 레이아웃이라고 합니다. 프로세스가 사용할 데이터를 적절한 곳에 적재하고 구획하여, 개발자의 직관적인 이해를 돕고 구획별 적절한 권한을 부여할 수 있어 메모리 오염(Memory Corruption) 취약점을 방지할 수 있는 특징이 있습니다. 메모리 레이아웃은 운영체제마다 다른데, 여기서는 Windows와 Linux 두 OS에 대한 레이아웃을 알아보겠습니다.


💻 Windows Memory Layout


섹션

.text

: 실행 가능한 기계 코드가 위치하는 영역. 코드 영역으로도 불리는 이 영역은 제어문, 함수, 상수 들을 저장함.

  • 읽기 권한(r)과 실행 권한(x)이 부여됨
  • 쓰기 권한을 부여하면 공격자가 악의적인 코드를 삽입할 수 있기에 대부분의 운영체제는 쓰기 권한을 제거함.


.data

: 컴파일 시점에 값이 정해진 전역변수, 정적변수 들이 위치하는 영역.

  • 메인(main) 함수 전에 선언 되어 프로그램이 끝날 때까지 메모리에 남아있는 변수.
  • 읽기 권한(r)과 쓰기 권한(w)이 부여됨.


.rdata

: 컴파일 시점에 값이 정해진 전역상수와 참조할 DLL외부 함수들의 정보과 같은 임포트 데이터가 저장되는 영역.

  • 읽기 권한(r)이 부여됨.
  • 과거에는 참조할 DLL과 외부 함수들의 정보를 .idata 영역에 저장하였으나, 최근에는 .rdata에 저장하는 추세.
1
2
3
4
const char data_rostr[] = "readonly_data"; // - (1)
char *str_ptr = "readonly"; // - (2)

int main() {...}

(1) - "readonly_data" 문자열이 const에 의해 상수 문자열로 저장되었기 때문에 .rdata 영역에 저장됨.

(2) - str_ptr전역 변수이기에 .data에 위치하나, "readonly"상수 문자열로 취급되기에 .rdata 영역에 저장됨.


섹션이 아닌 메모리

Stack

: 프로세스의 각 Tread는 자신만의 스택 공간을 갖고 있는데 이 영역에는 보통 지역변수, 함수의 return address, 매개변수(함수의 인자)들이 저장됨.

  • 읽기 권한(r)과 쓰기 권한(w)이 부여됨.
  • 함수가 종료되면 해당 함수에 할당된 변수들을 해제함.
  • 높은 주소에서 낮은 주소로 메모리에 할당되기에 ‘아래로 자란다’라는 표현을 사용함.


Heap

: 사용자에 의해 관리되는 영역으로, 모든 종류의 데이터가 저장될 수 있어 여러 용도로 사용되는 영역. 비교적 스택보다 큰 데이터를 저장할 수 있으며, 전역적으로 접근이 가능함. 메모리 동적 할당으로 저장되는 데이터는 모두 힙에 저장됨.

  • 읽기 권한(r)과 쓰기 권한(w)을 가지나, 상황에 따라서 실행 권한(x)을 가지는 경우도 존재.
  • malloc(), calloc() 등으로 메모리 할당 받음.
  • 낮은 주소에서 높은 주소로 메모리에 할당되기에 ‘위로 자란다’라는 표현을 사용함.

💡 힙과 스택이 반대 방향으로 자라는 이유? -> 두 영역이 동일한 방향으로 자라면, 한 영역을 모두 사용했을 때 이를 확장하는 과정에서 다른 영역과 충돌하게 됩니다. 이를 해결하기 위해 스택을 메모리의 에 위치 시키고, 힙과 스택을 반대로 자라게 하여 메모리를 최대한 자유롭게 이용하고 충돌 문제로부터 자유롭게 됩니다.


💻 Linux Memory Layout


리눅스에서는 프로세스의 메모리를 5가지의 세그먼트(segment, 영역)로 구분합니다.

Code Segment

: 코드 세그먼트(Code Segment)텍스트 세그먼트(Text Segment)라고도 불리는데, 프로그램에서 실행 가능한 코드 데이터가 위치함. 윈도우의 .text 영역과 동일.

  • 읽기 권한(r)과 실행 권한(x)이 부여됨
  • 쓰기 권한을 부여하면 공격자가 악의적인 코드를 삽입할 수 있기에 대부분의 운영체제는 쓰기 권한을 제거함.


Data Segment

: 데이터 세그먼트(Data Segment)컴파일 시점에 값이 정해지는 전역변수전역상수들이 위치함.

  • 기본적으로 읽기 권한(r)이 부여됨.
  • 데이터 세그먼트는 읽기 권한에 추가로 쓰기 권한(w)을 부여하는지에 따라 세그먼트를 나눔.
    • data 세그먼트 : 쓰기 권한이 부여된 세그먼트로, 전역변수와 같이 프로그램이 실행되면서 값이 변할 수 있는 데이터가 위치함.
    • rodata(read-only data) 세그먼트 : 쓰기 권한이 부여되지 않은 세그먼트로, 전역상수와 같이 프로그램이 실행되면서 값이 변하면 안되는 데이터가 위치함.
1
2
3
4
5
char data_rwstr[] = "writable_data"; // - (1)
const char data_rostr[] = "readonly_data"; // - (2)
char *str_ptr = "readonly"; // - (3)

int main() {...}

(1) - data_rwstr"writable_data"을 가리키는 전역 변수이기 때문에 data 세그먼트에 저장됨.

(2) - "readonly_data" 문자열이 const에 의해 상수 문자열로 저장되었기 때문에 rodata 세그먼트에 저장됨.

(3) - str_ptr"readonly"를 가리키는 전역 변수이기에 data 세그먼트에 위치하나, "readonly"상수 문자열로 취급되기에 rodata 세그먼트에 저장됨.


BSS Segment

: BSS 세그먼트(BSS Segment, Block Started By Symbol Segment)컴파일 시점에 값이 정해지지 않는 전역 변수가 위치함.

  • 읽기 권한(r)과 쓰기 권한(w)이 부여됨.
  • 초기화하지 않은 전역변수처럼 프로그램 시작 시에 모두 0으로 값이 초기화 됨.


Stack Segment

: 프로세스에서 사용하는 스택이 위치하는 메모리 영역. 함수의 인자, 지역변수, 매개변수와 같은 임시 변수들이 프로그램 실행 중에 동적으로 할당 받아 메모리에 저장됨.

  • 읽기 권한(r)과 쓰기 권한(w)이 부여됨.
  • 높은 주소에서 낮은 주소로 메모리에 할당.


Heap Segment

: C언어에서 malloc(), calloc()와 같은 함수를 통해 프로그램 실행 중 동적으로 할당받는 메모리가 위치하는 영역.

  • 읽기 권한(r)과 쓰기 권한(w)이 부여됨.
  • 낮은 주소에서 높은 주소로 메모리에 할당.


Summary


Windows Memory Layout

섹션역할일반적인 권한사용 예
.text실행 가능한 코드가 위치하는 영역읽기/실행main() 등의 함수 코드
.data초기화된 전역변수가 위치하는 영역읽기/쓰기초기화된 전역변수, 전역상수
.rdata초기화된 전역상수임포트 데이터가 위치하는 영역읽기전역상수, 외부 함수 정보 등의 임포트 데이터
Stack Segment임시 변수가 위치하는 영역읽기/쓰기지역변수, 함수의 인자
Heap Segment사용자에 의해 실행 중에 동적으로 사용되는 영역읽기/쓰기malloc(), calloc() 등으로 할당받은 메모리

Linux Memory Layout

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

[HackCTF] Login

[Study] IDA 사용법