IT 그리고 정보보안/Knowledge base

윈도우 프로세스와 스레드 생성과 동작 원리

plummmm 2021. 4. 13. 07:10
반응형

위 그림은 위 그림은 커널 동작 과정이다.

첫 과정인 프로세스와 스레드 관련 내용을 알아본다.

 

프로세스와 스레드는 작업을 처리하는 기본 단위들이다.

 

프로세스와 스레드의 관계에 대해 짚고 넘어가면,

우리가 실제로 하는 작업을 실행하는 것이 스레드이다. 작업의 주체라 이 말.

그리고 작업의 주체인 스레드를 위해 구성된 하나의 환경을 프로세스라고 보면 된다.

 

하나의 환경 즉, 프로세스에 작업의 주체인 스레드가 각자의 역할에 맞게 구성되어 있다..

라고 정리하면 될것 같다.

 

우리가 윈도우에서 보는 프로세스는 하나의 응용 프로그램. 즉, 하나 이상인 스레드의 집합을 말한다.

 

이런 프로세스는 종류가 4가지가 있다. 

 

1. 시스템 프로세스

커널에서만 실행되는 시스템 스레드들을 호스팅하는 프로세스로서, Ntoskrnl.exe의 커널 생성 단계에서 생성된다.

이는 디바이스 드라이버와 함께 시스템 공간에 로드되어 커널 모드에서 동작하는 스레드를 관리한다.

(시스템 스레드는 커널 모드의 PsCreateSystemThread 함수에 의해 생성됨.)

 

윈도우 커널 레벨에서 구동되는 주요 프로세스들... Winlogon.exe, Smss.exe 등등.

 

2. 서비스 프로세스

작업 표시줄에 드러나지 않는 백그라운드 형태로 실행되는 서비스들을 말한다.

흔히들 우리가 알고 있는 서비스의 개념이 서비스 프로세스 이다.

 

3. 응용 프로그램 (User Application)

유저모드에서 실행되는 프로그램들을 말한다. 메모장, Cmd 등,,,

 

4. 환경 서브시스템

Ntdll.dll의 Native Operating System Services와 응용프로그램 간에 주고받는 요청을 연결해주는 역할.

 

다음 프로세스의 생성과정을 한번 살펴보자. csrss 포스트에 사용했던 그림을 다시 가져오겠음.

최초 프로세스가 생성되면, 해당 프로세스의 정보를 담고 있는

EPROCESS (Executive Process) 라는 구조체를 커널 메모리 공간에 생성하고,

프로세스가 사용하는 스레드 수 만큼의 ETHREAD (Executive Thread) 도 함께 생성된다.

EPROCESS와 ETHREAD는 커널 메모리 공간에 생성되고, 커널 모드에서만 접근이 가능하다.

 

그리고 이들 구조체 안에는 PCB (Process Control Block) 와 TCB (Thread Control Block) 라는 이름의

하위 구조체가 생성된다. PCB = KPROCESS, TCB = KTHREAD 같은 뜻으로 사용함.

 

얘네들이 커널 영역에서만 동작을 하니.. 유저 모드에서 작업을 처리할 수 있는 구조가 필요하겠죠??

그래서 유저 영역에다가 PEB (Process Environment Block), TEB (Thread Environment Block) 을 만들게 된다.

 

PCB, TCB, PEB, TEB 이 네가지 구조체들이 프로세스를 이용하는데 사용되는 커다란 틀이라고 보면됨.

 

EPROCESS에선.. PCB(KPROCESS)의 포인터를 통해

프로세스 식별 정보, 프로세스에서 사용하는 메모리 정보, PEB 위치 정보, 스레드 정보 등을 알 수 있다.

 

PEB, TEB는 보다 시피 유저모드에서 동작된다.

프로세스, 스레드 리스트를 커널에 요청해야하는 수고를 덜고, 자유롭게 유저 공간에 접근이 가능하도록 해준다.

 

ETHREAD에선 KPROCESS의 ThreadListHead를 통해 스레드간 링크드 리스트로 연결되며

이녀석 또한 EPROCESS처럼 KTHREAD의 포인터를 통해 TEB 포인터 정보, 스레드 스케줄링, 쿼넘 값 등의 정보를 가짐.

 

이 들 중의 중심은 단연 EPROCESS

아까 프로세스와 스레드들은 포인터로 연결되어 정보를 받아온다고 했다.

그때 쓰이는 링크드 리스트들이 위에 보인다. 화살표 연결 되어있는 놈들을 위주로 보면 됨.

 

ThreadListHead : KPROCESS(PCB) 에 있는 리스트. 현재 프로세스에서 실행중인 스레드 리스트이다.

PsActiveProcessHead : 현재 시스템에서 실행중인 전체 프로세스 리스트이다.

HandleTableListHead : 현재 실행중인 전체 핸들 리스트이다.

 

PCB, PEB를 혼동하지 않아야 함.

PCB의 C가 Control 이니까.. 조정, 제어는 커널모드

PEB는 유저모드

 

프로세스와 스레드 구조체들은 아래 포스팅에 따로 정리해두었다. 

 

윈도우 EPROCESS와 KPROCESS 구조

EPROCESS 와 KPROCESS 구조체에 대해 한번 공부해봅시다. 프로세스는 무조건 이해해야한다. 우리가 운영체제를 이용하는 이유는 무엇인가.. 작업을 하고자 함이다. 게임을 하든 문서를 작성하든 인터

