본문 바로가기
시스템해킹

Syetem Hacking - [02] Computer Science - (1) Linux Memory Lauout

by minpiter 2022. 11. 30.
반응형

CONTENTS

 

1. 컴퓨터 구조와 메모리 오염

2. 리눅스 메모리 구조
 2-1. 코드 세그먼트
 2-2. 데이터 세그먼트
 2-3. BSS 세그먼트
 2-4. 힙 세그먼트
 2-5. 스택 세그먼트

3. 요약

 

 

 

 


 

 

 

 

1. 컴퓨터 구조와 메모리 오염

 

[컴퓨터 = CPU + 메모리]

 ▷공격자가 메모리를 조작하면, 조작된 메모 값에 의해 CPU도 잘못 동작

 ▷ 이러한 메모리 오염을 유발하는 취약점을 '메모리 오염(Memory Corruption)' 취약점이라고 한다

 

※ 메모리 오염과 관련된 취약점으로 다음과 같다

 ① Stack Buffer Overflow

 ② Off by One

 ③ Format String Bug

 ④ Double Free Bug

 ⑤ Use After Free

 

 

 


 

 

 

 

2. 리눅스 메모리 구조(Memory Layout)

 

 

 

 2-1. 세그먼트란

  - 리눅스에서는 프로세스의 메모리를 크게 5가지의 세그먼트(Segment)로 구분

  ▷ 코드 세그먼트, 데이터 세그먼트, BSS 세그먼트, 힙 세그먼트, 스택 세그먼트

  - 용도별로 나눈 세그먼트 별로 권한(읽기, 쓰기, 실행)을 각각 부여하여 관리 가능

 


 

 2-2. 코드 세그먼트(Code Segment)

  - 실행 가능한 기계코드가 위치하는 영역

  - 텍스트 세그먼트(Text Segment)라고도 불림

  - 이 세그먼트에는 읽기 권한과 실행 권한이 부여

  - 쓰기 권한이 있을 경우, 공격자가 코드를 삽입하여 공격할 수 있으므로 제거

int main() { return 31337; }

// 정수 '31337'을 반환하는 main함수가 컴파일 되면
// '554889e5b8697a00005dc3'이라는 기계코드로 변환되는데
// 이 기계코드가 코드 세그먼트에 위치한다

 


 

 2-3. 데이터 세그먼트(Data Segment)

  - 컴파일 시점에 값이 정해진 전역 변수 및 전역 상수들이 위치

  - CPU가 이 세그먼트의 데이터를 읽어야하므로 읽기 권한이 부여

 

 ▷ 데이터 세그먼트는 쓰기가 가능한 세그먼트와 쓰기가 불가능한 세그먼트로 아래와 같이 분류 된다.

쓰기가 가능한 세그먼트 쓰기가 불가능한 세그먼트
전역 변수와 같이 프로그램이 실행되면서 값이 변할 수 있는 데이터들이 위치 프로그램이 실행되면서 값이 변하면 안되는 데이터들이
위치하며, 전역으로 선언된 상수가 여기에 포함
data 세그먼트 rodata(read-only data) 세그먼트

 

 ▷아래는 데이터 세그먼트에 포함되는 여러 데이터의 유형이다

   - 변수 str_ptr은 "readonly"라는 문자열을 가리킨다

   - 이 문자열은 상수 문자열로 취급되어 rodata에 위치

   - 이를 가리키는 str_ptr은 전역 변수로서 data에 위치

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() { ... }

 


 

 2-4. BSS 세그먼트(BSS Segment, Block Started By Symbol Segment)

  - 컴파일 시점에 값이 정해지지 않은 전역 변수가 위치하는 메모리 영역

  - 프로그램이시작될 때, 모두 0으로 값이 초기화

  - 이 세그먼트에는 읽기 권한 및 쓰기 권한이 부여

 

  ▷ 아래 코드에서 초기화되지 않은 전역 변수인 bss_data가 BSS 세그먼트에 위치

int bss_data;

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

 


 

 2-5. 힙 세그먼트(Heap Segment)

  - 힙 데이터가 위치하는 세그먼트

  - 스택과 마찬가지고 실행중에 동적으로 할당될 수 있으며, 리눅스에서는 스택 세그먼트와 반대 방향으로 자란다

  - C언어에서 malloc(), calloc() 등을 호출해서 할당받는 메모리가 이 세그먼트에 위치하게 되며, 일반적으로 읽기 권한과 쓰기 권한이 부여

 

  ▷ 아래 코드는 heap_data_ptr에 malloc()으로 동적 할당한 영역의 주소를 대입이 영역에 값을 작성.

       heap_data_ptr은 지역변수이므로 스택에 위치하며, malloc으로 할당받은 힙 세그먼트의 주소를 가리킨다.

int main() {
  int *heap_data_ptr = 
      malloc(sizeof(*heap_data_ptr));    // 동적 할당한 힙 영역의 주소를 가리킵
  *heap_data_ptr = 31337;                // 힙 영역에 값을 씀
  printf("%d\n", *heap_data_ptr);        // 힙 영역의 값을 사용함
  return 0;
}

 


 

 2-6. 스택 세그먼트(Stack Segment)

  - 프로세스의 스택이 위치하는 영역으로 함수의 인자나 지역 변수와 같은 임시 변수들이 실행중에 이곳에 저장된다

  - 스택 세그먼트는 스택 프레임(Stack Frame)이라는 단위로 사용

  - 이 영역에는 CPU가 자유롭게 값을 읽고 쓸 수 있어야 하므로, 읽기 권한과 쓰기 권한이 부여

 

  ▷ 아래의 코드에서는 지역변수 choice가 스택에 저장된다

Voide func() {
  int choice = 0;
  
  scanf("%d", &choice);
  
  if (choice)
    call_true();
  else
    call_calse();
    
  return 0;
}

 

 


 

 

3. 요약

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

※ 이 게시글은 DREAMHACK 사이트 강의를 참조하여 작성되었습니다.

반응형