枚舉任意進程內核對象句柄的方法

原理:

調用ntdll的一個導出函數ZwQuerySystemInformation可以獲取一些重要信息,函數定義如下:

1 NTSTATUS WINAPI ZwQuerySystemInformation(
2   _In_       SYSTEM_INFORMATION_CLASS SystemInformationClass,
3   _Inout_    PVOID SystemInformation,
4   _In_       ULONG SystemInformationLength,
5   _Out_opt_  PULONG ReturnLength
6 );

不過msdn上說該函數在win8下已經不能使用了,用到的時候再說。

 重點關注該函數的第一個參數SYSTEM_INFORMATION_CLASS是一個結構體,具體定義如下:

typedef enum _SYSTEM_INFORMATION_CLASS {
   SystemBasicInformation,              // 0        Y        N
   SystemProcessorInformation,          // 1        Y        N
   SystemPerformanceInformation,        // 2        Y        N
   SystemTimeOfDayInformation,          // 3        Y        N
   SystemNotImplemented1,               // 4        Y        N
   SystemProcessesAndThreadsInformation, // 5       Y        N
   SystemCallCounts,                    // 6        Y        N
   SystemConfigurationInformation,      // 7        Y        N
   SystemProcessorTimes,                // 8        Y        N
   SystemGlobalFlag,                    // 9        Y        Y
   SystemNotImplemented2,               // 10       Y        N
   SystemModuleInformation,             // 11       Y        N
   SystemLockInformation,               // 12       Y        N
   SystemNotImplemented3,               // 13       Y        N
   SystemNotImplemented4,               // 14       Y        N
   SystemNotImplemented5,               // 15       Y        N
   SystemHandleInformation,             // 16       Y        N
   SystemObjectInformation,             // 17       Y        N
   SystemPagefileInformation,           // 18       Y        N
   SystemInstructionEmulationCounts,    // 19       Y        N
   SystemInvalidInfoClass1,             // 20
   SystemCacheInformation,              // 21       Y        Y
   SystemPoolTagInformation,            // 22       Y        N
   SystemProcessorStatistics,           // 23       Y        N
   SystemDpcInformation,                // 24       Y        Y
   SystemNotImplemented6,               // 25       Y        N
   SystemLoadImage,                     // 26       N        Y
   SystemUnloadImage,                   // 27       N        Y
   SystemTimeAdjustment,                // 28       Y        Y
   SystemNotImplemented7,               // 29       Y        N
   SystemNotImplemented8,               // 30       Y        N
   SystemNotImplemented9,               // 31       Y        N
   SystemCrashDumpInformation,          // 32       Y        N
   SystemExceptionInformation,          // 33       Y        N
   SystemCrashDumpStateInformation,     // 34       Y        Y/N
   SystemKernelDebuggerInformation,     // 35       Y        N
   SystemContextSwitchInformation,      // 36       Y        N
   SystemRegistryQuotaInformation,      // 37       Y        Y
   SystemLoadAndCallImage,              // 38       N        Y
   SystemPrioritySeparation,            // 39       N        Y
   SystemNotImplemented10,              // 40       Y        N
   SystemNotImplemented11,              // 41       Y        N
   SystemInvalidInfoClass2,             // 42
   SystemInvalidInfoClass3,             // 43
   SystemTimeZoneInformation,           // 44       Y        N
   SystemLookasideInformation,          // 45       Y        N
   SystemSetTimeSlipEvent,              // 46       N        Y
   SystemCreateSession,                 // 47       N        Y
   SystemDeleteSession,                 // 48       N        Y
   SystemInvalidInfoClass4,             // 49
    SystemRangeStartInformation,         // 50       Y        N
    SystemVerifierInformation,           // 51       Y        Y
    SystemAddVerifier,                   // 52       N        Y
    SystemSessionProcessesInformation    // 53       Y        N
} SYSTEM_INFORMATION_CLASS;

16號SystemHandleInformation即可獲得系統句柄信息。

獲取所以進程句柄後並不能直接操作這些句柄,因爲每個進程的句柄都是獨立存在的,所以需要調用DuplicateHandle將需要的進程句柄Dump到當前進程然後再進行操作,

BOOL WINAPI DuplicateHandle(
  _In_   HANDLE hSourceProcessHandle,
  _In_   HANDLE hSourceHandle,
  _In_   HANDLE hTargetProcessHandle,
  _Out_  LPHANDLE lpTargetHandle,
  _In_   DWORD dwDesiredAccess,
  _In_   BOOL bInheritHandle,
  _In_   DWORD dwOptions
);

得到的lpTargetHandle保存着目標進程的句柄。然後調用NtQueryObject可以獲取句柄的類型(mutex、File、Section等),以及句柄名稱等等。