plummmm.tistory.com

 

 

 

윈도우 ETHREAD와 KTHREAD 구조

커널모드에 있는 ETHREAD와 유저 모드에서 돌아가는 KTHREAD에 대해서 한번 알아보겠다. 스레드 구조체는 ETHREAD에 정의 되어 있는데, Windbg에서 dt _ETHREAD, dt_KTHREAD를 입력하면 구조체에 대한 정보를

plummmm.tistory.com

 

그럼 이제 Windbg로 프로세스를 확인해보자.

확인하기 전에 명령어 부터 한번 알아보고 가겠음.

!process : EPROCESS 구조체를 분석하는 명령어임.

!process /s /m [process] [flags]

/s : 특정 세션을 지정하여 확인할 수 있다

/m : 특정 모듈을 지정하여 확인할 수 있다.

[process] : PID 혹은 프로세스의 메모리 주소, 혹은 프로세서를 지정할 수 있따. 0은 모든 프로세서 의미

[flags] : 화면에 표시할 정보를 조절할 수 있따. 0~7 사이로 값을 조정

 

process 에 0을 주어 모든 프로세서, flags 에 0을 주어 가장 적은 정보를 출력하도록 하였다.

EPROCESS의 구조체를 이용하여 정보를 표시하는 걸 볼 수 잇음

 

이중 svchost.exe 를 자세히 보자.

 

 

Token 부터 순서대로

권한 토큰, 경과 시간, 유저모드 이용시간, 커널모드 이용시간, 이용 중인 페이지풀, 이용 중인 논페이지풀, 워킹 셋 크기

등의 프로세스 정보를 알 수 있따.

 

별표 있는 곳 부터는 스레드 정보이다.

 

그리고 다음.

-1 옵션을 붙이면 지금 현재 실행중인 프로세스에 대해 알 수있다.

 

 

현재 실행중인 프로세스는 Idle 이라는 것을 알 수 있다.

유휴 프로세스 즉, CPU 유휴 사용량 계산하는 프로세스

 

이것도 커널 생성 단계에서 생성된다.

CPU당 하나의 유휴 스레드를 할당 받아, 유휴 CPU 사용률 (남은 CPU 사용률)을 계산하는 역할을 한다.

Process Explore에서는 System Idle process라고 표기된다.

!cpuinfo, !cpuid 명령으로 프로세스 정보를 확인 가능함.

 

윈도우에서 보면 여러개의 프로그램이 실시간으로 병행 실행 되지만 실제로 시간을 분할하여

동시간대에 하나만 처리합니다.

 

Windbg 명령 프롬프트를 보면 kd 앞에 0 : 이 있는걸 볼 수 있음 ( 0 : kd> 요런식으로 )

이건 디버깅 중인 디버기(즉 가상머신 운영체제)의 실행 환경 정보이다.

그 의미는 아래와 같음.

 

[Processor] : [Thread][Environment]> 

 

[Processor] : 현재 활성화된 프로세서(CPU)를 표시한다. 0부터 표시됨.

                    윈도우에서는 물리 프로세서 안의 가상 프로세서를 포함한 단위이다.

                    멀티코어 기준

 

[Thread] : 현재 확인 중인 스레드를 표시한다.

[Environment] : 디버깅 모드 정보를 표시한다.

                    로컬 커널 디버깅: LKD,   커널 디버깅: KD.   유저모드 디버깅: 아무것도 안나타남.

커널/유저 모드 디버깅에 따라 스레드나 프로세스를 확인하거나 변경할 수 있는 명령으로 ~을 사용할 수 있다.

~명령에 대해 알아보입시다.

 

~.  : 현재 스레드를 표시한다. 유저 모드에서만 동작한다.

~# : 스레드의 현재 예외 처리나 디버그 이벤트를 표시한다. 유저모드에서만 동작한다.

~* : 현재 프로세서의 모든 스레드를 표시한다.

~숫자s : 해당 번호로 스레드를 변경한다.

~숫자   : 해당 번호로 프로세서를 변경한다.

 

다음 thread에 관한 명령어다.

프로세스는 그저 스레드들이 작업하기 위한 환경이다. 실제로 일하는 녀석들은 스레드임

커널 디버깅할 시에도 실제로 프로세스가 아니라 스레드를 보고 분석한다.

!thread [thread] [flags]

[thread] : 지정한 스레드를 보여준다. -1이나 값이 없을 경우 현재 스레드를 보여준다.

[flags] : 지정한 스레드의 정보양을 나타냄. 프로세스 명령어와 같음 0: 적은 정보, 6: 가장 많은 정보

-1 옵션 : 역시나 현재 실행중인 스레드.

 

윗 줄부터 보겠음.

THREAD 8055de60  Cid 0000.0000  Teb: 00000000 Win32Thread: 00000000 RUNNING on processor 0

-> 현재 스레드의 ETHREAD 위치는 8055de60, 0번 프로세서에서 실행중이다.

 

Attached Process          8055e0c0       Image:         Idle

-> EPROCESS는 8055e0c0 이고, Idle 프로세서에 속한 스레드이다.

 

Priority 16 BasePriority 0 PriorityDecrement 0 DecrementCount 0

-> 현재 스레드의 우선 순위

 

ChildEBP RetAddr  Args to Child

-> 호출한 스택 정보를 표시한다.

 

 

출처 : 리버싱 윈도우 - 로드북 

반응형