2014年6月25日星期三

枚举枚举系统/进程的句柄的信息

#include "stdafx.h"

/*
枚举一个进程的句柄信息。
这是一个基本的功能。

一直想做而没有做。
网上也有好多的代码。
今天算是实现了。

本文修改自微软的CppFileHandle工程。
有一定的可信度。

made by correy
made at 2014.06.25
homepage:http://correy.webs.com
*/

#pragma region Includes
#include <windows.h>
#include <assert.h>
#pragma endregion

#define STATUS_SUCCESS     ((NTSTATUS)0x00000000L)
#define STATUS_INFO_LENGTH_MISMATCH  ((NTSTATUS)0xc0000004L)

#include <winternl.h>

// Undocumented SYSTEM_INFORMATION_CLASS: SystemHandleInformation
const SYSTEM_INFORMATION_CLASS SystemHandleInformation = (SYSTEM_INFORMATION_CLASS)16;

// The NtQuerySystemInformation function and the structures that it returns are internal to the operating system and subject to change from one  release of Windows to another.
// To maintain the compatibility of your application, it is better not to use the function.
typedef NTSTATUS (WINAPI * PFN_NTQUERYSYSTEMINFORMATION)(
    IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
    OUT PVOID SystemInformation,
    IN ULONG SystemInformationLength,
    OUT PULONG ReturnLength OPTIONAL
    );

typedef NTSTATUS (WINAPI * PFN_ZwQueryObject)(
    __in_opt HANDLE  Handle,
    __in OBJECT_INFORMATION_CLASS  ObjectInformationClass,
    __out_bcount_opt(ObjectInformationLength) PVOID  ObjectInformation,
    __in ULONG  ObjectInformationLength,
    __out_opt PULONG  ReturnLength
    );


