枚举任意进程内核对象句柄的方法

原理:

调用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); } } } }
posted @ 2013-09-07 10:38  Lamboy  阅读(3028)  评论(0编辑  收藏  举报