저번 시간에 했던 프로그램이 메모리에 적재되어 실행되는 전체적인 과정에 대해서 살펴보았다.
오늘은 실제 메모리가 어떻게 구성되는지 좀더 디테일하게 설명할것임
최종적으로는 버퍼 오버플로우를 설명할 껀데 그러기 위해서 선행되어야 하는 필수적인 개념임
메모리의 구성이 어떻게 되어 있는지 정확히 알아야 나중에 공부하기도 더욱 수월함.
시스템 마다 다르긴 하지만 오늘은 인텔 8086 메모리에 대해서 설명하겠다.
메모리 구조
저번 시간에 하드 디스크에 있는 실행파일이 실행되기 위해 메모리에 올라가는 과정을 설명 했다.
그럼 그 올라가는 메모리는 시스템 마다 다를 텐데 인텔 8086 32비트 시스템은 다음과 같이 구성되어 있다.
32비트 운영체제에서는 프로세스당 0x00000000 ~ 0xffffffff 까지 총 4기가의 영역을 가질 수 있음
그 중 프로그램에서는 유저영역인 2G를 사용 가능하다
1. 커널 영역
운영체제 시스템 코드가 로드되는 부분이 바로 커널 모드임. 예를 들면 스레드 스케줄링, 메모리 관리, 파일 시스템 코드 등이 로드됨. 이 영역은 시스템 내의 모든 프로세스에게 공유된 메모리임. 사용자는 이 영역에 직접적인 접근은 못함
2. Off-Limit 영역
사용자가 커널 영역에 접근하지 못하도록 할당 해둔 공간.
3. 유저 영역
우리가 실제로 사용할 수 있는 공간이다. 스택, 힙, 코드 영역이 여기에 포함된다
4. Null Pointer 할당 영역
모두 0이고 변경 불가능한 영역으로 시스템 보호 차원에서 만들어둔 영역이다.
예전에는 저렇게 하나의 프로세스만을 썻지만 요새는 멀티 태스킹이 가능하므로 메모리에는 여러 개의 프로세스가 저장되어 병렬적으로 작업을 수행함.
가용 메모리 영역인 유저 영역에는 여러개의 세그먼트 들이 저장 될 수 있음. 세그먼트는 하나의 프로세스를 묶은 것으로 스택, 데이터, 코드 영역으로 구성되어 있다.
유저 영역
위의 유저 영역에 들어가는 세그먼트를 자세히 살펴보면 다음과 같다. 편의를 위해 그냥 현재 세그먼트 하나가 있다고 가정하고 메모리의 커널 영역을 제외한 유저 영역의 세그먼트는 아래의 그림처럼 6개의 영역으로 나뉘어져 있다.
1. 스택 영역
프로그램에서 사용되는 각종 환경 변수, 파라미터, 리턴 값, 지역 변수 등의 정보를 담고 있다
2. 공유 라이브러리 영역
프로그램이 내부에서 사용하는 라이브러리 함수들과 관련된 공유 라이브러리 파일이 적재되는 영역
/lib/libc.so.6 등이 있다
3. 힙 영역
동적 할당되는 변수의 데이터가 위치하는 영역
malloc(), realloc(), free() 함수 같은 동적 할당과 관련되는 함수들에 의해 선언되는 동적변수가 이 곳에 위치
4. BSS 영역, 데이터 영역
프로그램에서 사용되는 전역변수, 정적 변수 등 각종 변수 들이 실제로 위치하는 메모리 영역
굳이 BSS영역과 데이터 영역으로 나눌 필요는 없지만, BSS에는 초기화 되지 않은 데이터, 초기화 된 데이터는 데이터 영역에 들어간다
5. 코드 영역
실제 실행되는 기계어 명령어들, 어셈블리 코드가 쌓이는 곳이다.
프로그램이 실행되면 코드 영역에 있는 어셈블리 코드가 한 줄씩 해석되며 실행된다
위 5개의 영역을 실제 코드와 매핑 시켜보면 다음과 같다.
다음에 이제 최종적으로 스택 영역 데이터가 어떻게 쌓이는지 버퍼 오버플로우 관점에서 설명을 하겠다.