tmxklab

윈도우 프로세스(프로세스 관련) 본문

OS/03 Windows

윈도우 프로세스(프로세스 관련)

tmxk4221 2021. 4. 28. 15:14

윈도우 OS는 객체 기반이며 여기서 말하는 객체는 프로세스, 파일, 디바이스 등과 같은 시스템 리소스를 참조하고, 커널 컴포넌트인 객체관리자(object manager)에서 관리한다. MS에서 제공하는 WinObj툴을 통해 윈도우의 모든 객체 유형을 살펴 볼 수 있다.

 

[ WinObj ]

 

WinObj - Windows Sysinternals

The ultimate Object Manager namespace viewer is here.

docs.microsoft.com

관리자 권한으로 실행하고 왼쪽 탭에 ObjectTypes를 누르면 모든 윈도우 객체가 표시되는데, 이 때, Process도 객체임을 확인할 수 있다.

 

따라서, 프로세스도 객체로 관리되며 여기서 객체는 _EPROCESS구조체로 표현된다. 

 

[ _EPROCESS구조체 ]

  • 커널 메모리에 상주
  • 커널에서 프로세스를 관리하기 위한 오브젝트
  • 프로세스 이름, PID, PPID, 생성 시간 등 프로세스 관련하여 다양한 정보 나타냄

이제, 커널 디버거인 WinDbgLiveKD유틸리티를 사용하여 _EPROCESS구조체를 살펴보자

참고로 _EPROCESS는 커널 메모리에 상주하므로 LiveKD를 사용하여 운영중인 시스템에서 커널 디버깅 수행할 수 있도록 도와준다.

 

다음 링크에서 LiveKD를 다운받자

 

LiveKd - Windows Sysinternals

Use Microsoft kernel debuggers to examine a live system.

docs.microsoft.com

 

압축을 풀면 각각 x86, x64 2개씩 LiveKD.exe가 존재하는데 요거를 WinDbg 설치 디렉토리에 넣어주면 된다.

(그냥 WinDbg.exe와 같은 디렉토리에 넣어주면됨)

 

그리고 관리자 권한으로 cmd창을 열어서 livekd64.exe가 있는 경로에서 "livekd64.exe -w"를 입력하자

(이렇게 하기 귀찮으면 환경변수로 livekd64.exe 추가해줘도 됨)

Agree

 

하고 나면 조금 있다가 WinDbg가 뜬다.

 

이제 하단에 kd>명령프롬프트 창에 다음과 같이 입력하여 _EPROCESS의 구조체를 확인해보자

멤버 변수가 엄청 많은데 위에 6개 필드를 제외하고 나머지는 생략했다.

  • UniqueProcessId : PID를 참조하는 정수
  • ActiveProcessLinks : 시스템에 실행 중인 모든 활성 프로세스를 연결하는 Double Linked List(사실 이게 제일 중요함)
  • InheritedFromUniqueProcessId : PPID(부모 프로세스 ID)
  • ImageFileName : 프로세스 실행 파일 이름 16자리 ASCII 문자 배열
  • CreteTime : 프로세스 생성 타임 스탬프
  • ExitTime : 프로세스 종료 타임 스탬프

 

이제 "!process 0 0"명령어를 통해 모든 프로세스의 메타데이터를 출력해보자

  • 첫 번째 0 : 모든 프로세스의 메타 데이터 나열
  • 두 번째 0 : 상세 수준 지정 

위에서 smss.exe를 살펴보자 (smss.exe는 Windows의 모든 사용자 세션 시작을 관리하는 파일) 

  • [ ffffdb864d8eb040 ] : smss.exe 인스턴스와 연결된 _EPROCESS 구조체 주소
  • [ Cid: 01ac ] : PID 값
  • [ ParentCid: 0004 ] : PPID 값

_EPROCESS구조체의 주소를 알 수 있다면 다음과 같이 해당 프로세스에 대한 _EPROCESS구조체의 멤버 값을 알 수 있다.

앞서 "!process 0 0"명령어를 통해 확인한 smss.exe의 값과 일치하는 것을 확인할 수 있다.

 

그럼 이제 어떻게 시스템에 실행 중인 모든 프로세스의 정보를 얻는지 살펴보자

 


윈도우는 _EPROCESS 구조체의 순환 Double Linked List를 사용해 모든 프로세스를 추적할 수 있다. _EPROCESS 구조체는 LIST_ENTRY 유형의 ActiveProcessLinks라고 불리는 필드를 포함한다.

 

다음 그림에서는 LIST_ENTRY구조체가 FlinkBlink라는 2개의 멤버변수를 포함하는 것을 확인할 수 있다.

  • Flink(foward link) : 다음 _EPROCESS 구조체의 _LIST_ENTRY를 가리킴
  • Blink(backward link) : 이전 _EPROCESS 구조체의 _LIST_ENTRY를 가리킴

짐작할 수 있듯이 위 2개의 멤버를 통해 모든 프로세스는 순환 Double Linked List를 구성할 수 있다.

앞서 말했듯이 Flink와 Blink는 _EPROCESS 구조체의 시작점을 가리키는 것이 아니라 다음 또는 이전 _EPROCESS 구조체의 _LIST_ENTRY를 가리킨다. 시작점을 가리키지 않고 _LIST_ENTRY를 가리킴으로써 앞으로 또는 뒤로 이동할 수 있고 오프셋 값을 통해 찾고자 하는 프로세스의 _EPROCESS 구조체의 시작점을 알 수 있다.

 

다음 명령어를 통해 smss.exe의 ActiveProcessLinks인자에 Flink와 Blink를 확인해보자

  • Flink : 0xffffdb864f20e4c8
  • Blink : 0xffffdb864a3df488

Flink나 Blink의 값에서 ActiveProcessLinks의 offset(0x448)을 빼주면은 다음 프로세스 또는 이전 프로세스를 찾을 수 있다. 예를 들어 Blink를 통해서 이전 프로세스를 확인할 때 다음과 같이 작성하면된다.

위 결과를 통해 smss.exe의 이전 프로세스는 Registry임을 알 수 있다. 

(여기서 눈치챘다면 위에서 !process 0 0에서 출력된 프로세스 3개에서 Registry가 출력되고 smss.exe가 출력되었다.)

 


정리하자면 윈도우 OS에서 프로세스는 객체로 관리되고 여기서 말하는 객체는 EPROCESS의 구조체 형식을 말한다. 각 프로세스마다 EPROCESS구조체로 프로세스 관련 정보들이 담겨져 있는데 EPROCESS구조체에는 Flink와 Blink멤버 변수가 포함된 _LIST_ENTRY유형의 ActiveProcessLinks필드가 존재한다. ActiveProcessLinks필드를 통해 모든 프로세스들은 순환되어 있는 Double Linked List구조로 이뤄져있고 특정 프로세스를 통해서 모든 프로세스를 탐색할 수 있다.

 

+) volatility에서 pslist 플러그인은 위에서 봤듯이 메모리 이미지에서 Double Linked List를 통해 탐색하는 로직을 가진다. 이를 위해 pslist는 _EPROCESS 구조체의 Double Linked List의 시작을 나타내며 ntoskrnl.exe에 정의되어 있는 _PsActiveProcessHead라는 심볼을 찾는다. 이후에 Double Linked List를 탐색해 실행 중인 모든 프로세스를 나열한다.

 

'OS > 03 Windows' 카테고리의 다른 글

I/O 관련 작업(Device Driver, I/O Manager)  (2) 2021.05.07
Window API 호출 흐름  (0) 2021.04.19
Comments