리눅스의 메모리 구조
적재되는 데이터의 용도별로 5가지 세그먼트(segment)로 구분
- 코드 세그먼트(Code segment = Text segment): 실행 가능한 기계 코드가 위치하는 영역
- 프로그램 동작을 위해 읽기, 실행 권한 부여
- 쓰기 권한이 부여되면 공격자가 악의적인 코드를 삽입할 수 있으므로 대부분 운영체제에서 쓰기 권한 제거
int main() { return 31337; }
-> main 함수가 컴파일되면서 기계 코드로 변환되고, 이 기계 코드가 코드 세그먼트에 위치
- 데이터 세그먼트(Data segment): 컴파일 시점에 값이 정해진 전역 변수 및 전역 상수들이 위치
- CPU가 데이터를 읽어야 하므로 읽기 권한 부여
- 쓰기 권한 여부에 따라 또다시 2개의 세그먼트로 분류
- data segment: 쓰기 O, 전역 변수 같이 프로그램이 실행되면서 값이 변할 수 있는 데이터
- rodata(read-only data) segment: 쓰기 X, 값이 변하면 안되는 데이터들(전역 상수)
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
int main() { ... }
-> str_ptr의 경우 가리키는 문자열인 "readonly"는 상수 문자열로 취급됨
- BSS 세그먼트(Block Started By Symbol segment): 컴파일 시점에 값이 정해지지 않은 전역 변수가 위치하는 메모리 영역
- 개발자가 선언만 하고 초기화하지 않은 전역변수
- 프로그램이 시작될 때, 모두 0으로 초기화
- 읽기, 쓰기 권한 부여
int bss_data;
int main() {
printf("%d\n", bss_data); // 0
return 0;
}
-> C에서는 초기화되지 않은 전역 변수의 값은 0이 됨
- 스택 세그먼트(Stack segment): 프로세스 스택이 위치하는 영역, 함수 인자나 지역 변수 같은 임시 변수들이 실행 중에 저장
- 스택 프레임(Stack Frame)이라는 단위로 사용
- 스택 프레임은 함수가 호출될 때 생성, 반환될 때 해제
- 프로그램의 전체 실행 흐름은 사용자의 입력, 조건문 등의 요인에 영향을 받음
- 프로세스가 실행될 때 얼만큼의 스택 프레임을 사용할지 미리 계산하는 것은 일반적으로 불가능, 프로세스 시작 시 작은 크기의 스택 세그먼트를 먼저 할당한 후 부족할 때마다 확장
- '아래로 자란다' - 스택 확장 시 기존 주소보다 낮은 주소로 확장되기 때문
- CPU가 자유롭게 값을 읽고 쓸 수 있어야 하므로 읽기, 쓰기 권한 부여
- 힙 세그먼트(Heap segment): 힙 데이터 위치, 실행 중 동적 할당, 스택과 반대 방향으로 자람
- 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;
}
드림핵 시스템해킹 로드맵 참고
'보안' 카테고리의 다른 글
[시스템해킹] NX & ASLR (0) | 2024.04.23 |
---|---|
[시스템해킹] Background: Calling Convention(함수 호출 규약) (0) | 2024.04.23 |
[시스템해킹] Background: x86 Assembly (0) | 2024.04.23 |
[시스템해킹]Background: 컴퓨터 구조, 레지스터, ... (0) | 2024.04.22 |
[시스템해킹] 드림핵 워게임 basic_exploitation_000 (1) | 2024.04.03 |