// Undocumented structure: SYSTEM_HANDLE_INFORMATION
typedef struct _SYSTEM_HANDLE 
{
    ULONG ProcessId;
    UCHAR ObjectTypeNumber;
    UCHAR Flags;
    USHORT Handle;
    PVOID Object;
    ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;

typedef struct _SYSTEM_HANDLE_INFORMATION 
{
    ULONG NumberOfHandles;
    SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;


////摘自:\wrk\WindowsResearchKernel-WRK\WRK-v1.2\public\sdk\inc\ntobapi.h
//typedef enum _OBJECT_INFORMATION_CLASS {
//    ObjectBasicInformation,
//    ObjectNameInformation,
//    ObjectTypeInformation,
//    ObjectTypesInformation,
//    ObjectHandleFlagInformation,
//    ObjectSessionInformation,
//    MaxObjectInfoClass  // MaxObjectInfoClass should always be the last enum
//} OBJECT_INFORMATION_CLASS;

//摘自:\wrk\WindowsResearchKernel-WRK\WRK-v1.2\public\sdk\inc\ntobapi.h
typedef struct _OBJECT_NAME_INFORMATION {               // ntddk wdm nthal
    UNICODE_STRING Name;                                // ntddk wdm nthal
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;   // ntddk wdm nthal


BOOL SetPrivilege(
    //HANDLE hToken,          // access token handle
    LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
    BOOL bEnablePrivilege   // to enable or disable privilege
    ) 
{
    TOKEN_PRIVILEGES tp;
    LUID luid;

    HANDLE hToken; // Get a token for this process. 
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 
    {
        return( FALSE ); 
    }

    if ( !LookupPrivilegeValue( 
        NULL,            // lookup privilege on local system
        lpszPrivilege,   // privilege to lookup 
        &luid ) )        // receives LUID of privilege
    {
        printf("LookupPrivilegeValue error: %u\n", GetLastError() ); 
        return FALSE; 
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    if (bEnablePrivilege)
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    else
        tp.Privileges[0].Attributes = 0;

    // Enable the privilege or disable all privileges.
    if ( !AdjustTokenPrivileges(hToken,  FALSE,  &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) )
    { 
        printf("AdjustTokenPrivileges error: %u\n", GetLastError() ); 
        return FALSE; 
    } 

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        printf("The token does not have the specified privilege. \n");
        return FALSE;
    } 

    return TRUE;
}


/*!
* Enumerate all handles of the specified process using undocumented APIs.
*/
DWORD EnumerateProcessHandles(ULONG pid)
{
    // The functions have no associated import library.
    // You must use the LoadLibrary and GetProcAddress functions to dynamically link to ntdll.dll.
    HINSTANCE hNtDll = LoadLibrary(_T("ntdll.dll"));
    assert(hNtDll != NULL);
    PFN_NTQUERYSYSTEMINFORMATION NtQuerySystemInformation = (PFN_NTQUERYSYSTEMINFORMATION)GetProcAddress(hNtDll, "NtQuerySystemInformation");
    assert(NtQuerySystemInformation != NULL);   

    PFN_ZwQueryObject NtQueryObject = (PFN_ZwQueryObject)GetProcAddress(hNtDll, "NtQueryObject");
    assert(NtQueryObject != NULL);   

    // NtQuerySystemInformation does not return the correct required buffer size if the buffer passed is too small.
    // Instead you must call the function while increasing the buffer size until the function no longer returns STATUS_INFO_LENGTH_MISMATCH.
    DWORD nSize = 4096, nReturn;
    PSYSTEM_HANDLE_INFORMATION pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION)HeapAlloc(GetProcessHeap(), 0, nSize); 
    while (NtQuerySystemInformation(SystemHandleInformation, pSysHandleInfo, nSize, &nReturn) == STATUS_INFO_LENGTH_MISMATCH)// Get system handle information.
    {
        HeapFree(GetProcessHeap(), 0, pSysHandleInfo);
        nSize += 4096;
        pSysHandleInfo = (SYSTEM_HANDLE_INFORMATION*)HeapAlloc(GetProcessHeap(), 0, nSize);
    }
    /*
    这个函数已经把整个系统的句柄信息都已经获取了。
    当然还有别的信息,如进程等。
    下面就是根据这些信息进行分类而已,如进程。

    其实这个函数可以显示整个系统的句柄的详细信息。
    */

    DWORD dwhandles = 0;//一个进程的所有的句柄数量。

    // Get the handle of the target process.
    // The handle will be used to duplicate the handles in the process.
    HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, FALSE, pid);
    if (hProcess == NULL)
    {
        _tprintf(_T("OpenProcess failed w/err 0x%08lx\n"), GetLastError());
        return -1;
    }
    /*
    打开这个函数需要权限,经测试系统进程提权也打不开。
    经测试:
    在XP上可以打开系统进程(system)。
    在Windows 7上,提权,以管理员(administrator)权限,甚至以服务的权限(NT AUTHORITY\SYSTEM)都不行,估计的会话隔离导致(可服务应该也在会话0,所以还是驱动的权限大)。
    */

    for (ULONG i = 0; i < pSysHandleInfo->NumberOfHandles; i++)
    {
        PSYSTEM_HANDLE pHandle = &(pSysHandleInfo->Handles[i]);

        //根据进程进行搜索。
        if (pHandle->ProcessId == pid) 
        {
            dwhandles++; // Increase the number of handles

            /*
            经测试发现:EtwRegistration(39)类型的句柄会失败。
            0x00000032 不支持该请求。 
            */
            HANDLE hCopy;// Duplicate the handle in the current process
            if (!DuplicateHandle(hProcess, (HANDLE)pHandle->Handle, GetCurrentProcess(), &hCopy, MAXIMUM_ALLOWED, FALSE, 0))
            {
                wprintf(L"DuplicateHandle fail with 0x%x,HANDLE:0x%x,ObjectTypeNumber:%d file:%s,fun:%s,line:%d\n", GetLastError(),pHandle->Handle, pHandle->ObjectTypeNumber, __FILE__,__FUNCTION__, __LINE__);
                continue;
            }
            
            /*
            在这里可以利用复制的句柄进行一些操作,如查询值。
            */
            ULONG  ObjectInformationLength = sizeof (OBJECT_NAME_INFORMATION) + 512;
            POBJECT_NAME_INFORMATION poni = (POBJECT_NAME_INFORMATION)HeapAlloc(GetProcessHeap(), 0, ObjectInformationLength);
            assert(poni != NULL);  

            ULONG  ReturnLength;

            /*
            如果句柄的类型是TOKEN,线程,进程等类型的,需要再特殊的处理。
            也就是说这个函数是查询不到的。
            */
            if (NtQueryObject(hCopy, (OBJECT_INFORMATION_CLASS)1, poni, ObjectInformationLength, &ReturnLength) != STATUS_SUCCESS)
            {
                wprintf(L"NtQueryObject fail!\n");
                HeapFree(GetProcessHeap(), 0, poni); 
                continue;
            }
            
            wprintf(L"HANDLE:0x%x, NAME:%wZ\n", pHandle->Handle, &poni->Name);

            HeapFree(GetProcessHeap(), 0, poni); 
            CloseHandle(hCopy);
        }

        //可以显示整个系统的句柄信息。
        //wprintf(L"PID:0x%x\n", pHandle->ProcessId);
        //wprintf(L"\tHANDLE:0x%x\n", pHandle->Handle);
    }

    CloseHandle(hProcess); 
    HeapFree(GetProcessHeap(), 0, pSysHandleInfo);// Clean up. 
    return dwhandles;// Return the number of handles in the process
}


int _tmain(int argc, _TCHAR* argv[])
{
    BOOL B = SetPrivilege(SE_DEBUG_NAME, TRUE);
    DWORD dwFiles = EnumerateProcessHandles(3264);//GetCurrentProcessId()
    return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <ntifs.h>
#include <windef.h>

/*
内核版的枚举系统/进程的句柄及其信息的代码。

made by correy
made at 2014.06.26
homepage:http://correy.webs.com
不当之处,请指正。
*/


//这些在WDK 7600.16385.1中没有定义,在WDK8.0中定义了.
//以下代码是解决办法之一.
#ifndef _In_
#define _Inout_
#define _In_
#define _In_opt_
#define _Out_opt_
#endif


//摘自:\wrk\WindowsResearchKernel-WRK\WRK-v1.2\public\sdk\inc\ntexapi.h
// System Information Classes.
typedef enum _SYSTEM_INFORMATION_CLASS {
    SystemBasicInformation,
    SystemProcessorInformation,             // obsolete...delete
    SystemPerformanceInformation,
    SystemTimeOfDayInformation,
    SystemPathInformation,
    SystemProcessInformation,
    SystemCallCountInformation,
    SystemDeviceInformation,
    SystemProcessorPerformanceInformation,
    SystemFlagsInformation,
    SystemCallTimeInformation,
    SystemModuleInformation,
    SystemLocksInformation,
    SystemStackTraceInformation,
    SystemPagedPoolInformation,
    SystemNonPagedPoolInformation,
    SystemHandleInformation,//ExpGetHandleInformation处理的。
    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;


//摘自:\wrk\WindowsResearchKernel-WRK\WRK-v1.2\public\sdk\inc\ntexapi.h
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO {
    USHORT UniqueProcessId;
    USHORT CreatorBackTraceIndex;
    UCHAR ObjectTypeIndex;
    UCHAR HandleAttributes;
    USHORT HandleValue;
    PVOID Object;
    ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;


//摘自:\wrk\WindowsResearchKernel-WRK\WRK-v1.2\public\sdk\inc\ntexapi.h
typedef struct _SYSTEM_HANDLE_INFORMATION {
    ULONG NumberOfHandles;
    SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[ 1 ];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;

//摘自:\wrk\WindowsResearchKernel-WRK\WRK-v1.2\public\sdk\inc\ntobapi.h
//typedef enum _OBJECT_INFORMATION_CLASS {
//    ObjectBasicInformation,
//    ObjectNameInformation,
//    ObjectTypeInformation,
//    ObjectTypesInformation,
//    ObjectHandleFlagInformation,
//    ObjectSessionInformation,
//    MaxObjectInfoClass  // MaxObjectInfoClass should always be the last enum
//} OBJECT_INFORMATION_CLASS;

//摘自:\wrk\WindowsResearchKernel-WRK\WRK-v1.2\public\sdk\inc\ntobapi.h
//typedef struct _OBJECT_NAME_INFORMATION {               // ntddk wdm nthal
//    UNICODE_STRING Name;                                // ntddk wdm nthal
//} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;   // ntddk wdm nthal


/*
摘自:http://msdn.microsoft.com/en-us/library/windows/desktop/ms724509(v=vs.85).aspx。
有修改。
*/
NTSTATUS /* WINAPI NtQuerySystemInformation */ ZwQuerySystemInformation(_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, _Inout_ PVOID SystemInformation,
                                                                        _In_  ULONG SystemInformationLength, _Out_opt_  PULONG ReturnLength);

//摘自:\wrk\WindowsResearchKernel-WRK\WRK-v1.2\public\internal\base\inc\zwapi.h
NTSTATUS ZwAdjustPrivilegesToken(IN HANDLE TokenHandle, IN BOOLEAN DisableAllPrivileges, IN PTOKEN_PRIVILEGES NewState OPTIONAL, 
                                 IN ULONG BufferLength OPTIONAL, OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL, OUT PULONG ReturnLength);


#define tag 'tset' //test


static NTSTATUS AdjustPrivilege(ULONG Privilege, BOOLEAN Enable)
    /*
    摘自:http://www.osronline.com/article.cfm?article=23
    */
{
    NTSTATUS status;
    TOKEN_PRIVILEGES privSet;
    HANDLE tokenHandle;
    TOKEN_PRIVILEGES tokenPriv;  

    status = ZwOpenProcessTokenEx(NtCurrentProcess(), TOKEN_ALL_ACCESS, OBJ_KERNEL_HANDLE , &tokenHandle);// Open current process token
    if (!NT_SUCCESS(status)) {
        DbgPrint("NtOpenProcessToken failed, status 0x%x\n", status);
        return status;
    }

    // Set up the information about the privilege we are adjusting
    privSet.PrivilegeCount = 1;
    privSet.Privileges[0].Luid = RtlConvertUlongToLuid(Privilege);
    if (Enable) {
        privSet.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    } else {
        privSet.Privileges[0].Attributes = 0;
    }

    status = ZwAdjustPrivilegesToken(tokenHandle,
        FALSE, // don't disable all privileges
        &privSet,
        sizeof(privSet),
        NULL, // old privileges - don't care
        NULL); // returned length
    if (!NT_SUCCESS(status)) {
        DbgPrint("ZwAdjustPrivilegesToken failed, status 0x%x\n", status);
    } 

    (void) ZwClose(tokenHandle);// Close the process token handle

    return status;
}


DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{

}


NTSTATUS ZwQueryObjectNameByHandle(IN HANDLE Handle, OUT UNICODE_STRING * p_object_name)
{
    unsigned int status = STATUS_UNSUCCESSFUL; 
    PVOID Object;
    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
    ULONG  Length = 1024;//取这个数的原因:参看ObQueryNameString函数的第三个参数的说明:A reasonable size for the buffer to accommodate most object names is 1024 bytes. 
    POBJECT_NAME_INFORMATION pu = 0;

    status = ObReferenceObjectByHandle( Handle, 0, NULL, PreviousMode, &Object, 0 );
    if (!NT_SUCCESS( status )) {
        return( status );
    }

    Length = 0;
    status = ObQueryNameString(Object, pu, 0, &Length);
    if (status != STATUS_INFO_LENGTH_MISMATCH) {
        KdPrint(("ObQueryNameString fail with 0x%X!\n",status));
        ObDereferenceObject(Object);
        return status;
    }

    Length += 512;
    pu = (POBJECT_NAME_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, Length, tag );
    if (pu == 0) {
        ObDereferenceObject(Object);
        return status;
    }
    RtlZeroMemory(pu, Length);

    status = ObQueryNameString(Object, pu, Length, &Length);
    if (status != STATUS_SUCCESS ) 
    {
        /*
        经查此时的返回值是0xC0000001。
        即连到系统上的设备没有发挥作用。
        此时的句柄的类型是文件。
        而且process explorer也是显示的是没有值的。
        */
        KdPrint(("ObQueryNameString fail with 0x%X!\n",status));
        ExFreePoolWithTag(pu, tag );
        ObDereferenceObject(Object);
        return status;
    }

    ObDereferenceObject(Object);

    //有的对象是没有名字的。
    if (pu->Name.Length == 0)
    {        
        status = STATUS_UNSUCCESSFUL;
    }
    else
    {
        RtlCopyUnicodeString(p_object_name,&pu->Name);   
        //p_object_name->Buffer = pu->Name.Buffer;
        //p_object_name->Length = pu->Name.Length;
        //p_object_name->MaximumLength = pu->Name.MaximumLength;
    }

    ExFreePoolWithTag(pu, tag );

    return status;
}


NTSTATUS EnumerateProcessHandles(IN HANDLE pid, OUT DWORD * process_handle )
{
    unsigned int status = STATUS_UNSUCCESSFUL; 
    DWORD nSize = 4096, nReturn;
    PSYSTEM_HANDLE_INFORMATION pSysHandleInfo;
    CLIENT_ID   ClientId = {0};//不初始化ZwOpenProcess有问题。
    HANDLE  ProcessHandle;
    DWORD dwhandles = 0;//一个进程的所有的句柄数量。
    ULONG i = 0;
    OBJECT_ATTRIBUTES ob;

    pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION)ExAllocatePoolWithTag( NonPagedPool, nSize, tag);
    if (pSysHandleInfo == NULL) {
        KdPrint(("ExAllocatePoolWithTag fail with 0x%x, file:%s,fun:%s,line:%d\n",status,  __FILE__,__FUNCTION__, __LINE__));
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlZeroMemory(pSysHandleInfo, nSize);
    while (ZwQuerySystemInformation(SystemHandleInformation, pSysHandleInfo, nSize, &nReturn) == STATUS_INFO_LENGTH_MISMATCH)// Get system handle information.
    {
        ExFreePoolWithTag( pSysHandleInfo, tag );
        nSize += 4096;
        pSysHandleInfo = (SYSTEM_HANDLE_INFORMATION*)(PSYSTEM_HANDLE_INFORMATION)ExAllocatePoolWithTag( NonPagedPool, nSize, tag);
        if (pSysHandleInfo == NULL) {
            KdPrint(("ExAllocatePoolWithTag fail with 0x%x, file:%s,fun:%s,line:%d\n",status,  __FILE__,__FUNCTION__, __LINE__));
            return STATUS_INSUFFICIENT_RESOURCES;
        }
        RtlZeroMemory(pSysHandleInfo, nSize);    
    }       

    ClientId.UniqueProcess = pid ;
    InitializeObjectAttributes(&ob, 0, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
    status = ZwOpenProcess(&ProcessHandle, GENERIC_ALL, &ob, &ClientId);
    if (!NT_SUCCESS(status)) {
        KdPrint(("ZwOpenProcess fail with 0x%x, file:%s,fun:%s,line:%d\n",status,  __FILE__,__FUNCTION__, __LINE__));
        ExFreePoolWithTag( pSysHandleInfo, tag );
        return status;
    }    

    for (; i < pSysHandleInfo->NumberOfHandles; i++)
    {
        PSYSTEM_HANDLE_TABLE_ENTRY_INFO pHandle = &(pSysHandleInfo->Handles[i]);

        //根据进程进行搜索。
        if (pHandle->UniqueProcessId == (int)pid) 
        {
            HANDLE hCopy;// Duplicate the handle in the current process
            PVOID  ObjectInformation = 0;
            ULONG  ObjectInformationLength = 0;
            ULONG  ReturnLength = 0;
            PPUBLIC_OBJECT_TYPE_INFORMATION ppoti = 0;
            UNICODE_STRING object_name;

            dwhandles++; // Increase the number of handles

            /*
            访问系统进程中句柄类型为进程的IDLE句柄会返回0xc0000022.即拒绝访问。
            process explorer也是如此。估计是显示的PSYSTEM_HANDLE_TABLE_ENTRY_INFO的内容。
            pchunter没有显示句柄为进程和线程的信息。但是process explorer能。
            process explorer默认的情况下是不显示没有名字的句柄的MAPPINGS的。但是可以设置和修改。
            */
            status = ZwDuplicateObject(ProcessHandle, (HANDLE)pHandle->HandleValue, NtCurrentProcess(), &hCopy, PROCESS_ALL_ACCESS , FALSE, DUPLICATE_SAME_ACCESS);
            if (!NT_SUCCESS(status)) {
                KdPrint(("ZwDuplicateObject fail with 0x%x, file:%s,fun:%s,line:%d\n",status,  __FILE__,__FUNCTION__, __LINE__));
                continue;
            }

            //status = ZwQueryObject(hCopy, ObjectTypeInformation, ObjectInformation, ObjectInformationLength, &ReturnLength);
            //if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_BUFFER_TOO_SMALL)
            //{
            //    ObjectInformationLength = ReturnLength;
            //}
            //else
            //{
            //    //continue;
            //    break;//程序发出命令,但命令长度不正确。 C0000004
            //}

            //查询句柄类型,这是字符串。
            ObjectInformationLength = sizeof (PUBLIC_OBJECT_TYPE_INFORMATION) * 2;//这个应该再增加点。加个512应该合适点。             
            ObjectInformation = ExAllocatePoolWithTag( NonPagedPool, ObjectInformationLength, tag);
            if (ObjectInformation == NULL) {
                KdPrint(("ExAllocatePoolWithTag fail with 0x%x, file:%s,fun:%s,line:%d\n",status,  __FILE__,__FUNCTION__, __LINE__));
                ZwClose(hCopy);
                return STATUS_INSUFFICIENT_RESOURCES;
            }
            RtlZeroMemory(ObjectInformation, ObjectInformationLength);  
            status = ZwQueryObject(hCopy, ObjectTypeInformation, ObjectInformation, ObjectInformationLength, &ReturnLength);
            if (!NT_SUCCESS(status))
            {
                KdPrint(("ZwQueryObject fail with 0x%x, file:%s,fun:%s,line:%d\n",status,  __FILE__,__FUNCTION__, __LINE__));
                ExFreePoolWithTag( ObjectInformation, tag );
                ZwClose(hCopy);
                return status;
            }
            
            object_name.Buffer = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH, tag );
            if (object_name.Buffer == 0) {
                KdPrint(("ExAllocatePoolWithTag fail with 0x%x, file:%s,fun:%s,line:%d\n",status,  __FILE__,__FUNCTION__, __LINE__));
                ExFreePoolWithTag( ObjectInformation, tag );
                ZwClose(hCopy);
                return status;
            }
            RtlZeroMemory(object_name.Buffer, MAX_PATH);
            RtlInitEmptyUnicodeString(&object_name, object_name.Buffer,MAX_PATH);

            ppoti = (PPUBLIC_OBJECT_TYPE_INFORMATION)ObjectInformation;
            

            /*
            如果要查询句柄的值的名字,可以:
            1.用ZwQueryObject的未公开的ObjectNameInformation。其实这是使用ObReferenceObjectByHandle+ObpQueryNameString实现的。
            2.ObReferenceObjectByHandle+ObQueryNameString。
            */
            status = ZwQueryObjectNameByHandle(hCopy, &object_name);
            if (NT_SUCCESS(status))
            {
                KdPrint(("HANDLE:0x%x, TYPE:%wZ, NAME:%wZ\n",pHandle->HandleValue, &ppoti->TypeName, &object_name));
                RtlFreeUnicodeString(&object_name);
                //ExFreePoolWithTag(object_name.Buffer, tag );
            }   
            else 
            {
                KdPrint(("HANDLE:0x%x, TYPE:%wZ\n",pHandle->HandleValue, &ppoti->TypeName));
            }            
            
            status = ZwClose(hCopy);
            //if (!NT_SUCCESS(status))
            //{//有的句柄保护起来,是不准关闭的。
            //    KdPrint(("ZwClose fail with 0x%x, file:%s,fun:%s,line:%d\n",status,  __FILE__,__FUNCTION__, __LINE__));
            //    ExFreePoolWithTag( pSysHandleInfo, tag );
            //    ExFreePoolWithTag( ObjectInformation, tag );
            //    return status;
            //}

            ExFreePoolWithTag( ObjectInformation, tag );     
        }
    }

    status = ZwClose(ProcessHandle);
    /*if (!NT_SUCCESS(status)) {//可能有的句柄已经释放了。
        KdPrint(("ZwClose fail with 0x%x, file:%s,fun:%s,line:%d\n",status,  __FILE__,__FUNCTION__, __LINE__));
        ExFreePoolWithTag( pSysHandleInfo, tag );
        return status;
    } */   

    ExFreePoolWithTag( pSysHandleInfo, tag );

    * process_handle = dwhandles;

    return status;
}


DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT  * DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    unsigned int status = STATUS_UNSUCCESSFUL;  
    DWORD process_handle = 0;
    HANDLE test_handle = PsGetProcessId(PsInitialSystemProcess);//(HANDLE)1652;//PsGetProcessId(PsInitialSystemProcess);//获取系统进程的id,实用型很强,可以在别处使用,不只是驱动的入口。
    
    KdBreakPoint();

    DriverObject->DriverUnload = Unload;    

    status = AdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE);
    if (!NT_SUCCESS(status)) {
        DbgPrint("AdjustPrivilege SE_RESTORE_PRIVILEGE fail!\n");
        return status;
    }

    status = EnumerateProcessHandles(test_handle, &process_handle);
    if (!NT_SUCCESS(status)) {
        KdPrint(("EnumerateProcessHandles fail with 0x%x, file:%s,fun:%s,line:%d\n",status,  __FILE__,__FUNCTION__, __LINE__));
        return status;
    }        

    return status;//STATUS_SUCCESS
} 

没有评论:

发表评论