NTSTATUS NtQueryObject(
  _In_opt_   HANDLE Handle,
  _In_       OBJECT_INFORMATION_CLASS ObjectInformationClass,
  _Out_opt_  PVOID ObjectInformation,
  _In_       ULONG ObjectInformationLength,
  _Out_opt_  PULONG ReturnLength
);

說了一大堆了,開始寫代碼吧,由於這裏需要很多結構信息,因此我寫了一個頭文件來定義這些結構:

objEnum.h:
 1 #include "ntsecapi.h"
 2 #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
 3 typedef NTSTATUS (WINAPI *ZWQUERYSYSTEMINFORMATION)(DWORD, PVOID, DWORD, PDWORD);
 4 typedef enum _OBJECT_INFORMATION_CLASS {
 5      ObjectBasicInformation,
 6           ObjectNameInformation,
 7           ObjectTypeInformation,
 8           ObjectAllInformation,
 9           ObjectDataInformation,
10 } OBJECT_INFORMATION_CLASS;
11 typedef NTSTATUS (NTAPI *NTQUERYOBJECT)(
12      HANDLE Handle,
13      OBJECT_INFORMATION_CLASS ObjectInformationClass,
14      PVOID ObjectInformation,
15      ULONG ObjectInformationLength,
16      PULONG ReturnLength
17      );
18 typedef struct _OBJECT_NAME_INFORMATION {
19      UNICODE_STRING Name;
20 } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
21 typedef struct _SYSTEM_HANDLE_INFORMATION
22 {
23      ULONG ProcessId;
24      UCHAR ObjectTypeNumber;
25      UCHAR Flags;
26      USHORT Handle;
27      PVOID Object;
28      ACCESS_MASK GrantedAccess;
29 }SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
30 
31 typedef struct _SYSTEM_HANDLE_INFORMATION_EX
32 {
33      ULONG NumberOfHandles;
34      SYSTEM_HANDLE_INFORMATION Information[1];
35 }SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
36 #define SystemHandleInformation 0x10  // 16

然後是兩個函數:

1、GetSystemProcessHandeleInfo()可以獲取當前系統的所有內核對象句柄信息並返回。

 1 LPVOID GetSystemProcessHandleInfo()
 2 {
 3      ULONG cbBuffer = 0x4000;
 4      LPVOID pBuffer = NULL;
 5      NTSTATUS sts;
 6      do
 7      {
 8           pBuffer = malloc(cbBuffer);
 9           if(pBuffer == NULL)
10           {
11                cout<<"error alloc memory:"<<GetLastError()<<endl;
12                return NULL;
13           }
14           memset(pBuffer,0,cbBuffer);
15          
16           sts = ZwQuerySystemInformation(SystemHandleInformation, pBuffer, cbBuffer, NULL);
17           if(sts == STATUS_INFO_LENGTH_MISMATCH)
18           {
19                free(pBuffer);
20                pBuffer = NULL;
21                cbBuffer = cbBuffer +0x4000; // 初始分配的空間不足+4000h
22           }
23      }while(sts == STATUS_INFO_LENGTH_MISMATCH);
24      return pBuffer;
25 }
 2.EnumObjInfo()獲取從返回的內核對象句柄信息中取出指定pid,指定句柄類型的內核對象,並打印:
void EnumObjInfo(LPVOID pBuffer,DWORD pid)
 {
      char szType[128] = {0};
      char szName[512] = {0};
      DWORD dwFlags = 0;
      POBJECT_NAME_INFORMATION pNameInfo;
      POBJECT_NAME_INFORMATION pNameType;
      PSYSTEM_HANDLE_INFORMATION_EX pInfo = (PSYSTEM_HANDLE_INFORMATION_EX)pBuffer;
      ULONG OldPID = 0;
      for(DWORD i = 0; i < pInfo->NumberOfHandles; i++)
      {
           if(OldPID != pInfo->Information[i].ProcessId)
           {
               if(pInfo->Information[i].ProcessId==pid)
                {
                    
                     HANDLE newHandle;
                     DuplicateHandle(OpenProcess(PROCESS_ALL_ACCESS,FALSE,pInfo->Information[i].ProcessId),(HANDLE)pInfo->Information[i].Handle,GetCurrentProcess(),&newHandle,DUPLICATE_SAME_ACCESS,FALSE,DUPLICATE_SAME_ACCESS);
                     NTSTATUS status1=NtQueryObject(newHandle, ObjectNameInformation, szName, 512, &dwFlags);
                     NTSTATUS status2=NtQueryObject(newHandle, ObjectTypeInformation, szType, 128, &dwFlags);
                     if(strcmp(szName,"")&&strcmp(szType,"")&&status1!=0xc0000008&&status2!=0xc0000008)
                     {
                          pNameInfo = (POBJECT_NAME_INFORMATION)szName; 
pNameType = (POBJECT_NAME_INFORMATION)szType; printf("%wZ ",pNameType); printf("%wZ \n",pNameInfo); } } } }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章