https://greenfishblog.tistory.com/20
Kernel Object Handle의 정보(Type, Name) 구하기
Sysinternals의 Process Explorer를 실행하면, 임의의 Kernel Object Handle의 Type과 Name을 다음과 같이 알려줍니다. Win32 API에서는 이러한 정보를 구하는 방법을 제공하고 있지 않습니다. Windows Native AP..
greenfishblog.tistory.com
지금은 솔직히 잘 모르겠다^^;
Sysinternals의 Process Explorer를 실행하면, 임의의 Kernel Object Handle의 Type과 Name을
다음과 같이 알려줍니다.

Win32 API에서는 이러한 정보를 구하는 방법을 제공하고 있지 않습니다. Windows Native API를 사용해야
해당 정보를 구할 수 있습니다. (ntdll.dll::ZwQueryObject(...))
백문이 불여일견.
해당 정보를 리턴하는 다음 코드를 공유합니다.
(코드가 좀 길어 보여서... "view plain"으로 보시면 수월할 겁니다.)
자료구조를 포함하는 헤더 파일입니다.
view plaincopy to clipboardprint?
- #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을 구하는 함수입니다.
view plaincopy to clipboardprint?
- 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을 구하는 함수입니다.
view plaincopy to clipboardprint?
- 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)을 구할 수 있습니다.
출처: https://greenfishblog.tistory.com/20 [greenfish blog]
'개발 > VC++' 카테고리의 다른 글
[스크랩] MFC 프로세스 실행, 프로세스 죽이기, 죽인 프로세스 PID (0) | 2021.07.19 |
---|---|
[스크랩] Kernel object 와 오브젝트 핸 (0) | 2021.07.19 |
[스크랩] 쓰레드란? (0) | 2021.07.07 |
[스크랩] C++ 스레드 thread (0) | 2021.06.29 |
MFC 흐름도 (0) | 2015.03.25 |