枚举进程中打开的句柄

转载:https://blez.wordpress.com/2012/09/17/enumerating-opened-handles-from-a-process/

因为NtQueryInformation确实缺少文档或示例,因此我会在一两年前杀死这段消息。
以下代码显示特定进程的所有已打开句柄。结合DuplicateHandle技巧,您也可以打开其文件(或其他句柄)。

 

#ifndef UNICODE
#define UNICODE
#endif
 
#include <windows.h>
#include <stdio.h>
 
#define NT_SUCCESS(x) ((x) >= 0)
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
 
#define SystemHandleInformation 16
#define ObjectBasicInformation 0
#define ObjectNameInformation 1
#define ObjectTypeInformation 2
 
typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
     ULONG SystemInformationClass,
     PVOID SystemInformation,
     ULONG SystemInformationLength,
     PULONG ReturnLength
     );
typedef NTSTATUS (NTAPI *_NtDuplicateObject)(
     HANDLE SourceProcessHandle,
     HANDLE SourceHandle,
     HANDLE TargetProcessHandle,
     PHANDLE TargetHandle,
     ACCESS_MASK DesiredAccess,
     ULONG Attributes,
     ULONG Options
     );
typedef NTSTATUS (NTAPI *_NtQueryObject)(
     HANDLE ObjectHandle,
     ULONG ObjectInformationClass,
     PVOID ObjectInformation,
     ULONG ObjectInformationLength,
     PULONG ReturnLength
     );
 
