개발/VC++

[스크랩] C++ 커널 오브젝트 타입/네임 구하기

99iberty 2021. 7. 19. 23:40

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?

  1. #include <winternl.h>  
  2.   
  3. // ntdll::ZwQueryObject(...)의 prototype  
  4. typedef NTSTATUS (__stdcall *LPFN_ZwQueryObject)(IN HANDLE Handle, IN DWORD ObjectInformationClass, OUT PVOID ObjectInformation, IN ULONG ObjectInformationLength, OUT PULONG ReturnLength);  
  5.   
  6. // ntdll::ZwQueryObject(...)에서 쓰임  
  7. typedef struct tagPUBLIC_OBJECT_TYPE_INFORMATION  
  8. {  
  9.     UNICODE_STRING  TypeName;  
  10.     ULONG           Reserved[MAX_PATH];  
  11. } PUBLIC_OBJECT_TYPE_INFORMATION, *PPUBLIC_OBJECT_TYPE_INFORMATION;  
  12.   
  13. // ZwQueryObject를 통한 Kernel Object의 Type  
  14. typedef INT TYPE_KERNEL_OBJECT;  
  15. #define     TYPE_KERNEL_OBJECT_UNKNOWN                  0  
  16. #define     TYPE_KERNEL_OBJECT_TYPE                     1  
  17. #define     TYPE_KERNEL_OBJECT_DIRECTORY                2  
  18. #define     TYPE_KERNEL_OBJECT_SYMBOLICLINK             3  
  19. #define     TYPE_KERNEL_OBJECT_TOKEN                    4  
  20. #define     TYPE_KERNEL_OBJECT_PROCESS                  5  
  21. #define     TYPE_KERNEL_OBJECT_THREAD                   6  
  22. #define     TYPE_KERNEL_OBJECT_JOB                      7  
  23. #define     TYPE_KERNEL_OBJECT_DEBUGOBJECT              8  
  24. #define     TYPE_KERNEL_OBJECT_EVENT                    9  
  25. #define     TYPE_KERNEL_OBJECT_EVENTPAIR                10  
  26. #define     TYPE_KERNEL_OBJECT_MUTANT                   11  
  27. #define     TYPE_KERNEL_OBJECT_CALLBACK                 12  
  28. #define     TYPE_KERNEL_OBJECT_SEMAPHORE                13  
  29. #define     TYPE_KERNEL_OBJECT_TIMER                    14  
  30. #define     TYPE_KERNEL_OBJECT_PROFILE                  15  
  31. #define     TYPE_KERNEL_OBJECT_KEYEDEVENT               16  
  32. #define     TYPE_KERNEL_OBJECT_WINDOWSTATION            17  
  33. #define     TYPE_KERNEL_OBJECT_DESKTOP                  18  
  34. #define     TYPE_KERNEL_OBJECT_SECTION                  19  
  35. #define     TYPE_KERNEL_OBJECT_KEY                      20  
  36. #define     TYPE_KERNEL_OBJECT_PORT                     21  
  37. #define     TYPE_KERNEL_OBJECT_WAITABLEPORT             22  
  38. #define     TYPE_KERNEL_OBJECT_ADAPTER                  23  
  39. #define     TYPE_KERNEL_OBJECT_CONTROLLER               24  
  40. #define     TYPE_KERNEL_OBJECT_DEVICE                   25  
  41. #define     TYPE_KERNEL_OBJECT_DRIVER                   26  
  42. #define     TYPE_KERNEL_OBJECT_IOCOMPLETION             27  
  43. #define     TYPE_KERNEL_OBJECT_FILE                     28  
  44. #define     TYPE_KERNEL_OBJECT_WMIGUID                  29  
  45. #define     TYPE_KERNEL_OBJECT_FILTERCONNECTIONPORT     30  
  46. #define     TYPE_KERNEL_OBJECT_FILTERCOMMUNICATIONPORT  31  
  47. #define     TYPE_KERNEL_OBJECT_OTHER                    32  

 



Kernel Object Handle의 Type을 구하는 함수입니다.

