상세 컨텐츠

본문 제목

08.1 핸들 테이블과 오브젝트 핸들의 상속

Programming/Windows System

by RACC8N 2020. 4. 18. 16:59

본문

핸들과 커널 오브젝트 (REVIEW) : 핸들 256을 통해서 0x2400번지에 할당되어 있는 메일슬롯에 접근이 가능하다.

 

※ 0x2400번지에 커널 오브젝트가 생성되면서 핸들 256을 반환했다. 하지만 핸들 256이 0x2400번지에 존재하는 커널 오브젝트를 의미한다는 정보는 어디에도 없다.

 

프로세스의 핸들 테이블 도입

핸들 테이블은 프로세스로 전달되는 핸들 정보가 어떻게 전달 및 저장되는지 구체적으로 보여주고 있다.

 

※ 핸들 테이블은 핸들 정보를 저장하고 있는 테이블로서 프로세스별로 독립적이다.

 

핸들의 상속

CreateProcess 함수를 호출하면 새로운 자식 프로세스가 생성된다. 자식 프로세스를 위한 핸들 테이블도 생성된다.

CreateProcess 함수의 다섯 번째 전달인자가 무엇이냐에 따라서 부모 프로세스 핸들 테이블에 등록되어 있는 핸들 정보를 자식 프로세스에게 상속할 수 있다.

 

자식 프로세스는 부모 프로세스의 핸들 테이블에 등록되어 있는 핸들 정보를 상속받을 수 있다. 하지만 모든 핸들 정보를 상속받는 것은 아니다.

상속 여부가 Y인 핸들만 상속된다. 또한 상속 여부에 대한 정보도 변경 없이 그대로 상속 된다.

 

핸들의 상속과 커널 오브젝트의 Usage Count 

Usage Count는 커널 오브젝트를 참조하는 프로세스 개수만큼 증가한다. 

> 커널 오브젝트를 참조하는 프로세스가 되기 위해서는 핸들을 얻으면 된다.

> 프로세스가 핸들을 얻게 되었다는 의미는 핸들 테이블에 해당 핸들에 대한 정보가 갱신(추가)되었음을 의미한다.

 

[EXAMPLE] CreateMailSlot

1. 메일슬롯 리소스 생성

2. 커널 오브젝트 생성

3. 핸들 정보가 핸들 테이블에 갱신

4. CreateMailSlot함수를 빠져 나오면서 핸들값 반환

 

※ 대부분의 경우 프로세스가 핸들을 얻게 되었다고 하면, 4번째 단계에 초점을 맞춰서 생각하지만, 실제로는 3번째 단계 이후부터이다. 즉 핸들 테이블에 A 핸들에 대한 정보가 등록되면, A핸들을 얻은 것이다.

 

위의 [그림 8-3]을 Usage Count를 생각해서 다시 본다면 아래와 같을 것이다.

 

※ 핸들의 상속 여부는 어디서 결정되는 것일까? -> 리소스를 생성하는 함수의 전달인자를 통해 결정 된다.

 

상속되기 위한 핸들의 조건

핸들의 상속 여부 (핸들 테이블에서의 Y or N)는 리소스가 생성되는 순간에 결정된다. (프로그래머에 의해서 결정)

 

[EXAMPLE] CreateMailSlot과 CreateProcess

1. CreateMailSlot () 

네 번째 전달인자 LPSECURITY_ATTRIBUTES는 구조체 SECURITY_ATTRIBUTES의 포인터로 정의되어 있다. 즉 SECURITY_ATTRIBUTES 구조체 변수를 적절히 초기화한 다음, 주소값을 인자로 전달하라는 의미이다. 

 

구조체 SECURITY_ATTRIBUTES

