본문 바로가기

High Level Technique/Window System

Pseudo Handle, Handle Duplicate

Pseudo Handle, Handle Duplicate


자신의 핸들을 얻는 함수로는 GetCurrentProcess()가 있습니다. 이 함수를 이용해서 얻은 핸들을 Pseudo Handle이라고 합니다.


Pseudo Handle은 핸들 테이블에 등록되지 않은 핸들이며 그저 약속된 상수가 반환됩니다.  그래서 자식 프로세스로 상속되지 않고 CloseHandle()의 인자로 전달 할 필요가 없습니다.


그러면 실제 핸들 테이블에 존재하는 핸들 값을 어떻게 얻을까요?


DuplicateHandle()을 이용해서 핸들을 복사해 줍니다. 

가령, 부모 프로세스의 핸들 테이블에서 123이라는 핸들을 자식 프로세스 핸들 테이블에 넣고자 할 때 자식 프로세스의 핸들 테이블에서는 123이라는 핸들 값은 아무런 쓸모가 없죠.

그래서 각 정보를 복사해 자식 프로세스의 핸들에 넣어주어야 합니다.



DuplicateHandle()의 파라미터를 살펴보면 아래와 같다.



hSourceProcessHandle: 복제할 핸들을 소유하는 프로세스를 지정합니다.

hSourceHandle: 복제할 핸들을 지정합니다.

hTargetProcessHandle: 복제된 핸들을 소유할 프로세스를 지정합니다.

lpTargetHandle: 복제된 핸들값을 저장할 변수의 주소를 지정합니다.


이 4가지만 알고 넘어가도록 하겠습니다.


DuplicateHandle(A핸들, 256, B핸들, &val, ....) 로 사용한다면 


A 프로세스에 존재하는 256 핸들을 B 프로세스에 등록하고 등록된 핸들은 변수 val에 저장합니다.


해당 핸들 테이블에 복사가 되면 Usage Count 또한 증가합니다.


그러면 자기 자신에 복사를 하는 경우도 있는데 마찬가지로 Usage Count 또한 증가합니다.




부모 프로세스 핸들을 자식 프로세스에게 전달하기


DuplicateHandle.cpp


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
29
30
31
32
33
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
 
int main(void)
{
    HANDLE hProcess;
    TCHAR cmdString[1024];
 
    DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &hProcess, 0, TRUE, DUPLICATE_SAME_ACCESS);
 
    _stprintf(cmdString, _T("%s %u"), _T("ChildProcess.exe"), (unsigned)hProcess);
 
    STARTUPINFO si = { 0, };
    PROCESS_INFORMATION pi = { 0, };
    si.cb = sizeof(si);
 
    BOOL isSuccess = CreateProcess(NULL, cmdString, NULLNULL, TRUE, CREATE_NEW_CONSOLE, NULLNULL&si, &pi);
 
    if (isSuccess == FALSE)
    {
        printf("CreateProcess failed \n");
        return -1;
    }
 
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
 
    printf("[Parent Process]\n");
    printf("Ooops!\n");
 
    return 0;
}
cs



ChildProcess.cpp


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
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
 
int _tmain(int argc, TCHAR* argv[])
{
    HANDLE hParent = (HANDLE)_ttoi(argv[1]);
    DWORD isSuccess = WaitForSingleObject(hParent, INFINITE);
 
    printf("[Child Process]\n");
 
    if (isSuccess == WAIT_FAILED)
    {
        printf("WAIT_FAILED returned!\n");
        Sleep(10000);
        return -1;
    }
    else
    {
        printf("General Lee said, Dont inform \n");
        printf("The enemy my death\n");
    }
        
    Sleep(10000);
    return 0;
}
cs