view plaincopy to clipboardprint?

  1. NTSTATUS GetHandleType(IN HANDLE hHandle, OUT TYPE_KERNEL_OBJECT *pnObject)  
  2. {  
  3.     NTSTATUS                        nRtnValue   = 0;  
  4.     HMODULE                         hModule     = NULL;  
  5.     LPFN_ZwQueryObject              pfn         = NULL;  
  6.     ULONG                           nSize       = 0;  
  7.     LPBYTE                          pBuf        = NULL;  
  8.     PPUBLIC_OBJECT_TYPE_INFORMATION pstInfo     = NULL;  
  9.     PUBLIC_OBJECT_TYPE_INFORMATION  stInfo      = {0,};  
  10.   
  11.     if (NULL == pnObject)  
  12.     {  
  13.         nRtnValue = STATUS_INVALID_PARAMETER;  
  14.         goto FINAL;  
  15.     }  
  16.   
  17.     (*pnObject) = TYPE_KERNEL_OBJECT_UNKNOWN;  
  18.   
  19.     // 만들어 놓은 아래 함수가 없다면,  
  20.     // hModule = ::LoadLibraryEx(TEXT("ntdll.dll"), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);  
  21.     // 를 사용한다.  
  22.     hModule = LoadLibraryFromSystem(TEXT("ntdll.dll"));  
  23.     if (NULL == hModule)  
  24.     {  
  25.         nRtnValue = STATUS_OBJECT_PATH_NOT_FOUND;  
  26.         goto FINAL;  
  27.     }  
  28.   
  29.     pfn = (LPFN_ZwQueryObject)::GetProcAddress(hModule, "ZwQueryObject");  
  30.     if (NULL == pfn)  
  31.     {  
  32.         nRtnValue = STATUS_PROCEDURE_NOT_FOUND;  
  33.         goto FINAL;  
  34.     }  
  35.   
  36.     pstInfo = &stInfo;  
  37.     nRtnValue = (*pfn)(hHandle, 2, pstInfo, sizeof(stInfo), &nSize);    // 2 : ObjectTypeInformation  
  38.     if (STATUS_INFO_LENGTH_MISMATCH == nRtnValue)  
  39.     {  
  40.         pBuf = new BYTE[nSize];  
  41.         if (NULL == pBuf)  
  42.         {  
  43.             nRtnValue = STATUS_NO_MEMORY;  
  44.             goto FINAL;  
  45.         }  
  46.   
  47.         ZeroMemory(pBuf, sizeof(BYTE)*nSize);  
  48.         pstInfo = (PPUBLIC_OBJECT_TYPE_INFORMATION)pBuf;  
  49.   
  50.         nRtnValue = (*pfn)(hHandle, 2, pstInfo, nSize, &nSize);         // 2 : ObjectTypeInformation  
  51.     }  
  52.   
  53.     if (STATUS_SUCCESS != nRtnValue)  
  54.     {  
  55.         goto FINAL;  
  56.     }  
  57.   
  58.     if (NULL == pstInfo->TypeName.Buffer)  
  59.     {  
  60.         nRtnValue = STATUS_INVALID_PARAMETER;  
  61.         goto FINAL;  
  62.     }  
  63.   
  64.     // 빈도 많음  
  65.     if (0 == _tcsicmp(TEXT("Key"), pstInfo->TypeName.Buffer))  
  66.         (*pnObject) = TYPE_KERNEL_OBJECT_KEY;  
  67.     else if (0 == _tcsicmp(TEXT("File"), pstInfo->TypeName.Buffer))  
  68.         (*pnObject) = TYPE_KERNEL_OBJECT_FILE;  
  69.     else if (0 == _tcsicmp(TEXT("Thread"), pstInfo->TypeName.Buffer))  
  70.         (*pnObject) = TYPE_KERNEL_OBJECT_THREAD;  
  71.     else if (0 == _tcsicmp(TEXT("Directory"), pstInfo->TypeName.Buffer))  
  72.         (*pnObject) = TYPE_KERNEL_OBJECT_DIRECTORY;  
  73.     else if (0 == _tcsicmp(TEXT("Section"), pstInfo->TypeName.Buffer))  
  74.         (*pnObject) = TYPE_KERNEL_OBJECT_SECTION;  
  75.     else if (0 == _tcsicmp(TEXT("Event"), pstInfo->TypeName.Buffer))  
  76.         (*pnObject) = TYPE_KERNEL_OBJECT_EVENT;  
  77.     else if (0 == _tcsicmp(TEXT("Mutant"), pstInfo->TypeName.Buffer))  
  78.         (*pnObject) = TYPE_KERNEL_OBJECT_MUTANT;  
  79.     else if (0 == _tcsicmp(TEXT("Port"), pstInfo->TypeName.Buffer))  
  80.         (*pnObject) = TYPE_KERNEL_OBJECT_PORT;  
  81.     // 빈도 적음  
  82.     else if (0 == _tcsicmp(TEXT("KeyedEvent"), pstInfo->TypeName.Buffer))  
  83.         (*pnObject) = TYPE_KERNEL_OBJECT_KEYEDEVENT;  
  84.     else if (0 == _tcsicmp(TEXT("Token"), pstInfo->TypeName.Buffer))  
  85.         (*pnObject) = TYPE_KERNEL_OBJECT_TOKEN;  
  86.     else if (0 == _tcsicmp(TEXT("WindowStation"), pstInfo->TypeName.Buffer))  
  87.         (*pnObject) = TYPE_KERNEL_OBJECT_WINDOWSTATION;  
  88.     else if (0 == _tcsicmp(TEXT("Type"), pstInfo->TypeName.Buffer))  
  89.         (*pnObject) = TYPE_KERNEL_OBJECT_TYPE;  
  90.     else if (0 == _tcsicmp(TEXT("SymbolicLink"), pstInfo->TypeName.Buffer))  
  91.         (*pnObject) = TYPE_KERNEL_OBJECT_SYMBOLICLINK;  
  92.     else if (0 == _tcsicmp(TEXT("Process"), pstInfo->TypeName.Buffer))  
  93.         (*pnObject) = TYPE_KERNEL_OBJECT_PROCESS;  
  94.     else if (0 == _tcsicmp(TEXT("Job"), pstInfo->TypeName.Buffer))  
  95.         (*pnObject) = TYPE_KERNEL_OBJECT_JOB;  
  96.     else if (0 == _tcsicmp(TEXT("DebugObject"), pstInfo->TypeName.Buffer))  
  97.         (*pnObject) = TYPE_KERNEL_OBJECT_DEBUGOBJECT;  
  98.     else if (0 == _tcsicmp(TEXT("EventPair"), pstInfo->TypeName.Buffer))  
  99.         (*pnObject) = TYPE_KERNEL_OBJECT_EVENTPAIR;  
  100.     else if (0 == _tcsicmp(TEXT("Callback"), pstInfo->TypeName.Buffer))  
  101.         (*pnObject) = TYPE_KERNEL_OBJECT_CALLBACK;  
  102.     else if (0 == _tcsicmp(TEXT("Semaphore"), pstInfo->TypeName.Buffer))  
  103.         (*pnObject) = TYPE_KERNEL_OBJECT_SEMAPHORE;  
  104.     else if (0 == _tcsicmp(TEXT("Timer"), pstInfo->TypeName.Buffer))  
  105.         (*pnObject) = TYPE_KERNEL_OBJECT_TIMER;  
  106.     else if (0 == _tcsicmp(TEXT("Profile"), pstInfo->TypeName.Buffer))  
  107.         (*pnObject) = TYPE_KERNEL_OBJECT_PROFILE;  
  108.     else if (0 == _tcsicmp(TEXT("Desktop"), pstInfo->TypeName.Buffer))  
  109.         (*pnObject) = TYPE_KERNEL_OBJECT_DESKTOP;  
  110.     else if (0 == _tcsicmp(TEXT("WaitablePort"), pstInfo->TypeName.Buffer))  
  111.         (*pnObject) = TYPE_KERNEL_OBJECT_WAITABLEPORT;  
  112.     else if (0 == _tcsicmp(TEXT("Adapter"), pstInfo->TypeName.Buffer))  
  113.         (*pnObject) = TYPE_KERNEL_OBJECT_ADAPTER;  
  114.     else if (0 == _tcsicmp(TEXT("Controller"), pstInfo->TypeName.Buffer))  
  115.         (*pnObject) = TYPE_KERNEL_OBJECT_CONTROLLER;  
  116.     else if (0 == _tcsicmp(TEXT("Device"), pstInfo->TypeName.Buffer))  
  117.         (*pnObject) = TYPE_KERNEL_OBJECT_DEVICE;  
  118.     else if (0 == _tcsicmp(TEXT("Driver"), pstInfo->TypeName.Buffer))  
  119.         (*pnObject) = TYPE_KERNEL_OBJECT_DRIVER;  
  120.     else if (0 == _tcsicmp(TEXT("IoCompletion"), pstInfo->TypeName.Buffer))  
  121.         (*pnObject) = TYPE_KERNEL_OBJECT_IOCOMPLETION;  
  122.     else if (0 == _tcsicmp(TEXT("WmiGuid"), pstInfo->TypeName.Buffer))  
  123.         (*pnObject) = TYPE_KERNEL_OBJECT_WMIGUID;  
  124.     else if (0 == _tcsicmp(TEXT("FilterConnectionPort"), pstInfo->TypeName.Buffer))  
  125.         (*pnObject) = TYPE_KERNEL_OBJECT_FILTERCONNECTIONPORT;  
  126.     else if (0 == _tcsicmp(TEXT("FilterCommunicationPort"), pstInfo->TypeName.Buffer))  
  127.         (*pnObject) = TYPE_KERNEL_OBJECT_FILTERCOMMUNICATIONPORT;  
  128.     else  
  129.         (*pnObject) = TYPE_KERNEL_OBJECT_OTHER;  
  130.   
  131. FINAL:  
  132.   
  133.     if (NULL != pBuf)  
  134.     {  
  135.         delete [] pBuf;  
  136.         pBuf = NULL;  
  137.     }  
  138.   
  139.     if (NULL != hModule)  
  140.     {  
  141.         ::FreeLibrary(hModule);  
  142.         hModule = NULL;  
  143.     }  
  144.   
  145.     return nRtnValue;  
  146. }  

 



