Kernel Object Handle의 정보(Type, Name) 구하기
2009. 9. 29. 09:02 in 프로그래밍/Win32 Deep Inside

Sysinternals의 Process Explorer를 실행하면, 임의의 Kernel Object Handle의 Type과 Name을
다음과 같이 알려줍니다.
Win32 API에서는 이러한 정보를 구하는 방법을 제공하고 있지 않습니다. Windows Native API를 사용해야
해당 정보를 구할 수 있습니다. (ntdll.dll::ZwQueryObject(...))
백문이 불여일견.
해당 정보를 리턴하는 다음 코드를 공유합니다.
(코드가 좀 길어 보여서... "view plain"으로 보시면 수월할 겁니다.)
자료구조를 포함하는 헤더 파일입니다.
Kernel Object Handle의 Type을 구하는 함수입니다.
Kernel Object Handle의 Name을 구하는 함수입니다.
위 두개의 함수를 이용하면, Process Explorer에서 나열해준 정보 (Type, Name)을 구할 수 있습니다.
다음과 같이 알려줍니다.
Win32 API에서는 이러한 정보를 구하는 방법을 제공하고 있지 않습니다. Windows Native API를 사용해야
해당 정보를 구할 수 있습니다. (ntdll.dll::ZwQueryObject(...))
백문이 불여일견.
해당 정보를 리턴하는 다음 코드를 공유합니다.
(코드가 좀 길어 보여서... "view plain"으로 보시면 수월할 겁니다.)
자료구조를 포함하는 헤더 파일입니다.
- #include <winternl.h>
- // ntdll::ZwQueryObject(...)의 prototype
- typedef NTSTATUS (__stdcall *LPFN_ZwQueryObject)(IN HANDLE Handle, IN DWORD ObjectInformationClass, OUT PVOID ObjectInformation, IN ULONG ObjectInformationLength, OUT PULONG ReturnLength);
- // ntdll::ZwQueryObject(...)에서 쓰임
- typedef struct tagPUBLIC_OBJECT_TYPE_INFORMATION
- {
- UNICODE_STRING TypeName;
- ULONG Reserved[MAX_PATH];
- } PUBLIC_OBJECT_TYPE_INFORMATION, *PPUBLIC_OBJECT_TYPE_INFORMATION;
- // ZwQueryObject를 통한 Kernel Object의 Type
- typedef INT TYPE_KERNEL_OBJECT;
- #define TYPE_KERNEL_OBJECT_UNKNOWN 0
- #define TYPE_KERNEL_OBJECT_TYPE 1
- #define TYPE_KERNEL_OBJECT_DIRECTORY 2
- #define TYPE_KERNEL_OBJECT_SYMBOLICLINK 3
- #define TYPE_KERNEL_OBJECT_TOKEN 4
- #define TYPE_KERNEL_OBJECT_PROCESS 5
- #define TYPE_KERNEL_OBJECT_THREAD 6
- #define TYPE_KERNEL_OBJECT_JOB 7
- #define TYPE_KERNEL_OBJECT_DEBUGOBJECT 8
- #define TYPE_KERNEL_OBJECT_EVENT 9
- #define TYPE_KERNEL_OBJECT_EVENTPAIR 10
- #define TYPE_KERNEL_OBJECT_MUTANT 11
- #define TYPE_KERNEL_OBJECT_CALLBACK 12
- #define TYPE_KERNEL_OBJECT_SEMAPHORE 13
- #define TYPE_KERNEL_OBJECT_TIMER 14
- #define TYPE_KERNEL_OBJECT_PROFILE 15
- #define TYPE_KERNEL_OBJECT_KEYEDEVENT 16
- #define TYPE_KERNEL_OBJECT_WINDOWSTATION 17
- #define TYPE_KERNEL_OBJECT_DESKTOP 18
- #define TYPE_KERNEL_OBJECT_SECTION 19
- #define TYPE_KERNEL_OBJECT_KEY 20
- #define TYPE_KERNEL_OBJECT_PORT 21
- #define TYPE_KERNEL_OBJECT_WAITABLEPORT 22
- #define TYPE_KERNEL_OBJECT_ADAPTER 23
- #define TYPE_KERNEL_OBJECT_CONTROLLER 24
- #define TYPE_KERNEL_OBJECT_DEVICE 25
- #define TYPE_KERNEL_OBJECT_DRIVER 26
- #define TYPE_KERNEL_OBJECT_IOCOMPLETION 27
- #define TYPE_KERNEL_OBJECT_FILE 28
- #define TYPE_KERNEL_OBJECT_WMIGUID 29
- #define TYPE_KERNEL_OBJECT_FILTERCONNECTIONPORT 30
- #define TYPE_KERNEL_OBJECT_FILTERCOMMUNICATIONPORT 31
- #define TYPE_KERNEL_OBJECT_OTHER 32
Kernel Object Handle의 Type을 구하는 함수입니다.
- NTSTATUS GetHandleType(IN HANDLE hHandle, OUT TYPE_KERNEL_OBJECT *pnObject)
- {
- NTSTATUS nRtnValue = 0;
- HMODULE hModule = NULL;
- LPFN_ZwQueryObject pfn = NULL;
- ULONG nSize = 0;
- LPBYTE pBuf = NULL;
- PPUBLIC_OBJECT_TYPE_INFORMATION pstInfo = NULL;
- PUBLIC_OBJECT_TYPE_INFORMATION stInfo = {0,};
- if (NULL == pnObject)
- {
- nRtnValue = STATUS_INVALID_PARAMETER;
- goto FINAL;
- }
- (*pnObject) = TYPE_KERNEL_OBJECT_UNKNOWN;
- // 만들어 놓은 아래 함수가 없다면,
- // hModule = ::LoadLibraryEx(TEXT("ntdll.dll"), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
- // 를 사용한다.
- hModule = LoadLibraryFromSystem(TEXT("ntdll.dll"));
- if (NULL == hModule)
- {
- nRtnValue = STATUS_OBJECT_PATH_NOT_FOUND;
- goto FINAL;
- }
- pfn = (LPFN_ZwQueryObject)::GetProcAddress(hModule, "ZwQueryObject");
- if (NULL == pfn)
- {
- nRtnValue = STATUS_PROCEDURE_NOT_FOUND;
- goto FINAL;
- }
- pstInfo = &stInfo;
- nRtnValue = (*pfn)(hHandle, 2, pstInfo, sizeof(stInfo), &nSize); // 2 : ObjectTypeInformation
- if (STATUS_INFO_LENGTH_MISMATCH == nRtnValue)
- {
- pBuf = new BYTE[nSize];
- if (NULL == pBuf)
- {
- nRtnValue = STATUS_NO_MEMORY;
- goto FINAL;
- }
- ZeroMemory(pBuf, sizeof(BYTE)*nSize);
- pstInfo = (PPUBLIC_OBJECT_TYPE_INFORMATION)pBuf;
- nRtnValue = (*pfn)(hHandle, 2, pstInfo, nSize, &nSize); // 2 : ObjectTypeInformation
- }
- if (STATUS_SUCCESS != nRtnValue)
- {
- goto FINAL;
- }
- if (NULL == pstInfo->TypeName.Buffer)
- {
- nRtnValue = STATUS_INVALID_PARAMETER;
- goto FINAL;
- }
- // 빈도 많음
- if (0 == _tcsicmp(TEXT("Key"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_KEY;
- else if (0 == _tcsicmp(TEXT("File"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_FILE;
- else if (0 == _tcsicmp(TEXT("Thread"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_THREAD;
- else if (0 == _tcsicmp(TEXT("Directory"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_DIRECTORY;
- else if (0 == _tcsicmp(TEXT("Section"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_SECTION;
- else if (0 == _tcsicmp(TEXT("Event"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_EVENT;
- else if (0 == _tcsicmp(TEXT("Mutant"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_MUTANT;
- else if (0 == _tcsicmp(TEXT("Port"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_PORT;
- // 빈도 적음
- else if (0 == _tcsicmp(TEXT("KeyedEvent"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_KEYEDEVENT;
- else if (0 == _tcsicmp(TEXT("Token"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_TOKEN;
- else if (0 == _tcsicmp(TEXT("WindowStation"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_WINDOWSTATION;
- else if (0 == _tcsicmp(TEXT("Type"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_TYPE;
- else if (0 == _tcsicmp(TEXT("SymbolicLink"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_SYMBOLICLINK;
- else if (0 == _tcsicmp(TEXT("Process"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_PROCESS;
- else if (0 == _tcsicmp(TEXT("Job"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_JOB;
- else if (0 == _tcsicmp(TEXT("DebugObject"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_DEBUGOBJECT;
- else if (0 == _tcsicmp(TEXT("EventPair"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_EVENTPAIR;
- else if (0 == _tcsicmp(TEXT("Callback"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_CALLBACK;
- else if (0 == _tcsicmp(TEXT("Semaphore"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_SEMAPHORE;
- else if (0 == _tcsicmp(TEXT("Timer"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_TIMER;
- else if (0 == _tcsicmp(TEXT("Profile"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_PROFILE;
- else if (0 == _tcsicmp(TEXT("Desktop"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_DESKTOP;
- else if (0 == _tcsicmp(TEXT("WaitablePort"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_WAITABLEPORT;
- else if (0 == _tcsicmp(TEXT("Adapter"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_ADAPTER;
- else if (0 == _tcsicmp(TEXT("Controller"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_CONTROLLER;
- else if (0 == _tcsicmp(TEXT("Device"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_DEVICE;
- else if (0 == _tcsicmp(TEXT("Driver"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_DRIVER;
- else if (0 == _tcsicmp(TEXT("IoCompletion"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_IOCOMPLETION;
- else if (0 == _tcsicmp(TEXT("WmiGuid"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_WMIGUID;
- else if (0 == _tcsicmp(TEXT("FilterConnectionPort"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_FILTERCONNECTIONPORT;
- else if (0 == _tcsicmp(TEXT("FilterCommunicationPort"), pstInfo->TypeName.Buffer))
- (*pnObject) = TYPE_KERNEL_OBJECT_FILTERCOMMUNICATIONPORT;
- else
- (*pnObject) = TYPE_KERNEL_OBJECT_OTHER;
- FINAL:
- if (NULL != pBuf)
- {
- delete [] pBuf;
- pBuf = NULL;
- }
- if (NULL != hModule)
- {
- ::FreeLibrary(hModule);
- hModule = NULL;
- }
- return nRtnValue;
- }
Kernel Object Handle의 Name을 구하는 함수입니다.
- NTSTATUS GetHandleObjectName(IN HANDLE hHandle, OUT LPTSTR lpszName, IN DWORD dwCchName)
- {
- NTSTATUS nRtnValue = 0;
- HMODULE hModule = NULL;
- LPFN_ZwQueryObject pfn = NULL;
- ULONG nSize = 0;
- LPBYTE pBuf = NULL;
- PPUBLIC_OBJECT_TYPE_INFORMATION pstInfo = NULL;
- PUBLIC_OBJECT_TYPE_INFORMATION stInfo = {0,};
- if (NULL == lpszName)
- {
- nRtnValue = STATUS_INVALID_PARAMETER;
- goto FINAL;
- }
- // 만들어 놓은 아래 함수가 없다면,
- // hModule = ::LoadLibraryEx(TEXT("ntdll.dll"), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
- // 를 사용한다.
- hModule = LoadLibraryFromSystem(TEXT("ntdll.dll"));
- if (NULL == hModule)
- {
- nRtnValue = STATUS_OBJECT_PATH_NOT_FOUND;
- goto FINAL;
- }
- pfn = (LPFN_ZwQueryObject)::GetProcAddress(hModule, "ZwQueryObject");
- if (NULL == pfn)
- {
- nRtnValue = STATUS_PROCEDURE_NOT_FOUND;
- goto FINAL;
- }
- pstInfo = &stInfo;
- nRtnValue = (*pfn)(hHandle, 1, pstInfo, sizeof(stInfo), &nSize); // 1 : ObjectNameInformation
- if (STATUS_INFO_LENGTH_MISMATCH == nRtnValue)
- {
- pBuf = new BYTE[nSize];
- if (NULL == pBuf)
- {
- nRtnValue = STATUS_NO_MEMORY;
- goto FINAL;
- }
- ZeroMemory(pBuf, sizeof(BYTE)*nSize);
- pstInfo = (PPUBLIC_OBJECT_TYPE_INFORMATION)pBuf;
- nRtnValue = (*pfn)(hHandle, 1, pstInfo, nSize, &nSize); // 1 : ObjectNameInformation
- }
- if (STATUS_SUCCESS == nRtnValue)
- {
- StringCchCopy(lpszName, dwCchName, pstInfo->TypeName.Buffer);
- }
- FINAL:
- if (NULL != pBuf)
- {
- delete [] pBuf;
- pBuf = NULL;
- }
- if (NULL != hModule)
- {
- ::FreeLibrary(hModule);
- hModule = NULL;
- }
- return nRtnValue;
- }
위 두개의 함수를 이용하면, Process Explorer에서 나열해준 정보 (Type, Name)을 구할 수 있습니다.
'프로그래밍 > Win32 Deep Inside' 카테고리의 다른 글
WriteFile/ReadFile의 overlapped i/o 사용하기 (asynchronous, non-block, iocp) (3) | 2013.03.21 |
---|---|
Zombie Thread 오류로 인한 unknown/unloaded 오류 발견 & 대처법 (0) | 2010.10.20 |
열린 파일 찾기 (UnLocker) 소스 공유 (2) | 2010.08.23 |
DLL을 만들때의 최고의 습관 (DLLMain deadlock 회피) - (1) (1) | 2009.10.01 |
가변 길이 구조체 (0) | 2009.09.15 |