미역줄기의 이모저모

[Dreamhack]Linux Memory Layout 본문

Hacking/DreamHack 시스템 해킹 강의

[Dreamhack]Linux Memory Layout

미역줄기줄기 2024. 2. 3. 15:39
728x90

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

 

세그먼트(Segment)

세그먼트란 적재되는 데이터의 용도별 메모리의 구획이다. 리눅스에선 프로세스의 메모리를 코드 세그먼트, 데이터 세그먼트, BSS 세그먼트, 힙 세그먼트, 스택 세그먼트 이렇게 5개로 구분한다. 

 

이런느낌

 

각 용도에 맞게 권한을 부여할 수 있다. 그럼 CPU는 메모리에 대해 권한이 부여된 행위를 한다.

 

 

코드 세그먼트

실행 가능한 기계 코드가 위치하는 영역이다. 텍스트 세그먼트라고도 불린다, 읽기와 실행 권한이 부여된다. 

쓰기권한이 없는 이유는 공격자가 악의적인 코드를 삽입하는 것을 막기 위해서이다. 

 

int main() { return 31337; }

31337을 반환하는 main함수가 컴파일 되면 31337은 기계코드로 변환되고 이것은 코드 세그먼트에 위치한다.

 

 

 

 

 

데이터 세그먼트

컴파일 시점에서 값이 정해진 전역 변수, 전역 상수들이 위치한다. 읽기 권한이 부여된다.

데이터 세그먼트에는 쓰기 권한이 허용되는 것과 허용되지 않는 세그먼트로 나눠진다, 쓰기 가능한 세그먼트는 전역 변수와 같이 실행하면 값이 변할 수 있는 데이터들이 위치한다. 이 위치를 데이터 세그먼트라고 한다. 반대로 쓰기 권한이 허용되지 않는 세그먼트에는 전역으로 선언된 전역 상수와 같이 값이 변하면 안 되는 데이터들이 위치한다. 이 위치를 rodata 세그먼트라고 한다.

 

 

 

 

 

BSS 세그먼트

컴파일 시점에 값이 정해지지 앟은 전역변수들이 위치한다. 선언만 하고 초기화하지 않은 전역변수 등이 포함된다.

이 영역의 메모리 영역은 프로그램이 시작될 때, 모두 0으로 값이 초기화된다. 읽기 권한과 쓰기 권한이 부여된다.

int bss_data;

이런 것 말이다. 물론 bss_data는 main 함수의 바깥에 있다.

 

 

 

 

 

스택 세그먼트

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

스택 프레임이라는 단위로 사용된다. 스택 프레임은 함수가 호출될 때 생성되고 반환될 때 해제된다. 이때 사용자가 입력하느 것에 따라 호출될 함수가 달라지는 경우도 있다. 그리고 그 외에도 여러 요인을 받는다. 따라서 얼마 만큼의 스택 프레임이 사용될지 예측할 수 없기 때문에 운영체제는 작은 크기의 스택 세그먼트를 할당해준다. 대신 부족해 질 때마다 확장해준다. 이때 기존 주소보다 낮은 주소로 확장된다.

 

 

 

 

 

힙 세그먼트

힙 데이터가 위치하는 세그먼트이다. 실행 중에 동적으로 할당될 수 있으며 리눅스에서는 스택 세그먼트와 반대 방향으로 확장한다. c언어에서 malloc(), calloc() 등을 호출해서 할당 받는 메모리가 이 곳에 위치한다. 읽기와 쓰기 권한이 부여된다.

 

 

 

 


Quiz

#include <stdlib.h>
int a = 0xa;
const char b[] = "d_str";
int c;
int foo(int arg) {
  int d = 0xd;
  return 0;
}
int main()
{
  int *e = malloc(sizeof(*e));
  return 0;
}

d가 위치하는 세그먼트는 어디인가?

일단 d는 foo라는 함수 안에 정의된 지역 변수이다!! 함수 내의 지역 변수는 스택 메모리에 할당된다!!

 

c가 위치하는 세그먼트는 어디인가?

c는 값이 정해지지 않았다! 그럼 BSS에 있겠다!

 

a가 위치하는 세그먼트는 어디인가?

a는 함수 바깥,, 그러니까 코드의 전역 범위에 선언되었다. 그렇다면 데이터 세그먼트에 있겠네!

 

foo가 위치하는 세그먼트는 어디인가?

foo는 함수다! 그럼 코드 세그먼트에 있겠다!

 

"d_str"이 위치하는 세그먼트는 어디인가?

일단 코드의 전역범위에 있다. 그리고 문자열 상수로 초기화된 전역 상수이기 때문에 읽기전용 데이터(rodata) 세그먼트에 위치한다!

 

b가 위치하는 세그먼트는 어디인가?

b는 전역 범위에 정의된 문자열 상수이다. 따라서 읽기 전용 데이터 세그먼트에 위치한다

 

e는 어느 세그먼트의 데이터를 가리키는가?

e는 포인터로 malloc() 함수를 사용하여 동적으로 할당된 메모리의 주소를 저장한다. 동적으로 할당된 메모리는 주로 힙 세그먼트에 위치한다. 따라서 e가 가리키는 데이터는 힙 세그먼트에 할당된 메모리 블록이다.