zoukankan      html  css  js  c++  java
  • 用Windows Native API枚举所有句柄及查找文件句柄对应文件名的方法

    枚举所有句柄的方法

    由于windows并没有给出枚举所有句柄所用到的API,和进程所拥有的句柄相关的只有GetProcessHandleCount这个函数,然而这个函数只能获取到和进程相关的句柄数,不能获取到实际的句柄,要获得句柄,我们必须使用未公开的Native API才可以。
     
    PS:网上有很多关于这类的方法,但几乎都是抄来抄去,很多连编译都过不了就直接放上去了(囧)。我整理了一下方法,实测在win10和win7都可以用。
    NTSTATUS WINAPI NtQuerySystemInformation(
      _In_      SYSTEM_INFORMATION_CLASS SystemInformationClass,
      _Inout_   PVOID                    SystemInformation,
      _In_      ULONG                    SystemInformationLength,
      _Out_opt_ PULONG                   ReturnLength
    );
    枚举的关键是使用NtQuerySystemInformation(旧版本是ZwQuerySystemInformation)这个方法
     
    但MSDN上并没有把这个函数的第一个参数的枚举值给全,而且Windows API所定义的枚举值也是MSDN上面列的几个而已,如下:
    typedef enum _SYSTEM_INFORMATION_CLASS {
        SystemBasicInformation = 0,
        SystemPerformanceInformation = 2,
        SystemTimeOfDayInformation = 3,
        SystemProcessInformation = 5,
        SystemProcessorPerformanceInformation = 8,
        SystemInterruptInformation = 23,
        SystemExceptionInformation = 33,
        SystemRegistryQuotaInformation = 37,
        SystemLookasideInformation = 45,
        SystemPolicyInformation = 134,
    } SYSTEM_INFORMATION_CLASS;
    这几个值的定义在MSDN上都有,具体可以在上面给的链接的文档查到,这里就不列了。这些枚举值都是可以拿来指定NtQuerySystemInformation所查询的内容
     
    然而所给到的枚举值并没有我们想要的枚举句柄的功能,这个时候只能求助于强大的搜索引擎了,我们可以查到比较完整的SYSTEM_INFORMATION_CLASS的定义是下面的列表
    typedef enum _SYSTEM_INFORMATION_CLASS {
        SystemBasicInformation,
        SystemProcessorInformation,             
        SystemPerformanceInformation,
        SystemTimeOfDayInformation,
        SystemPathInformation,
        SystemProcessInformation,
        SystemCallCountInformation,
        SystemDeviceInformation,
        SystemProcessorPerformanceInformation,
        SystemFlagsInformation,
        SystemCallTimeInformation,
        SystemModuleInformation,
        SystemLocksInformation,
        SystemStackTraceInformation,
        SystemPagedPoolInformation,
        SystemNonPagedPoolInformation,
        SystemHandleInformation,
        SystemObjectInformation,
        SystemPageFileInformation,
        SystemVdmInstemulInformation,
        SystemVdmBopInformation,
        SystemFileCacheInformation,
        SystemPoolTagInformation,
        SystemInterruptInformation,
        SystemDpcBehaviorInformation,
        SystemFullMemoryInformation,
        SystemLoadGdiDriverInformation,
        SystemUnloadGdiDriverInformation,
        SystemTimeAdjustmentInformation,
        SystemSummaryMemoryInformation,
        SystemMirrorMemoryInformation,
        SystemPerformanceTraceInformation,
        SystemObsolete0,
        SystemExceptionInformation,
        SystemCrashDumpStateInformation,
        SystemKernelDebuggerInformation,
        SystemContextSwitchInformation,
        SystemRegistryQuotaInformation,
        SystemExtendServiceTableInformation,
        SystemPrioritySeperation,
        SystemVerifierAddDriverInformation,
        SystemVerifierRemoveDriverInformation,
        SystemProcessorIdleInformation,
        SystemLegacyDriverInformation,
        SystemCurrentTimeZoneInformation,
        SystemLookasideInformation,
        SystemTimeSlipNotification,
        SystemSessionCreate,
        SystemSessionDetach,
        SystemSessionInformation,
        SystemRangeStartInformation,
        SystemVerifierInformation,
        SystemVerifierThunkExtend,
        SystemSessionProcessInformation,
        SystemLoadGdiDriverInSystemSpace,
        SystemNumaProcessorMap,
        SystemPrefetcherInformation,
        SystemExtendedProcessInformation,
        SystemRecommendedSharedDataAlignment,
        SystemComPlusPackage,
        SystemNumaAvailableMemory,
        SystemProcessorPowerInformation,
        SystemEmulationBasicInformation,
        SystemEmulationProcessorInformation,
        SystemExtendedHandleInformation,
        SystemLostDelayedWriteInformation,
        SystemBigPoolInformation,
        SystemSessionPoolTagInformation,
        SystemSessionMappedViewInformation,
        SystemHotpatchInformation,
        SystemObjectSecurityMode,
        SystemWatchdogTimerHandler,
        SystemWatchdogTimerInformation,
        SystemLogicalProcessorInformation,
        SystemWow64SharedInformation,
        SystemRegisterFirmwareTableInformationHandler,
        SystemFirmwareTableInformation,
        SystemModuleInformationEx,
        SystemVerifierTriageInformation,
        SystemSuperfetchInformation,
        SystemMemoryListInformation,
        SystemFileCacheInformationEx,
        MaxSystemInfoClass  // MaxSystemInfoClass should always be the last enum
    } SYSTEM_INFORMATION_CLASS;
    注意看到第17项(枚举值16)的SystemHandleInformation,这就是我们想要的东西,通过这个值传入NtQuerySystemInformation,然后在NtQuerySystemInformation的函数的第二项放入缓存空间长度,第三项放入缓存空间的指针即可。
     
    现在我们要确定缓存区的类型了。如果我们传入SystemHandleInformation,那么NtQuerySystemInformation将会返回下面这个结构
    typedef struct _SYSTEM_HANDLE_INFORMATION_EX
    {
        ULONG NumberOfHandles;
        SYSTEM_HANDLE_INFORMATION Information[655360];//注意655360这个值是我自己定义的,你们可以自己定义其他的常量值
    }SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
     
    其中,SYSTEM_HANDLE_INFORMATION的定义是:
    typedef struct _SYSTEM_HANDLE_INFORMATION
    {
        ULONG ProcessId;//进程标识符 
        UCHAR ObjectTypeNumber;//打开的对象的类型
        UCHAR Flags;//句柄属性标志
        USHORT Handle;//句柄数值,在进程打开的句柄中唯一标识某个句柄
        PVOID Object;//这个就是句柄对应的EPROCESS的地址
        ACCESS_MASK GrantedAccess;//句柄对象的访问权限
    }SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
    注意到这里有个很奇怪的地方,就是Handle值的类型是USHORT的,然而HANDLE的定义是void *,在32位上是4个字节,在64位上是8个字节。这就告诉我们,我们只能枚举到一个进程的0~65535个句柄值, 但是我们从Windows Internals这本书里面可以知道,现在Windows每个进程的句柄值已经可以到16000000以上了(虽然不会用到那么多)。
     
    这样我们就可以根据ProcessId来获取我们感兴趣的进程的句柄值了,但是这里也有一个问题,虽然ProcessId的类型是ULONG,但是也只能枚举到16位以下的ProcessId的值,也就是枚举到的最大ProcessId值是65535,如果我们的程序的ProcessId大于65535,我们就不能枚举到这些进程所创建的句柄了。(这就是Undocument的函数不可靠的体现了)。
     
    ObjectTypeNumber是我们想要的句柄值的类型,但是我暂时还无法找到关于这个值的详细资料,只是在windows driver里面查到了这个东西ObReferenceObjectByHandle,但是我现在想在ring3层把问题解决,暂时先不考虑驱动。事实上我们可以在Process Explorer里面根据把句柄值一个一个对应然后找到相应类型,比如下图:

    我们可以看到获知句柄值为0x4时,对应的值是Type是Key

    我们再来看下我们取到的Info的ObjectType是7,也就是说,我们的Key的类型值就是7

    同理我们也可以找到File类型的ObjectType是35
     
     
     
    我无法确定这个值是否会跟着系统不同而改变,如果要使用这个方法,请一定要先测试一下。
     
    接下来的事情就很好办了,我们只要把NtQuerySystemInformation从NtDll.dll里面拉出来就可以了,我们可以写出这样的代码:
    //头文件引#include <winternl.h>
    #define SystemHandleInformation 0x10
    typedef DWORD(WINAPI *NTQUERYSYSTEMINFORMATION)(DWORD, PVOID, DWORD, PDWORD);
    HMODULE hNtDll = LoadLibrary(L"ntdll.dll");
    NTQUERYSYSTEMINFORMATION NtQuerySystemInformation =
            (NTQUERYSYSTEMINFORMATION)GetProcAddress(hNtDll, "NtQuerySystemInformation");
    ULONG cbBuffer = sizeof(SYSTEM_HANDLE_INFORMATION_EX);
    LPVOID pBuffer = (LPVOID)malloc(cbBuffer);
    if (pBuffer)
    {
           NtQuerySystemInformation(SystemHandleInformation, pBuffer, cbBuffer, NULL);
           PSYSTEM_HANDLE_INFORMATION_EX pInfo = (PSYSTEM_HANDLE_INFORMATION_EX)pBuffer;
           for (ULONG r = 0; r < pInfo->NumberOfHandles; r++)
           {
               //dosomething
           }
            
        free(pBuffer);
    }
    FreeModule(hNtDll);
     
    Native API其他用法举例:查找文件句柄文件名的方法

    有时候我们想查找句柄的所对应的信息,比如我之前就遇到了一个需要查找文件句柄所对应文件名的方法,这个时候也需要Native API来完成,需要用到ZwQueryInformationFile这个方法
    NTSTATUS ZwQueryInformationFile(
      _In_  HANDLE                 FileHandle,
      _Out_ PIO_STATUS_BLOCK       IoStatusBlock,
      _Out_ PVOID                  FileInformation,
      _In_  ULONG                  Length,
      _In_  FILE_INFORMATION_CLASS FileInformationClass
    );
    其中第一个参数是我们要查询的文件句柄,信息可以存放在FileInformation指向的内存中,这个内存的长度由Length指定。
     
    现在我们来看下第二个参数IoStatusBlock的类型IO_STATUS_BLOCK
    typedef struct _IO_STATUS_BLOCK {
      union {
        NTSTATUS Status;
        PVOID    Pointer;
      };
      ULONG_PTR Information;
    } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
     
    Pointer是个保留项,第一项就是指定IRP's I/O的返回值,这个值我们可以不用
     
    最后一个参数是FILE_INFORMATION_CLASS类型的一个数,这个数可以拿来指定ZwQueryInformationFile所查询的内容(就像NtQuerySystemInformation的那一堆枚举值也是用来指定NtQuerySystemInformation所查询的内容一样),这个值在MSDN有完整的定义,但在VS自带的SDK里面却没有。
    typedef enum _FILE_INFORMATION_CLASS { 
      FileDirectoryInformation                 = 1,
      FileFullDirectoryInformation,
      FileBothDirectoryInformation,
      FileBasicInformation,
      FileStandardInformation,
      FileInternalInformation,
      FileEaInformation,
      FileAccessInformation,
      FileNameInformation,
      FileRenameInformation,
      FileLinkInformation,
      FileNamesInformation,
      FileDispositionInformation,
      FilePositionInformation,
      FileFullEaInformation,
      FileModeInformation,
      FileAlignmentInformation,
      FileAllInformation,
      FileAllocationInformation,
      FileEndOfFileInformation,
      FileAlternateNameInformation,
      FileStreamInformation,
      FilePipeInformation,
      FilePipeLocalInformation,
      FilePipeRemoteInformation,
      FileMailslotQueryInformation,
      FileMailslotSetInformation,
      FileCompressionInformation,
      FileObjectIdInformation,
      FileCompletionInformation,
      FileMoveClusterInformation,
      FileQuotaInformation,
      FileReparsePointInformation,
      FileNetworkOpenInformation,
      FileAttributeTagInformation,
      FileTrackingInformation,
      FileIdBothDirectoryInformation,
      FileIdFullDirectoryInformation,
      FileValidDataLengthInformation,
      FileShortNameInformation,
      FileIoCompletionNotificationInformation,
      FileIoStatusBlockRangeInformation,
      FileIoPriorityHintInformation,
      FileSfioReserveInformation,
      FileSfioVolumeInformation,
      FileHardLinkInformation,
      FileProcessIdsUsingFileInformation,
      FileNormalizedNameInformation,
      FileNetworkPhysicalNameInformation,
      FileIdGlobalTxDirectoryInformation,
      FileIsRemoteDeviceInformation,
      FileUnusedInformation,
      FileNumaNodeInformation,
      FileStandardLinkInformation,
      FileRemoteProtocolInformation,
      FileRenameInformationBypassAccessCheck,
      FileLinkInformationBypassAccessCheck,
      FileVolumeNameInformation,
      FileIdInformation,
      FileIdExtdDirectoryInformation,
      FileReplaceCompletionInformation,
      FileHardLinkFullIdInformation,
          FileIdExtdBothDirectoryInformation,
      FileMaximumInformation
    } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
     
    在我们的例子中,我们需要用到的枚举值是FileNameInformation(枚举值9)
     
    具体使用也像 一样,先从ntdll.dll里面导出来,然后把参数往里面填就好了,在这里我先定义一个缓冲区:
    typedef struct _NM_INFO
    {
        HANDLE   hFile;
        FILE_NAME_INFORMATION Info;
    } NM_INFO, *PNM_INFO;
     
    FILE_NAME_INFORMATION结构:
    typedef struct _FILE_NAME_INFORMATION {
        ULONG FileNameLength;
        WCHAR FileName[256];//256我自己定的,可以改成其他的,只要够放位置就行
    } FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
     
    调用API:
    NM_INFO nmInfo = { 0 };
    nmInfo.hFile = hFile;    
    PNM_INFO         NmInfo = (PNM_INFO)lpParameter;
    IO_STATUS_BLOCK IoStatus;
    ZWQUERYINFORMATIONFILE ZwQueryInformationFile =
            (ZWQUERYINFORMATIONFILE)GetProcAddress(hNtDll, "ZwQueryInformationFile");
    ZwQueryInformationFile(NmInfo->hFile, &IoStatus, &NmInfo->Info, 256, FILE_INFORMATION_CLASS::FileNameInformation);
     
    注意查询出来的FileNameLength是字节数,而不是WCHAR数组的最大偏移值,在这里WCHAR的最大偏移值应该是512,因为WCHAR是两个字节的
     
     
    例子:找出所有文件句柄,并且把对应文件名含有ABC的句柄关掉

    注意我把FILE_INFORMATION_CLASS改了个名字,改成了RFILE_INFORMATION_CLASS,这是因为SDK里面已经有了一个FILE_INFORMATION_CLASS了,而且我还把第一个枚举值给改了个名字,如果用以前的那个不知道为啥VS不给编译通过。
     
    #include <afx.h>
    #include <winternl.h>
    typedef DWORD(WINAPI *NTQUERYSYSTEMINFORMATION)(DWORD, PVOID, DWORD, PDWORD);
    typedef struct _SYSTEM_HANDLE_INFORMATION
    {
        ULONG ProcessId;
        UCHAR ObjectTypeNumber;
        UCHAR Flags;
        USHORT Handle;
        PVOID Object;
        ACCESS_MASK GrantedAccess;
    }SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
    #define STATUS_INFO_LENGTH_MISMATCH 0x004
    typedef struct _SYSTEM_HANDLE_INFORMATION_EX
    {
        ULONG NumberOfHandles;
        SYSTEM_HANDLE_INFORMATION Information[165536];
    }SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
    #define SystemHandleInformation 0x10  // 16
    typedef struct _FILE_NAME_INFORMATION {
        ULONG FileNameLength;
        WCHAR FileName[256];
    } FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
    typedef struct _NM_INFO
    {
        HANDLE   hFile;
        FILE_NAME_INFORMATION Info;
    } NM_INFO, *PNM_INFO;
    typedef enum _RFILE_INFORMATION_CLASS {
        FileDirectoryInformation1 = 1,
        FileFullDirectoryInformation,
        FileBothDirectoryInformation,
        FileBasicInformation,
        FileStandardInformation,
        FileInternalInformation,
        FileEaInformation,
        FileAccessInformation,
        FileNameInformation,
        FileRenameInformation,
        FileLinkInformation,
        FileNamesInformation,
        FileDispositionInformation,
        FilePositionInformation,
        FileFullEaInformation,
        FileModeInformation,
        FileAlignmentInformation,
        FileAllInformation,
        FileAllocationInformation,
        FileEndOfFileInformation,
        FileAlternateNameInformation,
        FileStreamInformation,
        FilePipeInformation,
        FilePipeLocalInformation,
        FilePipeRemoteInformation,
        FileMailslotQueryInformation,
        FileMailslotSetInformation,
        FileCompressionInformation,
        FileObjectIdInformation,
        FileCompletionInformation,
        FileMoveClusterInformation,
        FileQuotaInformation,
        FileReparsePointInformation,
        FileNetworkOpenInformation,
        FileAttributeTagInformation,
        FileTrackingInformation,
        FileIdBothDirectoryInformation,
        FileIdFullDirectoryInformation,
        FileValidDataLengthInformation,
        FileShortNameInformation,
        FileIoCompletionNotificationInformation,
        FileIoStatusBlockRangeInformation,
        FileIoPriorityHintInformation,
        FileSfioReserveInformation,
        FileSfioVolumeInformation,
        FileHardLinkInformation,
        FileProcessIdsUsingFileInformation,
        FileNormalizedNameInformation,
        FileNetworkPhysicalNameInformation,
        FileIdGlobalTxDirectoryInformation,
        FileIsRemoteDeviceInformation,
        FileUnusedInformation,
        FileNumaNodeInformation,
        FileStandardLinkInformation,
        FileRemoteProtocolInformation,
        FileRenameInformationBypassAccessCheck,
        FileLinkInformationBypassAccessCheck,
        FileVolumeNameInformation,
        FileIdInformation,
        FileIdExtdDirectoryInformation,
        FileReplaceCompletionInformation,
        FileHardLinkFullIdInformation,
        FileIdExtdBothDirectoryInformation,
        FileMaximumInformation
    } RFILE_INFORMATION_CLASS, *PRFILE_INFORMATION_CLASS;
    typedef NTSTATUS(WINAPI *ZWQUERYINFORMATIONFILE)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, RFILE_INFORMATION_CLASS);
    CString GetFileName(HMODULE hNtDll, PNM_INFO lpParameter)
    {
        PNM_INFO         NmInfo = (PNM_INFO)lpParameter;
        IO_STATUS_BLOCK IoStatus;
        ZWQUERYINFORMATIONFILE ZwQueryInformationFile =
            (ZWQUERYINFORMATIONFILE)GetProcAddress(hNtDll, "ZwQueryInformationFile");
        ZwQueryInformationFile(NmInfo->hFile, &IoStatus, &NmInfo->Info, 256, RFILE_INFORMATION_CLASS::FileNameInformation);
        if (NmInfo->Info.FileNameLength != 0)
        {
            CString str;
            str.Append(NmInfo->Info.FileName, NmInfo->Info.FileNameLength / sizeof(WCHAR));
            return str;
        }
        return CString();
    }
    extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/,
        LPTSTR /*lpCmdLine*/, int nShowCmd)
    {
        HMODULE hNtDll = LoadLibrary(L"ntdll.dll");
        NTQUERYSYSTEMINFORMATION NtQuerySystemInformation =
            (NTQUERYSYSTEMINFORMATION)GetProcAddress(hNtDll, "ZwQuerySystemInformation");
        ULONG cbBuffer = sizeof(SYSTEM_HANDLE_INFORMATION_EX);
        LPVOID pBuffer = (LPVOID)malloc(cbBuffer);
        auto id=  GetCurrentProcessId();
        if (pBuffer)
        {
            NtQuerySystemInformation(SystemHandleInformation, pBuffer, cbBuffer, NULL);
            PSYSTEM_HANDLE_INFORMATION_EX pInfo = (PSYSTEM_HANDLE_INFORMATION_EX)pBuffer;
            for (ULONG r = 0; r < pInfo->NumberOfHandles; r++)
            {
                if (pInfo->Information[r].ObjectTypeNumber == 35)
                {
                    NM_INFO nmInfo = { 0 };
                    nmInfo.hFile = (HANDLE)pInfo->Information[r].Handle;
                    CString fileName = GetFileName(hNtDll, &nmInfo);
                    if (!fileName.IsEmpty())
                    {
                        if (fileName.Find(L"ABC") != -1)
                        {
                            CloseHandle(nmInfo.hFile);
                        }
                    }
                }
            }
            
            free(pBuffer);
        }
        FreeModule(hNtDll);
        return 0;
    }

     

     
  • 相关阅读:
    实现一个与内容合二为一的ActionBar动画效果
    hdoj 1506&amp;&amp;1505(City Game) dp
    remine chart2安装
    zoom的学习
    海哥:T2C时代的到来了,那么什么叫T2C?
    minhash算法
    动态创建按钮的JS
    socket编程在windows和linux下的区别
    http staus汇总
    MySQL HINT:Straight_JOIN
  • 原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/6932966.html
Copyright © 2011-2022 走看看