본문 바로가기

[+] Information/[-] System

Windows OS의 구조 및 원리 - 프로세스

Windows 에서는 실행중인 프로그램을 프로세스라고 부른다. 프로세스는 두가지의 의미 또는 단위로 사용 된다.


 - 자원 소유의 단위(의미) : 프로세스는 Memory에 독자적인 영역을 가지고 있으며 실행 이미지 로더와 I/O 장치도 독자적으로 할당 받아야 한다.


 - Dispatching 단위(의미) : 프로세스는 CPU의 자원을 일정기간 동안 할당 받아 명령어를 실행해야 하며 OS는 병렬 명령처리를 위해 CPU의 사용시간을 각 프로세스들에게 골고루 나누어 주어야 한다.



Windows 에서 프로세스는 여러가지 구조체들로 관리되고 이루어진다. 그 중 중요한 구조체와 멤버들에 대해서 알아보도록 하겠다. Windows Kernel에서는 EPROCESS 구조체를 사용 해 kernel Memory의 프로세스를 구조화 한다. EPROCESS 중에서 중요한 멤버들은 다음과 같다.


 - unit32 DirectoryTableBase[2] : 프로세스 별로 가지고 있는 가상 Memory의 CR3 레지스터 값을 저장하고 있다.


 - struct _LIST_ENTRY ThreadListHead : 프로세스가 가지고 있는 쓰레드 목록을 가지고 있는 멤버이다.


 - void *UniqueProcessId : 프로세스의 고유 번호를 가지고 있는 멤버이다.


 - struct _LIST_ENTRY ActiveProcessLinks, *Flink, *Blink : 프로세스 목록을 관리하는 멤버들이다.


 - unit32 WorkingSetSize : 프로세스의 워킹셋 크기를 가지고 있는 멤버이다.


 - struct _HANDLE_TABLE *ObjectTable : 프로세스의 핸들 주소를 가지고 있는 테이블이다.


 - void *VadRoot : 프로세스에 할당되어 있는 모든 User Memory 영역을 설명하는 VAD 포인터이다.


 - byte ImageFileName[16] : 프로세스의 이름을 가지고 있는 멤버이다.


 * 참고 : VAD란 자체 밸런싱 바이너리 트리를 말하는데 이는 특정 노드의 왼쪽은 특정 노드 보다 낮은 값의 노드, 오른쪽은 특정 노드보다 높은 값의 노드로 이루어져 있는 트리를 말한다. 좀 더 자세히 VAD를 알고 싶다면 'A porcess-eye view of Physical Memory(Brendan Dolan-Gavitt)' 문서를 참고하기 바란다.


프로그램에서 실행 중인 프로세스의 목록을 얻어오려면 NTDLL.dll 파일에 존재하는 ZwQuerySystemInformation() API를 사용하면 된다. 자세한 사용법과 설명은 여기를 참조하기 바란다.

또 프로그램에서 현재 프로세스의 EPROCESS 정보를 얻고 싶다면 Windows Device Development Kit의 PsGetCurrentProcess() 함수를 사용하면 된다. 사용법은 여기를 참고하기 바란다.

마지막으로 다른 프로세스의 EPROCESS 정보를 얻고 싶다면 PsLookupProcessByProcessId() 함수를 사용하면 된다. 사용법은 여기를 참고하기 바란다.


프로세스의 구성요소를 한번 살펴보자. 프로세스는 독립적인 Memory 공간을 가지고 있는데 이 메모리 공간은 paging 기법을 사용해 프로세스마다 별도의 고유한 Memory 공간을 갖는 공간을 말한다. 또 VAD를 이용해 프로세스 별로 메모리와 파일을 VAD에 맵핑해 User Memory를 관리하며 Handle Table, Handle, Windows Kernel 객체, PEB가 프로세스의 구성요소로 자리잡고 있다.

Handle Table은 프로세스가 사용하는 핸들의 주소를 가지고 있는 배열 공간을 의미하며 Handle은 프로세스가 사용하는 핸들 주소를 가지고 있다. 이 값을 인덱스 값으로 HandleTable을 검색한다. Windows Kernel 객체는 Windows에서 커널 리소스들을 객체화 해 프로세스들이 공통적인 요소를 독립적으로 사용 할 수 있게끔 해 놓은 것으로 프로세스 구성의 한 부분이다. PEB(Process Environment Block)은 Kernel Level의 프로세스 관리 구조체인 EPROCESS와는 달리 User Level에서의 프로세스 추가적인 정보를 저장하고 있는 구조체이다. 자주 참조하는 정보를 PEB에 저장해 둠으로 불필요하게 Kernel Level 진입을 최소화 하는데 그 목적이 있다. PEB 구조체의 주요 내용은 다음과 같다.


 - Ldr : Ptr32 _PEB_LDR_DATA -> 프로세스에 로드 된 모듈들의 리스트를 가지고 있다.


 - ReadOnlySharedMemoryBase : Ptr32 Void -> 읽기 전용 메모리 공유 멤버이다.


 - AnsiCodePageData : Ptr32 Void -> 읽기 전용 메모리 공유 멤버의 ANSI Code Page Table이다.


 - LoaderLock : Ptre32 Void -> PE Loader가 프로세스 로딩 중 사용하는 잠금 변수이다.