/ POSTS

windows-0x01

0x01 윈도우 메모리

가상 메모리

x86 메모리 구조

x86 윈도우의 경우 각 프로세스 별로 최대 4GB를 지원합니다. 이 중 상위 절반(0xFFFFFFFF~0x80000000)은 OS 메모리로 사용하고(커널영역), 나머지 하위 절반(0x7FFFFFFF~0x00000000)은 프로세스가 독립적으로 사용할 수 있도록 제공합니다.(유저영역) 그림 1-1는 32비트 윈도우에 의해 지원되는 전형적인 가상 주소 공간 배치를 나타냅니다.

[그림 1-1]
[그림 1-1]

그림 1-1에서 확인하였듯이 커널 영역은 다른 프로세스와 공통으로 사용하는 구조로 되어 있습니다. 그리고 이 영역은 OS가 사용하는 아주 중요한 영역입니다. 그래서 윈도우에서는 유저 영역에서 운영체제의 데이터에 접근하거나 수정하는 것을 막기 위해 두 가지 접근 모드(커널모드, 유저모드)를 사용합니다. 유저 모드는 커널 영역에 대한 접근을 할 수가 없지만, 커널 모드는 모든 시스템 메모리와 모든 CPU 명령어 등에 대해 접근이 허가된 실행모드를 말합니다. 이렇게 함으로써, 윈도우는 운영체제 시스템 커널에 잘못된 사용자 어플리케이션이 오동작을 유발하여, 시스템 전체의 안정성을 해치지 않게 보장하고 있습니다. 표 1-1은 커널모드, 유저모드를 뜻하는 다양한 용어들에 대한 정리입니다.

모드 용어
커널 모드 커널 모드, 링 0, 커널 레벨, 슈퍼 바이저 모드
유저 모드 유저 모드, 링 3, 유저 레벨, 어플리케이션 모드
[표 1-1] 커널 모드, 유저모드 용어 정리

** 윈도우는 4가지의 특권 레벨을 정의하고 있습니다. 하지만, 단지 두 개의 레벨만을 사용하는 이유는 일부 하드웨어 구조(ARM이나 MIPS 등)에서 2가지의 특권 레벨만 구현했기 때문입니다.

x86 유저 영역 주소 공간 배치
[그림 1-2]
[그림 1-2]

그림 1-2는 우리가 중점적으로 알아볼 유저영역의 메모리 배치입니다. 위 그림에서 볼 수 있듯이, 유저 영역은 스택, 힙, 공유라이브러리, PE Image 등으로 구성되어 있습니다. 또한, 각 영역의 주소가 임의로 할당됨을 알 수 있습니다. 메모리 보호기법 중 하나인 ASLR이 적용되어 위 그림과 같이 각 영역의 주소가 임의로 할당되는 것이죠. 그럼 계산기 프로그램을 가지고 실제로 저렇게 할당되는지 살펴보겠습니다.

[그림 1-3]
[그림 1-3]

그림 1-3은 Sysinternals suites의 vmmap을 통해 살펴 본 계산기의 메모리 구조입니다. 계산기를 종료한 후 다시 실행해보면 위치 값이 이전과 다르다는 것도 확인할 수 있습니다. 또한, vmmap은 각 할당 유형에 따라 다음과 같은 요약된 형태로 보여줍니다.

  • Image : 실행 파일과 동적 라이브러리 같은 의존물, PE Image 파일을 매핑하는 데 사용되는 메모리 할당
  • Shareable : 일반적으로 공유 메모리를 포함해 공유 속성으로 설정된 메모리 할당
  • Heap : 프로세스가 소유한 힙을 위해 할당된 메모리 영역
  • Stack : 프로세스 내의 각 스레드를 위한 스택 용도로 할당된 영역
  • Private Data : 스택이나 힙을 제외한 전용 데이터(내부 데이터 구조체 등)로 표시된 메모리 영역

지금까지 윈도우 시스템의 가상 메모리 할당에 대한 대략적인 부분을 알아봤습니다. 이 글의 도입부에서 제가 각 프로세스 별로 4GB를 지원한다고 했습니다. 그런데 일반적으로 여러분들이 사용하는 PC의 RAM은 4~16GB 정도인데, 어떻게 실행하는 모든 프로세스마다 4GB를 지원할 수 있을까요?

Paging

대부분의 시스템이 프로세스 실행에 사용하는 가상 메모리의 총합보다 작은 물리 메모리를 가지고 있습니다. 그래서 윈도우의 메모리 관리자는 프로세스가 사용하는 메모리 내용의 일부를 디스크로 보냅니다. 데이터를 디스크에 전송하면서 물리 메모리의 공간을 비울 수 있고, 그 자리를 다른 프로세스가 사용할 수 있도록 지원합니다. 만약 디스크에 전송한 내용을 사용하기 위해 가상 주소를 접근할 경우, 동일한 과정을 거쳐 메모리로 정보를 다시 가져옵니다. 이런 방식으로 윈도우에서는 메모리를 관리하고 있고, 디스크로 또는 메모리로 매핑하는 데이터의 단위를 페이지라고 부르고 기본 크기는 4KB입니다. 그림 1-4은 방금 설명한 페이징을 나타냅니다.

[그림 1-4]
[그림 1-4]
공유 메모리

공유 메모리란, 프로세스와 운영체제 사이의 공통으로 사용하는 메모리를 이야기합니다. 각 프로세스는 개별 데이터를 저장하거나 실행하기 위해 자신만의 메모리 공간을 갖겠지만, 여러 프로세스에서 동일하게 사용하는 부분은 굳이 여러 번 메모리에 할당할 필요가 없습니다. 그래서 윈도우는 그림 1-5과 같이 동일한 dll이나 다른 자원을 물리 메모리로 한 번만 로딩시키고 공유해서 사용하도록 구성되어 있습니다.

[그림 1-5]
[그림 1-5]

이런 구조를 사용함으로써 메모리를 좀 더 효율적으로 사용할 수가 있게 됩니다.

윈도우 메모리 구조에 대해 중요한 기본 개념들을 살펴봤습니다. 다음 연재에서는 본격적으로 Stack의 구조와 Stack에서 일어날 수 있는 취약점들에 대해서 알아보도록 하겠습니다.