nLength 구조체 변수 크기 (반드시 구조체 변수 크기로 초기화 [sa.nLenth = sizeof(sa)]
lpSecurityDescriptor 우선 NULL로 초기화 (핸들의 상속 관점에서 의미가 없다)
bInheritHandle 상속 여부를 결정짓는 요소 (핸들 테이블의 Y or N 역할 T/F)

2. CreateProcess() 

※ CreateProcess 함수는 호출 시 핸들 상속과 관련해서 두 가지 사항을 결정해야 한다.

1. 자식 프로세스에게 핸들 테이블을 상속할 것인가를 결정하는 것 (CreateProcess의 다섯 번째 인자 설정!)

2. 자식 프로세스 생성 시 얻게 되는 핸들(자식 프로세스를 가리키는 핸들)의 상속 여부를 결정하는 것 (SECURITY_ATTRIBUTES 설정!)

 

CreateProcess의 다섯 번째 인자 bInheritHandles는 핸들의 상속 여부(Y/N)를 결정하는 것이 아니라, 부모 프로세스가 소유하고 있는 핸들 테이블 정보의 상속 여부를 결정하는 것이다.

 

 

[EXAMPLE] MailSlot

MailReceiver의 핸들 테이블은 CreateMailSlot 함수에 의해서 생성.

MailSender의 핸들 테이블은 CreateFile 함수에 의해서 생성.

 

양쪽 핸들 테이블의 핸들값이 모두 127인 것은 우연의 일치이다. Sender와 Receiver는 서로 다른 프로세스로서 핸들 테이블이 서로 독립적이기 때문이다. 또한 메일슬롯은 Sender와 Receiver가 공유하는 것 처럼 보이지만, 이것은 Receiver의 리소스 이다.

 

[EXAMPLE] MailSlot 핸들 상속.

MailSender가 CreateProcess 함수를 통해서 자식 프로세스를 생성했다.

자식 프로세스는 상속된 핸들 정보를 참조해서 메일슬롯으로 데이터를 전송할 수 있다.

 

Pseudo 핸들과 핸들의 중복(duplicate)

 

현재 실행 중에 있는 프로세스 자신의 핸들을 얻는 방법으로써 GetCurrentProcess 함수가 있다.

> 이 함수를 통해 얻은 핸들을 가리켜 가짜 핸들(Pseudo 핸들)이라 한다.

> 이렇게 얻은 핸들은 핸들 테이블에 등록되어 있지 않은 핸들이고, 현재 실행 중인 프로세스를 참조하기 위한 용도로 정의해 놓은, 약속된 상수가 반환되기 때문이다.

> 따라서 자식 프로세스로 상속되지 않으며, CloseHandle함수를 사용할 필요가 없다.

 

현재 실행중인 프로세스의 진짜 핸들을 복사하는 함수 : DuplicateHandle() 

 

hSourceProcessHandle 복제할 핸들을 소유하는 프로세스 지정
hSourceHandle 복제할 핸들을 지정
hTargetProcessHandle 복제된 핸들을 소유할 프로세스 지정
hTargetHandle 복제된 핸들값을 저장할 변수의 주소
dwDesiredAccess 복제된 핸들의 접근권한 지정
bInheritHandle 복제된 핸들의 상속 여부를 지정. (TRUE : 새로운 자식 프로세스로 상속됨, FALSE: 상속 안됨)
dwOptions

DUPLICATE_SAME_ACCESS : 원본 핸들과 동일한 접근권한

DUPLICATE_CLOSE_SOURCE : 원본 핸들을 종료 (CloseHandle과 같은 효과)

[EXAMPLE - 1]

프로세스 A에 존재하는 핸들 256의 정보를 프로세스 B의 핸들 테이블에 등록하고, 등록된 핸들의 값은 val에 저장한다.

 

[EXAMPLE - 2]

프로세스 A에 존재하는 핸들 256의 정보를 프로세스 A의 핸들 테이블에 복제한다. UC는 2로 증가한다.

복사된 핸들에 대해서도 CloseHandle함수를 호출하여 핸들을 반환해야 한다.

 

[EXAMPLE - 3]

GetCurrentProcess 함수 호출을 통해 얻은 핸들을 복사한다면 (가짜 핸들을 복사한다면) 진짜 핸들이 생성되어 핸들 테이블에 등록된다.

 

'Programming > Windows System' 카테고리의 다른 글

08.3 프로세스 환경변수  (0) 2020.04.18
08.2 파이프 방식의 IPC  (0) 2020.04.18
07.3 Signaled vs Non-Signaled  (0) 2020.04.18
07.2 메일슬롯 방식의 IPC  (0) 2020.04.18
07.1 프로세스간 통신(IPC)의 의미  (0) 2020.04.18

관련글 더보기

댓글 영역