[시스템 아키텍처] 핵심 시스템 컴포넌트 - 2
[시스템 아키텍처] 핵심 시스템 컴포넌트 - 2
커널
- 커널은 기본 메커니즘을 제공하는
ntoskrnl.exe내의 함수 집합으로 구성된다.- 이들 함수에는 익스큐티브 컴포넌트에 의해 사용되는 스레드 스케줄링과 동기화 서비스 및 각 프로세서 아키텍처별로 다른 인터럽트와 예외 디스패칭 같은 저수준 하드웨어 아키텍처 종속적인 지원이 해당된다.
- 커널 코드는 주로 C로 작성됐으며, C에서 쉽게 접근할 수 없는 특화된 프로세서 명령어와 레지스터에 대한 액세스가 요구되는 작업에는 어셈블리 코드가 사용됐다.
커널 객체
- 커널은 익스큐티브의 상위 레벨 컴포넌트가 필요로 하는 것을 수행할 수 있게 잘 정의된 예측 가능한 OS 기반 요소(Primitive)와 메커니즘의 기반을 제공한다.
- 커널은 OS 메커니즘을 구현하고, 정책을 만드는 것을 배제함으로써 익스큐티브의 나머지 부분으로부터 커널 자체를 분리한다.
- 커널이 구현한 스레드 스케줄링과 디스패칭을 제외한 거의 모든 정책 결정은 익스큐티브에 있다.
- 커널 외부의 익스큐티브는 스레드와 여타 공유 가능한 리소스를 객체로 표현한다.
- 객체는 자신들의 조작에 필요한 객체 핸들과 자신들을 보호하기 위한 보안 점검, 그리고 생성될 때 공제하기 위한 리소스 쿼터 같은 정책 오버헤드가 요구된다.
- 커널 내에서는 커널 통제 중앙 처리를 돕고 익스큐티브 객체 생성을 지원하기 위한 커널 객체라고 하는 단순 객체 집합을 구현해 오버헤드를 제거했다.
- 대부분의 익스큐티브 레벨 객체는 커널에서 정의한 속성과 결합시킨 하나 이상의 커널 객체로 캡슐화되어 있다.
- 컨트롤 객체로 불리는 커널 객체의 한 집합은 다양한 OS 함수 제어에 대한 의미론을 확립한다. 이 집합은 APC 객체와 지연된 프로시저 호출(DPC) 객체, I/O 관리자에서 사용하는 인터럽트 객체 같은 여러 객체를 포함한다.
- 디스패처 객체로 알려진 또 다른 객체 집합은 스레드 스케줄링을 변경하거나 스레드 스케줄링에 영향을 주는 동기화 기능을 통합한다.
- 디스패처 객체는 커널 스레드와 뮤텍스, 이벤트, 커널 이벤트 페어, 세마포어, 타이머, 대기 가능 타이머를 포함한다.
- 익스큐티브는 커널 객체의 인스턴스를 생성하고 조작하고 유저 모드에 제공하기 위해 좀 더 복잡한 객체를 구축하고자 커널 함수를 사용한다.
커널 프로세서 컨트롤 영역과 컨트롤 블록
- 커널은 프로세서 컨트롤 영역(KPCR; Kernel Processor Control Region)이라고 하는 데이터 구조체를 사용하고 프로세서 한정적 데이터를 저장한다.
- KPCR은 프로세서의 인터럽트 테이블과 태스크 상태 세그먼트, 글로벌 디스크립터 테이블 같은 기본 정보를 담고 있다. 또한 ACPI 드라이버와 HAL 같은 모듈과 공유하는 인터럽트 컨트롤 상태를 담고 있다.
- KPCR에 쉽게 접근할 수 있도록 커널은 이를 가리키는 포인터를 32비트 윈도우에서
FS레지스터에 저장하고, 64비트 윈도우 시스템에서GS레지스터에 저장한다.
- KPCR은 또한 커널 프로세서 컨트롤 블록(KPRCB; Kernel PRocessor Control Block)라고 하는 내장된 데이터 구조체를 담고 있다.
- 서드파티 드라이버와 다른 내부 윈도우 커널 컴포넌트를 위해 문서화되어 있는 KPCR과 다르게 KPRCB는
ntoskrnl.exe의 커널 코드에 의해서만 사용되는 비공개 구조체이다. - 스케줄링 정보, 디스패처 데이터베이스, DPC 큐, CPU 벤더/식별자 정보, CPU와 NUMA 토폴로지, 캐시 크기, 시간 계정 정보 등의 정보를 가진다. 또한 I/O, 캐시 관리자, DPC, 메모리 관리자 등의 통계 정보를 담고 있다.
- KPRCB는 종종 메모리 접근을 최적화하기 위해 캐시 정렬된 프로세서별 구조체를 저장하기 위해 사용된다.
- 서드파티 드라이버와 다른 내부 윈도우 커널 컴포넌트를 위해 문서화되어 있는 KPCR과 다르게 KPRCB는
KPCR과 KPRCB 살펴보기
!pcr과!prcb커널 디버거 명령을 사용해 KPCR과 KPRCB의 내용을 볼 수 있다. 기본적으로는 CPU 0의 정보를 보여주며, 명령 뒤에 숫자를 추가해 CPU를 지정할 수 있다.!pcr명령은 원격 디버깅 세션에서 변경할 수 있는 현재 프로세서의 정보를 보여주며, 로컬 디버깅을 하고 있다면 CPU 번호를 지정한!pcr익스텐션을 사용해 KPCR의 주소를 구할 수 있으며, 이 주소로@$pcr을 대체한다.dt nt!_KPCR @$pcr과!prcb의 결과
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 0: kd> dt nt!_KPCR @$pcr +0x000 NtTib : _NT_TIB +0x000 GdtBase : 0xfffff800`18a2ffb0 _KGDTENTRY64 +0x008 TssBase : 0xfffff800`18a2e000 _KTSS64 +0x010 UserRsp : 0x00000034`409ffa48 +0x018 Self : 0xfffff800`15b02000 _KPCR +0x020 CurrentPrcb : 0xfffff800`15b02180 _KPRCB +0x028 LockArray : 0xfffff800`15b02870 _KSPIN_LOCK_QUEUE +0x030 Used_Self : 0x00000034`3f51a000 Void +0x038 IdtBase : 0xfffff800`18a2d000 _KIDTENTRY64 +0x040 Unused : [2] 0 +0x050 Irql : 0 '' +0x051 SecondLevelCacheAssociativity : 0xc '' +0x052 ObsoleteNumber : 0 '' +0x053 Fill0 : 0 '' +0x054 Unused0 : [3] 0 +0x060 MajorVersion : 1 +0x062 MinorVersion : 1 +0x064 StallScaleFactor : 0xbb3 +0x068 Unused1 : [3] (null) +0x080 KernelReserved : [15] 0 +0x0bc SecondLevelCacheSize : 0x1800000 +0x0c0 HalReserved : [16] 0xb2872000 +0x100 Unused2 : 0 +0x108 KdVersionBlock : (null) +0x110 Unused3 : (null) +0x118 PcrAlign1 : [24] 0 +0x180 Prcb : _KPRCB
1 2 3 4 5 6 7 80: kd> !prcb PRCB for Processor 0 at fffff80015b02180: Current IRQL -- 2 Threads-- Current fffff80016c7da40 Next 0000000000000000 Idle fffff80016c7da40 Processor Index 0 Number (0, 0) GroupSetMember 1 Interrupt Count -- 00018034 Times -- Dpc 0000000b Interrupt 00000008 Kernel 0000070b User 00000073dt명령을 사용해_KPRCB데이터 구조체를 직접 덤프할 수 있다. 예를 들어 부트 시점에 탐지되는 프로세서의 속도를 알고 싶다면 다음 명령으로MHz필드를 살펴보면 된다.
1 2 3 4 0: kd> dt nt!_KPRCB fffff80015b02180 MHz +0x044 MHz : 0xbb3 0: kd> ? bb3 Evaluate expression: 2995 = 00000000`00000bb3
하드웨어 지원
- 커널의 다른 주요 임무는 윈도우에 의해 지원되는 하드웨어 아키텍처 간의 차이점으로부터 익스큐티브와 디바이스 드라이버를 추상화하거나 격리시키는 것이다.
- 커널은 이식 가능하고 모든 아키텍처에서 의미상 동일한 인터페이스 집합을 제공하며, 이들 이식 가능한 인터페이스를 구현한 대부분의 코드는 모든 아키텍처에서 동일하다.
- 인터페이스 중 일부는 아키텍처별로 다르게 구현되어 있으며, 일부 인터페이스는 부분적으로 아키텍처 한정적인 코드가 구현되어 있다.
- 커널은 오래된 16비트 MS-DOS 프로그램을 지원할 필요로 인해 x86 한정적인 인터페이스 코드를 일부 가진다.
- 아키텍처 한정적인 코드의 또 다른 예는 변환 버퍼와 CPU 캐시 지원을 제공하기 위한 인터페이스이다. 이는 캐시가 구현된 방법 때문에 아키텍처별로 다른 코드를 필요로 한다.
- 다른 예는 컨텍스트 전환이다. 고수준에서는 스레드 선택과 컨텍스트 전환을 위해 같은 알고리즘이 사용됐지만, 프로세서별 구현에는 아키텍처적인 차이가 있다. 컨텍스트가 프로세서 상태에 의해 기술되기 때문에 아키텍처별로 무엇이 저장되고 로드될지 달라진다.
하드웨어 추상화 계층(HAL)
- 하드웨어 추상화 계층은 이식성을 가능하게 하는 핵심 부분으로, 윈도우가 실행 중인 하드웨어 플랫폼에 대한 저수준 인터페이스를 제공하는 로드 가능한 커널 모듈(
hal.dll)이다.- I/O 인터페이스와 인터럽트 컨트롤러, 멀티프로세서 통신 메커니즘 같은 하드웨어 의존적인 세부 사항을 감춘다.
- 모든 함수는 아키텍처 한정적이고 머신에 의존적이다.
- 윈도우 내부 컴포넌트는 플랫폼 의존적인 정보가 필요할 때 하드웨어를 직접 액세스하는 것보다 사용자가 작성한 드라이버와 마찬가지로 HAL 루틴을 호출함으로써 이식성을 유지한다.
- x86 윈도우에는 다음과 같은 HAL이 포함되어 있다.
halacpi.dll: 고급 구성 및 전원 인터페이스. APIC 지원이 없는 단일 프로세서 머신halmacpi.dll: ACPI가 있는 고급 프로그램 가능 인터럽트 컨트롤러
- x64와 ARM 머신에서는
hal.dll이라는 하나의 HAL 이미지만 존재한다. x64 머신 프로세서가 ACPI와 APIC 지원을 필요로 하여 모든 x64 머신이 같은 마더보드 구성을 가지게 되었기 때문이다.
디바이스 드라이버
- 디바이스 드라이버는 로드 가능한 커널 모드 모듈(
.sys)로 I/O 관리자와 관련 하드웨어 사이를 인터페이스로 연결한다. 다음과 같은 세 가지 컨텍스트 중 하나로 커널 모드에서 동작한다.- I/O 함수를 호출한 유저 스레드 컨텍스트
- 커널 모드 시스템 스레드 컨텍스트(PnP 관리자로부터의 요청 등)
- 인터럽트의 결과로서 어떤 특정한 스레드의 컨텍스트가 아닌 인터럽트가 발생할 때 그 시점의 스레드 컨텍스트
- 윈도우의 디바이스 드라이버는 하드웨어를 직접 조작하지 않는다. 대신 하드웨어와 통신하기 위해 HAL 내의 함수를 호출한다.
- 드라이버는 보통 C(때로 C++)로 작성되어 있다. 그러므로 HAL 루틴을 적절히 사용해 윈도우가 지원하는 CPU 아키텍처 사이에서 소스코드 이식성을 가질 수 있고, 아키텍처 계열에서 바이너리 이식성을 가질 수 있다.
디바이스 드라이버의 유형
- 하드웨어 디바이스 드라이버
- 물리적 디바이스나 네트워크로부터 입력을 읽어 들이거나 출력을 쓰기 위해 하드웨어를 조작하는 데 HAL을 사용한다.
- 버스 드라이버와 휴먼 인터페이스 드라이버, 대용량 스토리지 드라이버 등과 같이 많은 유형의 하드웨어 디바이스 드라이버가 있다.
- 파일 시스템 드라이버
- 파일 지향적인 I/O 요청을 받아들이고 특정 장치로 I/O 요청을 보내는 윈도우 드라이버이다.
- 프로토콜 드라이버
- TCP/IP, NetBEUI, IPX/SPX 같은 네트워크 프로토콜을 구현한다.
- 커널 스트리밍 필터 드라이버
- 오디오와 비디오 레코딩, 디스플레이 같은 데이터 스트림 상에서의 시그널 처리를 수행하기 위해 함께 연결되어 있다.
- 소프트웨어 드라이버
- 일부 유저 모드 프로세스를 대신해 커널 모드에서만 이뤄질 수 있는 동작을 수행하는 커널 모듈이다.
- Sysinternals 등의 많은 유틸리티가 정보를 수집하거나 유저 모드 API로는 수행이 불가능한 작업을 하기 위해 드라이버를 사용한다.
- 파일 시스템 필터 드라이버, 네트워크 리디렉터와 서버 등
윈도우 드라이버 모델
- WDM(Windows Driver Model)의 관점으로 볼때 세 가지 종류의 드라이버가 있다.
- 버스 드라이버: 버스 컨트롤러나 어댑터, 브리지, 자식 디바이스를 가진 디바이스에 서비스를 제공
- 펑션 드라이버: 메인 디바이스 드라이버로서 디바이스에 대한 동작 인터페이스를 제공
- 필터 드라이버: 디바이스나 기존 드라이버에 기능을 추가하거나 다른 드라이버로부터의 I/O 요청이나 응답을 수정하기 위해 사용
- WDM 드라이버 환경에서는 단일 드라이버가 디바이스의 모든 면을 제어하지 않는다. 펑션 드라이버가 디바이스를 조작하고, 버스 디바이스는 버스상의 디바이스를 PnP 관리자에 복로하는 작업에 관여한다.
- 대부분의 경우 저수준 필터 드라이버는 디바이스 하드웨어의 행위를 수정한다. 실제로 16개의 I/O 포트를 필요로 하는 디바이스가 버스 드라이버에게 4개의 I/O 포트가 필요하다고 보고하면 하위 레벨의 디바이스 펑션 필터 드라이버는 버스 드라이버로부터 PnP 관리자에게 보고되는 하드웨어 리소스 목록을 가로채 I/O 포트의 개수를 갱신할 수 있다.
- 상위 레벨 필터 드라이버는 보통 디바이스에 가치를 더하는 기능을 제공한다. 어떤 디스크를 위한 상위 레벨 디바이스 필터 드라이버는 부가적인 보안 점검을 강제할 수 있다.
윈도우 드라이버 파운데이션
- WDF(Windows Driver Foundation)은 커널 모드 드라이버 프레임워크(KMDF)와 유저 모드 드라이버 프레임워크(UMDF)라는 두 가지 프레임워크를 제공해 윈도우 드라이버 개발을 단순하게 한다.
- KMDF는 WDM에 대한 단순한 인터페이스를 제공하며, 하위 버스/펑션/필터 모델을 수정하지 않고도 드라이버 작성자로부터 KMDF의 복잡성을 감춘다.
- KMDF 라이브러리는 이벤트에 응답하고 자신들이 관리하는 하드웨어 한정적이지 않은 작업을 수행하기 위해 KMDF 라이브러리를 호출할 수 있다.
- UMDF는 비디오 카메라와 MP3 플레이어, 핸드폰, 프린터 같은 어떤 클래스의 드라이버가 유저 모드 드라이버로 구현되는 것을 가능하게 한다.
- 본질적으로 유저 모드 서비스에서 각 유저 모드 드라이버를 실행한다.
- 하드웨어에 대한 실제 접근을 제공하는 커널 모드 래퍼 드라이버와 통신하기 위해 ALPC를 ㅅ하용한다.
- UMDF 드라이버가 크래시되면 프로세스가 종료되고 다시 시작되므로, 시스템이 불안정해지지 않는다.
범용 윈도우 드라이버
- 범용 윈도우 드라이버(Universal Windows Drivers)라는 용어는 윈도우 10 공통 코어에 의해 제공되는 API와 디바이스 드라이버 인터페이스를 공유하는 디바이스 드라이버를 작성하기 위한 능력을 가리킨다.
- 이들 드라이버는 특정 CPU 아키텍처에 대해 바이너리 호환 가능하며, IoT 장치에서부터 폰과 홀로렌즈, Xbox One, 노트북 및 데스크톱에 이르기까지 다양한 폼 팩터로 사용될 수 있다.
설치된 디바이스 드라이버 살펴보기
문서화되지 않은 인터페이스 자세히 보기
- 핵심 시스템 이미지(
ntoskrnl.exe,hal.dll,ntdll.dll등)에서 익스포트됐거나 글로벌 심볼에 있는 이름을 살펴보면 현재 문서화됐고 지원되고 있는 것보다 윈도우가 할 수 있는 일이 뭔가 더 있을 것이라는 생각이 든다.ntdll.dll의 함수 목록을 살펴보면 각 서브시스템이 노출하는 부분집합에 대비해 윈도우가 유저 모드 서브시스템 DLL에 제공하는 전체 시스템 서비스 목록을 알 수 있다.- 윈도우 서브시스템 DLL의 임포트 루틴을 살펴보고 이들이
ntdll.dll내의 어떤 함수를 호출하는지 조사해보는 것도 좋다.- 커널 모드 디바이스 루틴이 사용하는 익스포트된 루틴의 상당수가 문서화되어 있지만, 일부는 그렇지 않다.
- 윈도우 시스템 루틴의 명명 규칙은 다음과 같다.
<접두어><오퍼레이션><객체>
ExAllocatePoolWithTag는 Paged Pool이나 Non-Paged Pool에 할당하는 익스큐티브 지원 루틴이다.KeInitializeThread는 커널 스레드 객체를 할당하고 설정하는 루틴이다.
시스템 프로세스
- 다음의 시스템 프로세스는 모두 윈도우 10 시스템에 존재한다.
- 유휴 프로세스
- 시스템 프로세스와 안전한 시스템 프로세스, 메모리 압축 프로세스: 유저 모드 실행 파일을 실행하지 않는다는 점에서 완전한 프로세스가 아니며, 최소 프로세스로 불린다.
- 세션 관리자(
smss.exe), 윈도우 서브시스템(csrss.exe), 세션 0 초기화(wininit.exe), 로그온 프로세스(winlogon.exe) - 서비스 컨트롤 관리자(
services.exe, 생성한 자식 서비스 프로세스(svchost.exe등)) - 로컬 보안 인증 서비스(
lsass.exe,lsaiso.exe)
- 이들 프로세스의 연관 관계를 이해하기 위해 프로세스 간의 부모/자식 관계를 나타내는 프로세스 트리를 ProcMon으로 볼 수 있다.

시스템 유휴 프로세스
- 유휴 프로세스는 실제 유저 모드 이미지를 실행하지 않으며, 유휴 시간을 처리한다.
시스템 프로세스와 시스템 스레드
- 시스템 프로세스(PID 4)는 커널 모드에서만 동작하는 특별한 스레드의 집과 같은 곳이다.
- 시스템 스레드는 일반 유저 모드 스레드의 모든 속성과 컨텍스트를 가진다. 그러나
ntoskrnl.exe나 다른 어떤 로드된 디바이스 드라이버든 시스템 공간에 로드된 커널 모드 실행 코드만을 동작시킨다는 것이 차이다. - 시스템 스레드는 유저 프로세스 주소 공간을 갖지 않으므로, Paged Pool이나 Non-Paged Pool과 같은 OS 메모리 힙으로부터 동적 스토리지를 할당해야만 한다.
- 시스템 스레드는
PsCreateSystemThread와IoCreateSystemThread함수에 의해 생성된다. 이들 함수는 커널 모드에서만 호출할 수 있다. - 윈도우는 다양한 디바이스 드라이버와 마찬가지로 시스템을 초기화하는 동안 I/O를 수행하거나, 객체를 대기하거나, 디바이스 폴링 같은 스레드 컨텍스트가 요구되는 동작을 수행하기 위해 시스템 스레드를 생성한다.
- 커널의 균형 세트 관리자: 스케줄링, 메모리 관리와 관련된 이벤트 구동
- 캐시 관리자: 선행 읽기나 후위 쓰기 I/O 구현
- 파일 서버 디바이스 드라이버: 네트워크로 공유된 디스크 파티션상의 파일 데이터에 대한 네트워크 I/O 요청 응답
- 플로피 드라이버: 플로피 디바이스 폴링
- 시스템 스레드는 시스템 프로세스에 의해 소유된다. 그러나 디바이스 드라이버는 어떤 프로세스에든 시스템 스레드를 생성할 수 있다.
안전한 시스템 프로세스
- 안전한 시스템 프로세스는 기술적으로 VTL 1 수준의 안전한 커널 주소 공간과 핸들, 시스템 스레드의 집에 해당한다.
- VTL 0 커널이 스케줄링과 객체 관리, 메모리 관리를 소유하고 실제로 이들은 안전한 시스템 프로세스와는 관계되지 않는다.
- 이 프로세스의 유일한 사용처는 사용자에게 VBS가 현재 동작중이라는 사실에 대한 시각적 표시를 제공하기 위함이다.
메모리 압축 프로세스
- 메모리 압축 프로세스는 특정 프로세스의 워킹셋으로부터 축출된 스탠바이 메모리에 해당하는 압축된 페이지를 저장하기 위해 자신의 유저 모드 주소공간을 이용한다.
- 안전한 시스템 프로세스와 달리 메모리 압축 프로세스는 일반적으로 흔히 볼 수 있는
SmKmStoreHelperWorker와SmStReadThread같은 다수의 시스템 스레드를 호스팅한다. 이들 두 스레드는 메모리 압축을 관리하는 저장소 관리자에 속한다. - 이 프로세스는 실제로 자신의 메모리를 유저 모드 주소 공간에 저장한다.
세션 관리자
- 세션 관리자(
smss.exe)는 시스템에서 생성되는 첫 번째 유저 모드 프로세스이다. 익스큐티브와 커널 초기화의 마지막 시기를 수행하는 커널 모드 시스템 스레드는 이 프로세스를 생성한다. smss.exe는 시작 시 자신이 첫 번째 인스턴스이거나 마스터smss.exe가 세션을 생성하기 위해 시작시킨 인스턴스인지 검사한다. 커맨드라인이 존재하면 후자에 해당한다.smss.exe는 부팅 동안 터미널 서비스 세션 생성 중 여러 인스턴스를 생성함으로써 동시에 다수의 세션을 생성할 수 있다.- 하나의 세션이 초기화를 마치면
smss.exe의 복사본이 종료되며, 최초의smss.exe만이 활성 상태로 남는다.
마스터 smss.exe의 초기화 단계
- 프로세스와 최초 스레드를 임계 상태(Critical Process/Thread)로 표시한다. 임계 상태로 표시된 프로세스나 스레드가 종료되면 윈도우는 크래시된다.
- 프로세스로 하여금 유효하지 않은 핸들 사용과 힙 손상 등의 특정 오류를 임계 상황으로 처리하게 하고, 동적 코드 실행 비활성화 미티게이션을 활성화한다.
- 프로세스의 기본 우선순위를 11로 향상시킨다.
- 시스템이 핫 프로세서 추가를 지원한다면 자동 프로세서 친화성 갱신을 활성화한다. 이 경우 새로운 세션은 추가된 프로세서를 사용할 수 있다.
- ALPC 명령과 기타 워크 아이템을 처리할 스레드 풀을 초기화한다.
- 명령을 받을
\SmApiPortALPC 포트를 생성한다. - 시스템의 NUMA 토폴로지에 대한 로컬 복사본을 초기화한다.
- 파일 재명명 동작을 동기화하기 위한
PendingRenameMutex뮤텍스를 생성한다. - 초기 프로세스 환경 블록을 생성하고 필요하다면 Safe Mode 변수를 갱신한다.
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager키의ProtectionMode값에 기반을 두고 다양한 시스템 자원에 대해 사용될 보안 디스크립터를 생성한다.HKLM\SYSTEM\CurrentControlSet\Control\Session Manager키의ObjectDirectories값에 기반을 두고\RPC Control과\Windows라는 객체 관리자 디렉터리를 생성한다.BootExecute와BootExecuteNoPnpSync,SetupExecute아래에 나열된 프로그램을 저장한다.HKLM\SYSTEM\CurrentControlSet\Control\Session Manager키의S0InitialCommand값에 나열된 프로그램 경로를 저장한다.HKLM\SYSTEM\CurrentControlSet\Control\Session Manager키에서NumberOfInitialSessions값을 읽는다.HKLM\SYSTEM\CurrentControlSet\Control\Session Manager키의PendingFileRenameOperations와PendingFileRenameOperations2아래에 나열된 파일 재명명 동작을 읽는다.HKLM\SYSTEM\CurrentControlSet\Control\Session Manager키의AllowProtectedRenames와ClearTempFiles,TempFileDirectory,DisableWpbtExecution값을 읽는다.HKLM\SYSTEM\CurrentControlSet\Control\Session Manager키의ExcludeFromKnownDllList값에서 DLLs 목록을 읽는다.HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management키의PagingFiles와ExistingPageFiles목록 값,PagefileOnOsVolume과WaitForPagingFiles구성 값 같은 페이징 파일 정보를 읽는다.HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices키에 저장된 값을 읽고 저장한다.HKLM\SYSTEM\CurrentControlSet\Control\Session Manager키에 저장된KnownDlls값 목록을 읽고 저장한다.HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment에 정의된 시스템 전역 환경 변수를 생성한다.\KnownDlls디렉터리를 생성하며,WoW64를 가진 64비트 시스템에서는\KnownDlls32디렉터리를 생성한다.- 객체 관리자 네임스페이스 내의
\Global??아래HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Dos Devices내에 정의된 장치에 대한 심볼릭 링크를 생성한다. - 객체 관리자 네임스페이스 내에
루트\Sessions디렉터리를 생성한다. - 악의적 유저 모드 애플리케이션이 서비스의 시작 전에 실행될 경우에 발생할 수 있는 스푸핑 공격으로부터 서비스 애플리케이션을 보호하기 위한 보호 메일슬롯과 네임드 파이프 프리픽스를 생성한다.
- 이전에 파싱된
BootExecute와BootExecuteNoPnpSync목록의 프로그램 부분을 실행시킨다. (기본 프로그램은autochk.exe) - 레지스트리의 나머지 부분을 초기화한다. (HKLM 소프트웨어와 SAM, 보안 하이브)
- 레지스트리에 의해 비활성화가 되지 않는다면 해당 ACPI 테이블에 등록된 윈도우 플랫폼 바이너리 테이블 바이너리를 실행한다.
- 윈도우 복구 환경의 부트가 아니라면 앞서 살펴본 레지스트리 키에 명시된 펜딩 파일 재명명 작업을 처리한다.
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management와HKLM\SYSTEM\CurrentControlSet\Control\CrashControl키에 기반을 두고 페이징 파일과 전용 덤프 파일 정보를 초기화한다.- NUMA 시스템에서 사용되는 메모리 냉각 기술에 대한 시스템 호환성을 검사한다.
- 오래된 페이징 파일을 저장하고 크래시 전용 덤프 파일을 생성하며, 이전의 크래시 정보에 기반을 두고 필요한 새로운 페이징 파일을 생성한다.
PROCESSOR_ARCHITECTURE와PROCESSOR_LEVEL,PROCESSOR_IDENTIFIER,PROCESSOR_REVISION과 같은 추가적인 동적 환경 변수를 생성한다.HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SetupExecute에 있는 프로그램을 실행시킨다.smss.exe와 교환되는 정보를 위해 자식 프로세스(예를 들면csrss.exe)와 공유하는 언네임드 세션 객체를 생성한다. 이 섹션에 대한 핸들은 상속을 통해 자식 프로세스로 전달된다.- 이전의 레지스트리 검사에서 예외로 등록된 것들은 제외하고 알려진 DLL을 열고 영구 섹션으로 매핑한다.
- 세션 생성 요청에 대응하기 위한 스레드를 생성한다.
- 세션 0(비대화식 세션)을 초기화하기 위한
smss.exe인스턴스를 생성한다. - 세션 1(대화식 세션)을 초기화하기 위한
smss.exe인스턴스를 생성한다. 레지스트리에 구성이 되어 있다면 잠재적인 미래의 사용자 로그온에 미리 대비하기 위해 추가적인 대화식 세션 용도의smss.exe인스턴스를 생성한다.smss.exe가 이들 인스턴스를 생성할 때NtCreateUserProcess에서 매번PROCESS_CREATE_NEW_SESSION플래그를 사용해 새로운 세션 ID의 명시적 생성을 요청한다. 이는 내부 메모리 관리자 함수MiSessionCreate를 호출하는 효과를 가진다. 이 함수는 필요한 커널 모드 세션 데이터 구조체(SessionObject등)를 생성하고 윈도우 서브시스템(win32k.sys)의 커널 모드 부분이 사용하느 ㄴ세션 공간 주소와 기타 세션 공간 디바이스 드라이버를 설정한다.- 이런 단계가 완료되면
smss.exe는csrss.exe의 세션 0 인스턴스에 대한 핸들을 무기한 대기한다.csrss.exe는 임계 프로세스이므로 이 대기는 결코 완료되지 않는다.
- 이런 단계가 완료되면
smss.exe의 세션 시작 인스턴스
- 세션을 위한 서브시스템 프로세스들을 생성한다. (
csrss.exe) winlogon(대화식 세션)이나 세션 0 이니셜 커맨드를 생성한다.- 이를 마지막으로 임시적인
smss.exe프로세스는 종료한다. 서브시스템 프로세스와winlogon,wininit은 부모가 없는 프로세스인 채로 유지된다.
윈도우 초기화 프로세스
wininit.exe프로세스는 다음과 같은 시스템 초기화 기능을 수행한다.- 자신과 메인 스레드를 임계 상태로 표시한다.
- 프로세스로 하여금 유효하지 않은 핸들 사용과 힙 손상 등의 특정 오류를 임계 상황으로 처리하게 한다.
- SKU가 상태 분리를 지원한다면 이에 대한 지원을 초기화한다.
- 어떤 WinLogon이 먼저 시작해야 하는지를 탐지하기 위해 WinLogon 프로세스가 사용할
Global\FirstLogonCheck라는 이벤트를 생성한다. - WinLogon 인스턴스가 사용할
BasedNamedObjects객체 관리자 디렉터리 내에WinlogonLogoff이벤트를 생성한다. 이 이벤트는 로그오프 동작이 시작될 때에 시그널된다. - 자신의 프로세스 기본 우선순위를 13으로 상승시키고 자신의 메인 스레드 우선순위는 15로 상승시킨다.
HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon키에NoDebugThread레지스트리 값으로 정기적 타이머 큐를 생성한다. 이 타이머는 커널 디버거에 의해 명시된 유저 모드 프로세스로 디버깅이 이뤄지게 한다.- 환경 변수
COMPUTERNAME에 머신 이름을 설정하고 도메인 이름과 호스트 이름 같은 TCP/IP 관련 정보를 갱신하고 구성한다. - 기본 프로파일 환경변수인
USERPROFILE과ALLUSERSPROFILE,PUBLIC,ProgramData를 설정한다. %SystemRoot%\Temp를 확장해 임시 디렉터리를 생성한다.- 세션 0이 대화식 세션이라면 폰트 로딩과 DWM을 설정한다. (이는 SKU에 따라 다름)
- 세션 0에서 실행하는 프로세스를 위한 윈도우 스테이션(Winsta0)과 두 개의 데스크톱(Winlogon, Default)으로 구성된 최초의 터미널을 생성한다.
- 로컬에 저장됐는지 또는 대화식으로 입력을 받아야 하는지에 따라 LSA 머신 암호화 키를 초기화한다.
- 서비스 컨트롤 관리자(SCM 또는
service.exe)를 생성한다. - 로컬 보안 인증 서브시스템 서비스(
lsass.exe)를 시작한다. Credential Guard가 활성화되어 있다면 격리된 LSA 트러스트릿(lsaiso.exe)을 시작한다. 이 또한 UEFI로부터 VBS 권한 설정 키를 질의해야 한다. - 셋업이 현재 펜딩 상태라면 셋업 프로그램을 시작한다. (최초 설치되는 동안에 처음 시작되는 부트이거나 주요 OS 빌드 업데이트라면)
- 시스템 종료 요청이나 앞서 언급한 시스템 프로세스 중 하나가 종료하기를 무기한 대기한다.
서비스 컨트롤 관리자
- 서비스는 대화식 로그온 없이 시스템 부트 타임에 자동으로 실행되도록 구성 가능하다는 점에서 리눅스의 데몬 프로세스 같은 것이다. 이는 수동으로 시작할 수 있다.
- 일반적으로 서비스는 특수한 조건하에서 로그인된 사용자와 상호작용할 수 있지만, 이들과 상호작용하지 않는다.
- 대부분의 서비스는 특수한 서비스 계정(SYSTEM이나 LOCAL_SERVICE 등)에서 실행하더라도 여타 서비스는 사용자 계정으로 로그인한 것과 동일한 보안 컨텍스트로 실행할 수 있다.
- 서비스 컨트롤 관리자(SCM)는 서비스 프로세스에 대한 시작과 중지, 상호작용에 대한 책임이 있는
%SystemRoot%\System32\Services.exe이미지를 실행하는 특별한 시스템 프로세스이며, 보호 프로세스이다.- 서비스 프로그램은 실제로 서비스의 성공적인 시작이나 상태 요청에 대한 응답, 일시 중지, 서비스 종료 같은 동작을 수행하기 위해 SCM과 상호작용하는 특별한 윈도우 함수를 호출하는 윈도우 이미지이다.
- 서비스는
HKLM\SYSTEM\CurrentControlSet\Services레지스트리 아래에 정의되어 있다.
- 다수의 윈도우 컴포넌트는 프린터 스풀러와 이벤트 로그, 작업 스케줄러, 다양한 네트워크 컴포넌트 같은 서비스로 구현되어 있다.
- 설치된 서비스를 나열하려면 제어판에서 관리 툴을 선택하고 서비스를 선택하거나, 시작에서
services.msc를 실행한다. - 서비스는 다른 서비스와 프로세스를 공유할 수도 있다. 항상 1대1로 대응되지 않는다.
Winlogon과 LogonUI, Userinit
- 윈도우 로그온 프로세스(
winlogon.exe)는 대화식 유저 로그온과 로그오프를 처리한다.- 사용자가 보안 주의 시퀀스(SAS; Secure Attention Sequence) 키 입력 조합을 입력할 때 유저 로그온 요청을 통지받는다. 윈도우의 기본 SAS는 Ctrl + Alt + Delete이다.
- SAS가 존재하는 이유는 이 키 입력이 유저 모드 프로그램에 의해 가로채질 수 없기 때문에 로그온 프로세스를 흉내내는 패스워드 가로채기 프로그램으로부터 사용자를 보호하기 위함이다.
- 로그온 프로세스의 식별과 인증과 인증 부분은 자격증명 제공자(Credential Providers)로 불리는 DLL을 통해 구현된다.
- 표준 윈도우 자격증명 제공자는 기본 윈도우 인증 인터페이스인 패스워드와 스마트카드를 구현한다.
- 윈도우 10은 생체 인식 자격증명 제공자(Windows Hello)를 제공한다. 그렇지만 개발자는 표준 윈도우 사용자 이름/비밀번호 방법을 대체하는 다른 식별이나 인증 메커니즘을 구현하기 위해 고유한 자격증명 제공자를 제공할 수 있다.
winlogon.exe는 시스템이 의존하고 있는 민감한 시스템 프로세스이므로 자격증명 제공자와 로그온 대화상자를 나타내기 위한 UI는logonUI.exe라고 하는winlogon.exe의 자식 프로세스 내부에서 실행된다.- 사용자가 자신들의 자격증명을 입력하거나 로그온 인터페이스를 해제할 때
logonUI.exe프로세스는 종료된다.
- 사용자가 자신들의 자격증명을 입력하거나 로그온 인터페이스를 해제할 때
winlogon.exe는 2차 인증을 수행하기 위해 필요한 부가적인 네트워크 공급자 DLL을 로드할 수 있다. 이 기능을 통해 다중 네트워크 공급자는 로그온 동안 한 번에 모든 식별과 인증 정보를 모을 수 있다.- 사용자 이름과 비밀번호가 캡처되고 나면 인증을 받기 위해 로컬 보안 인증 서비스 프로세스(
lsass.exe)로 보내진다.lsass.exe는 액티브 디렉토리나 SAM에 저장되어 있는 것과 비밀번호가 일치하는지와 같은 실제 검증을 수행하기 위해 DLL로 구 현된 적절한 인증 패키지를 호출한다. - 인증이 성공하면
lsass.exe는 사용자의 보안 프로파일을 담고 있는 접근 토큰 객체를 생성하기 위해 보안 참조 모니터(SRM)의 함수(예를 들면NtCreateToken)를 호출한다. - UAC가 사용되고 있고 로그온한 사용자가 관리자 그룹이나 관리자 특권을 가지고 있다면
lsass.exe는 두 번째 토큰의 제한된 버전을 생성한다. 이후 이 접근 토큰은 사용자의 세션에 초기 프로세스를 생성하기 위해 WinLogon에 의해 사용된다.- 초기 프로세스는
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon레지스트리 키 아래에 있는 값Userinit에 저장되어 있다. - 기본 값은
userinit.exe이며, 하나 이상의 이미지가 리스트에 있을 수 있다.
- 초기 프로세스는
userinit.exe는 사용자 환경 초기화(로그인 스크립트 실행, 네트워크 연결 재설정 등)를 수행하고, 레지스트리의Shell값을 살핀 후 시스템에 정의된 셸을 실행하기 위한 프로세스(기본값은explorer.exe)를 생성한다. 이후userinit.exe는 종료된다. 이것이 바로 탐색기의 부모가 나타나지 않는 이유다.winlogon.exe는 사용자의 로그온과 로그오프 과정뿐만 아니라 키보드로부터 SAS를 가로챌 때마다 활성화된다. 로그온돼 있을 때 Ctrl + Alt + Delete를 누르면 옵션으로 로그오프와 작업 관리자 실행, 워크스테이션 잠금, 시스템 종료 등을 제공하는 윈도우 보안 대화상자가 나타난다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.


