[Dreamhack] Linux Memory Layout

·2024년 1월 27일

Security

목록 보기
2/60

리눅스 프로세스의 메모리 구조

: 프로세스의 메모리를 5가지의 세그먼트로 구분

1. 세그먼트란

적재되는 데이터의 용도별로 메모리의 구획을 나눈 것

2. 코드 세그먼트

실행 가능한 기계 코드가 위치하는 영역, Text Segment

** 프로그램이 동작하기 위해선 코드를 실행할 수 있어야 함, 이 seg에는 읽기 권한과 실행권한이 부여됨, 쓰기 권한이 있을 경우 공격자가 악의적인 코드를 삽입하기 쉬워지기 때문에 현대 OS에서는 이 seg에 쓰기 권한 제거함

3. 데이터 세그먼트

컴파일 시점에 값이 정해진 전역 변수 및 전역 상수들이 위치함, CPU가 이 seg의 데이터를 읽을 수 있어야 하므로, 읽기 권한이 부여됨

a. 쓰기 가능한 세그먼트
전역 변수와 같이 프로그램이 실행되며 값이 변할 수 있는 데이터들이 위치함, data segment
b. 쓰기 불가능한 세그먼트
프로그램이 실행되면서 값이 변하면 안되는 데이터들이 위치함, 전역으로 선언된 상수 포함, rodata(read-only-data) segment
int data_num=31337; // data
char data_rwstr[]="writable_data"; // data
const char data_rostr[]="readonly_data"; //rodata
char *str_ptr="readonly"; //str_ptr은 data, 문자열은 rodata

4. BSS 세그먼트

컴파일 시점에 값이 정해지지 않은 전역 변수가 위치하는 메모리 영역, 선언만 하고 초기화하지 않은 전역변수 등이 포함
이 세그먼트의 메모리 영역은 프로그램이 시작될 때, 모두 0으로 값이 초기화되며, 이 seg에는 읽기 및 쓰기 권한 부여됨

int bss_data;
int main() {
	printf("%d\n",bss_data); // 0
    return 0;
}

5. 스택 세그먼트

프로세스의 스택이 위치하는 영역, 함수의 인자나 지역 변수와 같은 임시 변수들이 실행 중에 여기에 저장됨
스택 세그먼트는 스택 프레임(Stack Frame)이라는 단위로 사용, 스택 프레임 함수가 호출될 때 생성되고, 반환될 때 해제됨

void func() {
	int choice =0;
    scanf("%d", &choice);
    // choice에 따라 call_true()가 호출될 수도, call_false()가 호출될 수도 있음
    if(choice)
    	call_true();
    else
    	call_false();
    return 0;
}

6. 힙 세그먼트

힙 데이터가 위치하는 세그먼트, 스택과 마찬가지로 실행 중에 동적으로 할당될 수 있고, 리눅스에서는 스택 세그먼트와 반대 방향으로 자람.
C언어에서는 malloc(), calloc() 등을 호출해서 할당받는 메모리가 이 세그먼트에 위치하게 됨

int main() {
  int *heap_data_ptr =
      malloc(sizeof(*heap_data_ptr));  // 동적 할당한 힙 영역의 주소를 가리킴
  *heap_data_ptr = 31337;              // 힙 영역에 값을 씀
  printf("%d\n", *heap_data_ptr);  // 힙 영역의 값을 사용함
  return 0;
}
profile
Whatever I want | Interested in DFIR, Security, Infra, Cloud

0개의 댓글