typedef struct _UNICODE_STRING {
     USHORT Length;
     USHORT MaximumLength;
     PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
 
typedef struct _SYSTEM_HANDLE {
     ULONG ProcessId;
     BYTE ObjectTypeNumber;
     BYTE Flags;
     USHORT Handle;
     PVOID Object;
     ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
 
typedef struct _SYSTEM_HANDLE_INFORMATION {
     ULONG HandleCount;
     SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
 
typedef enum _POOL_TYPE {
     NonPagedPool,
     PagedPool,
     NonPagedPoolMustSucceed,
     DontUseThisType,
     NonPagedPoolCacheAligned,
     PagedPoolCacheAligned,
     NonPagedPoolCacheAlignedMustS
} POOL_TYPE, *PPOOL_TYPE;
 
typedef struct _OBJECT_TYPE_INFORMATION {
     UNICODE_STRING Name;
     ULONG TotalNumberOfObjects;
     ULONG TotalNumberOfHandles;
     ULONG TotalPagedPoolUsage;
     ULONG TotalNonPagedPoolUsage;
     ULONG TotalNamePoolUsage;
     ULONG TotalHandleTableUsage;
     ULONG HighWaterNumberOfObjects;
     ULONG HighWaterNumberOfHandles;
     ULONG HighWaterPagedPoolUsage;
     ULONG HighWaterNonPagedPoolUsage;
     ULONG HighWaterNamePoolUsage;
     ULONG HighWaterHandleTableUsage;
     ULONG InvalidAttributes;
     GENERIC_MAPPING GenericMapping;
     ULONG ValidAccess;
     BOOLEAN SecurityRequired;
     BOOLEAN MaintainHandleCount;
     USHORT MaintainTypeList;
     POOL_TYPE PoolType;
     ULONG PagedPoolUsage;
     ULONG NonPagedPoolUsage;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
 
PVOID GetLibraryProcAddress( PSTR LibraryName, PSTR ProcName) {
     return GetProcAddress(GetModuleHandleA(LibraryName), ProcName);
}
 
void ErrorExit( LPTSTR lpszFunction) {
     // Retrieve the system error message for the last-error code
 
     LPVOID lpMsgBuf;
     LPVOID lpDisplayBuf;
     DWORD dw = GetLastError();
 
     FormatMessage(
         FORMAT_MESSAGE_ALLOCATE_BUFFER |
         FORMAT_MESSAGE_FROM_SYSTEM |
         FORMAT_MESSAGE_IGNORE_INSERTS,
         NULL,
         dw,
         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
         ( LPTSTR ) &lpMsgBuf,
         0, NULL );
 
     printf (( LPTSTR ) lpMsgBuf);
 
     LocalFree(lpMsgBuf);
     LocalFree(lpDisplayBuf);
     ExitProcess(dw);
}
 
void ShowErr() {
     CHAR errormsg[100];
     FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, errormsg, sizeof (errormsg), NULL);
     printf ( "ERROR: %s" , errormsg);
}
 
int wmain( int argc, WCHAR *argv[]) {
 
     _NtQuerySystemInformation NtQuerySystemInformation = GetLibraryProcAddress( "ntdll.dll" , "NtQuerySystemInformation" );
     _NtDuplicateObject NtDuplicateObject = GetLibraryProcAddress( "ntdll.dll" , "NtDuplicateObject" );
     _NtQueryObject NtQueryObject = GetLibraryProcAddress( "ntdll.dll" , "NtQueryObject" );
 
     NTSTATUS status;
     PSYSTEM_HANDLE_INFORMATION handleInfo;
     ULONG handleInfoSize = 0x10000;
     ULONG pid;
     HANDLE processHandle;
     ULONG i;
 
     if (argc < 2) {
         printf ( "Usage: handles [pid]\n" );
         return 1;
     }
 
     pid = _wtoi(argv[1]);
 
     if (!(processHandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid))) {
         printf ( "Could not open PID %d! (Don't try to open a system process.)\n" , pid);
         return 1;
     }
 
     handleInfo = (PSYSTEM_HANDLE_INFORMATION) malloc (handleInfoSize);
 
     // NtQuerySystemInformation won't give us the correct buffer size,
     //  so we guess by doubling the buffer size.
     while ((status = NtQuerySystemInformation(
         SystemHandleInformation,
         handleInfo,
         handleInfoSize,
         NULL
         )) == STATUS_INFO_LENGTH_MISMATCH)
         handleInfo = (PSYSTEM_HANDLE_INFORMATION) realloc (handleInfo, handleInfoSize *= 2);
 
     // NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH.
     if (!NT_SUCCESS(status)) {
         printf ( "NtQuerySystemInformation failed!\n" );
         return 1;
     }
 
     for (i = 0; i < handleInfo->HandleCount; i++) {
         SYSTEM_HANDLE handle = handleInfo->Handles[i];
         HANDLE dupHandle = NULL;
         POBJECT_TYPE_INFORMATION objectTypeInfo;
         PVOID objectNameInfo;
         UNICODE_STRING objectName;
         ULONG returnLength;
 
         // Check if this handle belongs to the PID the user specified.
         if (handle.ProcessId != pid)
             continue ;
 
         // Duplicate the handle so we can query it.
         if (!NT_SUCCESS(NtDuplicateObject(
             processHandle,
             ( void *) handle.Handle,
             GetCurrentProcess(),
             &dupHandle,
             0,
             0,
             0
             ))) {
 
             printf ( "[%#x] Error!\n" , handle.Handle);
             continue ;
         }
 
         // Query the object type.
         objectTypeInfo = (POBJECT_TYPE_INFORMATION) malloc (0x1000);
         if (!NT_SUCCESS(NtQueryObject(
             dupHandle,
             ObjectTypeInformation,
             objectTypeInfo,
             0x1000,
             NULL
             ))) {
 
             printf ( "[%#x] Error!\n" , handle.Handle);
             CloseHandle(dupHandle);
             continue ;
         }
 
         // Query the object name (unless it has an access of
         //   0x0012019f, on which NtQueryObject could hang.
         if (handle.GrantedAccess == 0x0012019f) {
 
             // We have the type, so display that.
             printf (
                 "[%#x] %.*S: (did not get name)\n" ,
                 handle.Handle,
                 objectTypeInfo->Name.Length / 2,
                 objectTypeInfo->Name.Buffer
                 );
 
             free (objectTypeInfo);
             CloseHandle(dupHandle);
             continue ;
         }
 
         objectNameInfo = malloc (0x1000);
         if (!NT_SUCCESS(NtQueryObject(
             dupHandle,
             ObjectNameInformation,
             objectNameInfo,
             0x1000,
             &returnLength
             ))) {
 
             // Reallocate the buffer and try again.
             objectNameInfo = realloc (objectNameInfo, returnLength);
             if (!NT_SUCCESS(NtQueryObject(
                 dupHandle,
                 ObjectNameInformation,
                 objectNameInfo,
                 returnLength,
                 NULL
                 ))) {
 
                 // We have the type name, so just display that.
                 printf (
                     "[%#x] %.*S: (could not get name)\n" ,
                     handle.Handle,
                     objectTypeInfo->Name.Length / 2,
                     objectTypeInfo->Name.Buffer
                     );
 
                 free (objectTypeInfo);
                 free (objectNameInfo);
                 CloseHandle(dupHandle);
                 continue ;
             }
         }
 
         // Cast our buffer into an UNICODE_STRING.
         objectName = *(PUNICODE_STRING)objectNameInfo;
 
         // Print the information!
         if (objectName.Length)
         {
             // The object has a name.
             printf (
                 "[%#x] %.*S: %.*S\n" ,
                 handle.Handle,
                 objectTypeInfo->Name.Length / 2,
                 objectTypeInfo->Name.Buffer,
                 objectName.Length / 2,
                 objectName.Buffer
                 );
         }
         else {
             // Print something else.
             printf (
                 "[%#x] %.*S: (unnamed)\n" ,
                 handle.Handle,
                 objectTypeInfo->Name.Length / 2,
                 objectTypeInfo->Name.Buffer
                 );
         }
 
         free (objectTypeInfo);
         free (objectNameInfo);
         CloseHandle(dupHandle);
     }
 
     free (handleInfo);
     CloseHandle(processHandle);
 
     return 0;
}

转载于:https://www.cnblogs.com/kuangke/p/11133741.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值