Kernel Object Handle의 Name을 구하는 함수입니다.

view plaincopy to clipboardprint?

  1. NTSTATUS GetHandleObjectName(IN HANDLE hHandle, OUT LPTSTR lpszName, IN DWORD dwCchName)  
  2. {  
  3.     NTSTATUS                        nRtnValue   = 0;  
  4.     HMODULE                         hModule     = NULL;  
  5.     LPFN_ZwQueryObject              pfn         = NULL;  
  6.     ULONG                           nSize       = 0;  
  7.     LPBYTE                          pBuf        = NULL;  
  8.     PPUBLIC_OBJECT_TYPE_INFORMATION pstInfo     = NULL;  
  9.     PUBLIC_OBJECT_TYPE_INFORMATION  stInfo      = {0,};  
  10.   
  11.     if (NULL == lpszName)  
  12.     {  
  13.         nRtnValue = STATUS_INVALID_PARAMETER;  
  14.         goto FINAL;  
  15.     }  
  16.   
  17.     // 만들어 놓은 아래 함수가 없다면,  
  18.     // hModule = ::LoadLibraryEx(TEXT("ntdll.dll"), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);  
  19.     // 를 사용한다.  
  20.     hModule = LoadLibraryFromSystem(TEXT("ntdll.dll"));  
  21.     if (NULL == hModule)  
  22.     {  
  23.         nRtnValue = STATUS_OBJECT_PATH_NOT_FOUND;  
  24.         goto FINAL;  
  25.     }  
  26.   
  27.     pfn = (LPFN_ZwQueryObject)::GetProcAddress(hModule, "ZwQueryObject");  
  28.     if (NULL == pfn)  
  29.     {  
  30.         nRtnValue = STATUS_PROCEDURE_NOT_FOUND;  
  31.         goto FINAL;  
  32.     }  
  33.   
  34.     pstInfo = &stInfo;  
  35.     nRtnValue = (*pfn)(hHandle, 1, pstInfo, sizeof(stInfo), &nSize);    // 1 : ObjectNameInformation  
  36.     if (STATUS_INFO_LENGTH_MISMATCH == nRtnValue)  
  37.     {  
  38.         pBuf = new BYTE[nSize];  
  39.         if (NULL == pBuf)  
  40.         {  
  41.             nRtnValue = STATUS_NO_MEMORY;  
  42.             goto FINAL;  
  43.         }  
  44.   
  45.         ZeroMemory(pBuf, sizeof(BYTE)*nSize);  
  46.         pstInfo = (PPUBLIC_OBJECT_TYPE_INFORMATION)pBuf;  
  47.   
  48.         nRtnValue = (*pfn)(hHandle, 1, pstInfo, nSize, &nSize);         // 1 : ObjectNameInformation  
  49.     }  
  50.   
  51.     if (STATUS_SUCCESS == nRtnValue)  
  52.     {  
  53.         StringCchCopy(lpszName, dwCchName, pstInfo->TypeName.Buffer);  
  54.     }  
  55.   
  56. FINAL:  
  57.   
  58.     if (NULL != pBuf)  
  59.     {  
  60.         delete [] pBuf;  
  61.         pBuf = NULL;  
  62.     }  
  63.   
  64.     if (NULL != hModule)  
  65.     {  
  66.         ::FreeLibrary(hModule);  
  67.         hModule = NULL;  
  68.     }  
  69.   
  70.     return nRtnValue;  
  71. }  



위 두개의 함수를 이용하면, Process Explorer에서 나열해준 정보 (Type, Name)을 구할 수 있습니다.

출처: https://greenfishblog.tistory.com/20 [greenfish blog]