米老鼠和蓝精鼠v 发表于 2024-3-3 09:23:31

c++枚举系统句柄

1、利用ToolHelp API
首先创建一个系统快照,然后通过对系统快照的访问完成进程的枚举获取系统快照使用CreateToolhelp32Snapshot 函数
函数原型声明如下:

HANDLE WINAPI CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);
将dwFlags设置为TH32CS_SNAPPROCESS用于获取进程快照。函数调用成功后会返回一个快照的句柄,便可以使用Process32First、Process32Next进行枚举了

函数原型声明如下:

BOOL WINAPI Process32First(
HANDLE hSnapshot,
LPPROCESSENTRY32 lppe
);
BOOL WINAPI Process32Next( HANDLE hSnapshot, LPPROCESSENTRY32 lppe);



下面是相关代码:
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
void useToolHelp()
{
    HANDLE procSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
    if ( procSnap == INVALID_HANDLE_VALUE )
    {
      printf( "CreateToolhelp32Snapshot failed, %d ", GetLastError() );
      return;
    }
/**/
    PROCESSENTRY32 procEntry = { 0 };
    procEntry.dwSize = sizeof(PROCESSENTRY32);
    BOOL bRet = Process32First( procSnap, &procEntry );
    while ( bRet )
    {
      wprintf( L"PID: %d (%s) ", procEntry.th32ProcessID, procEntry.szExeFile );
      bRet = Process32Next( procSnap, &procEntry );
    }
    CloseHandle( procSnap );
}


void main()
{
    useToolHelp();
    getchar();
}


用此方法可以在进程ID和进程名称间进行转换,即通过进程名称获得进程ID,通过进程ID获取进程名称。

2、通过psapi.dll提供的函数

通过psapi.dll提供的EnumProcesses、EnumProcessModules实现

函数原型声明如下:
BOOL EnumProcesses( DWORD* pProcessIds, DWORD cb, DWORD* pBytesReturned);BOOL EnumProcessModules( HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include "psapi.h"
#pragma comment(lib,"psapi.lib")

void PrintProcessNameAndID(DWORD processID)
{
   TCHAR szProcessName = _T("<unknown>");
   HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,processID);   
   //Process name.
   if(NULL!=hProcess)
   {
         HMODULE hMod;
   DWORD cbNeeded;
   if(EnumProcessModules(hProcess,&hMod,sizeof(hMod), &cbNeeded))         
   {
             GetModuleBaseName(hProcess,hMod,szProcessName,sizeof(szProcessName)/sizeof(TCHAR));                        
   }
   }
   wprintf(_T("PID: %d (%s) "),processID,szProcessName);
   CloseHandle(hProcess);
}
void main( )
{
   DWORD aProcesses, cbNeeded, cProcesses;
   unsigned int i;
   if(!EnumProcesses(aProcesses,sizeof(aProcesses),&cbNeeded))
         return;
   cProcesses = cbNeeded/sizeof(DWORD);
   for(i=0;i<cProcesses;i++)
         PrintProcessNameAndID(aProcesses);
   getchar();
}

此方法由于需要进行OpenProcess操作,所以需要一定的权限,当权限不够时,有些进程将不能被打开。

下面给出提升权限的相关代码:

void RaisePrivilege()
{
    HANDLE            hToken;
    TOKEN_PRIVILEGES    tp;
    tp.PrivilegeCount      = 1;
    tp.Privileges.Attributes    = SE_PRIVILEGE_ENABLED;
    if ( OpenProcessToken( GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken ) )
    {
      if ( LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &tp.Privileges.Luid ) )
      {
            AdjustTokenPrivileges( hToken, FALSE, &tp, NULL, NULL, 0 );
      }
    }
    if ( hToken )
      CloseHandle( hToken );
}

3、通过ntdll.dll提供的Native API
使用Native API 中的ZwQuerySystemInformation的SystemProcessesAndThreadsInformation系统调用枚举进程由于该函数没有被导出,所以首先定义要使用到的结构和常量

typedef DWORD (WINAPI *ZWQUERYSYSTEMINFORMATION)(DWORD, PVOID, DWORD, PDWORD);
typedef struct _SYSTEM_PROCESS_INFORMATION
{
DWORD NextEntryDelta;
DWORD ThreadCount;
DWORD Reserved1;
FILETIME ftCreateTime;
FILETIME ftUserTime;
FILETIME ftKernelTime;
UNICODE_STRING ProcessName;
DWORD BasePriority;
DWORD ProcessId;
DWORD InheritedFromProcessId;
DWORD HandleCount;
DWORD Reserved2;
DWORD VmCounters;
DWORD dCommitCharge;
PVOID ThreadInfos;
}SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
#define SystemProcessesAndThreadsInformation 5
然后动态加载ntdll.dll,获得函数的地址。便可以进行进程的枚举

#include <windows.h>
#include <ntsecapi.h>
#include <stdio.h>
typedef DWORD (WINAPI * ZWQUERYSYSTEMINFORMATION)( DWORD, PVOID, DWORD, PDWORD );
typedef struct _SYSTEM_PROCESS_INFORMATION
{
    DWORD      NextEntryDelta;
    DWORD      ThreadCount;
    DWORD      Reserved1;
    FILETIME    ftCreateTime;
    FILETIME    ftUserTime;
    FILETIME    ftKernelTime;
    UNICODE_STRING    ProcessName;
    DWORD      BasePriority;
    DWORD      ProcessId;
    DWORD      InheritedFromProcessId;
    DWORD      HandleCount;
    DWORD      Reserved2;
    DWORD      VmCounters;
    DWORD      dCommitCharge;
    PVOID      ThreadInfos;
}SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
#define SystemProcessesAndThreadsInformation 5
void main()
{
    HMODULE hNtDll = GetModuleHandle( L"ntdll.dll" );
    if ( !hNtDll )
      return;
    ZWQUERYSYSTEMINFORMATION    ZwQuerySystemInformation    = (ZWQUERYSYSTEMINFORMATION) GetProcAddress( hNtDll, "ZwQuerySystemInformation" );
    ULONG                cbBuffer            = 0x10000;
    LPVOID                pBuffer                = NULL;
    pBuffer = malloc( cbBuffer );
    if ( pBuffer == NULL )
      return;
    ZwQuerySystemInformation( SystemProcessesAndThreadsInformation, pBuffer, cbBuffer, NULL );
    PSYSTEM_PROCESS_INFORMATION pInfo = (PSYSTEM_PROCESS_INFORMATION) pBuffer;
    for (;; )
    {
      wprintf( L"PID: %d (%ls) ", pInfo->ProcessId, pInfo->ProcessName.Buffer );
      if ( pInfo->NextEntryDelta == 0 )
            break;
      pInfo = (PSYSTEM_PROCESS_INFORMATION) ( ( (PUCHAR) pInfo) + pInfo->NextEntryDelta);
    }
    free( pBuffer );
    getchar();
}

4、通过进程打开的句柄来枚举进程

#include <windows.h>
#include <ntsecapi.h>
#include <ntstatus.h>
#include <stdio.h>
typedef NTSTATUS (WINAPI * ZWQUERYSYSTEMINFORMATION)( 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;
typedef struct _SYSTEM_HANDLE_INFORMATION_EX
{
    ULONG                NumberOfHandles;
    SYSTEM_HANDLE_INFORMATION    Information;
}SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
#define SystemHandleInformation 0x10 /* 16 */
void main()
{
    HMODULE hNtDll = LoadLibrary( L"ntdll.dll" );
    if ( !hNtDll )
      return;
    ZWQUERYSYSTEMINFORMATION    ZwQuerySystemInformation    = (ZWQUERYSYSTEMINFORMATION) GetProcAddress( hNtDll, "ZwQuerySystemInformation" );
    ULONG                cbBuffer            = 0x4000;
    LPVOID                pBuffer                = NULL;
    NTSTATUS            s;
    do
    {
      pBuffer = malloc( cbBuffer );
      if ( pBuffer == NULL )
            return;
      memset( pBuffer, 0, cbBuffer );
      s = ZwQuerySystemInformation( SystemHandleInformation, pBuffer, cbBuffer, NULL );
      if ( s == STATUS_INFO_LENGTH_MISMATCH )
      {
            free( pBuffer );
            cbBuffer = cbBuffer * 2;
      }
    }
    while ( s == STATUS_INFO_LENGTH_MISMATCH );
    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.ProcessId )
      {
            OldPID = pInfo->Information.ProcessId;
            wprintf( L"PID: %d ", OldPID );
      }
    }
    free( pBuffer );
    FreeLibrary( hNtDll );
    getchar();
}
一直在使用一个小工具叫unlocker。知道它是用关闭句柄的方法来删除文件的,但是自己也没有怎么研究过这东西。传说中更厉害的方法是直接向磁盘写0 和Xcb大法,最近准备好好研究这些删除方法。那么就从句柄开始吧。这里我只做枚举句柄的工作,因为关闭句柄就是把ZwDuplicateObject 的Options 这个参数赋值为DUPLICATE_CLOSE_SOURCE 。这里还要感谢一下sudami和NetRoc同学。。。O(∩_∩)O哈哈~

#include <ntddk.h>

#define AYA_DEVICE    L"\\Device\\EnumHandle"
#define AYA_LINK    L"\\DosDevices\\EnumHandle"

#define SystemHandleInformation 16

#define OB_TYPE_PROCESS 5

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;

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

typedef enum _OBJECT_INFORMATION_CLASS {
    ObjectBasicInformation,
    ObjectNameInformation,
    ObjectTypeInformation,
    ObjectAllInformation,
    ObjectDataInformation
} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;

typedef struct _OBJECT_BASIC_INFORMATION {
    ULONG      Attributes;
    ACCESS_MASK    DesiredAccess;
    ULONG      HandleCount;
    ULONG      ReferenceCount;
    ULONG      PagedPoolUsage;
    ULONG      NonPagedPoolUsage;
    ULONG      Reserved;
    ULONG      NameInformationLength;
    ULONG      TypeInformationLength;
    ULONG      SecurityDescriptorLength;
    LARGE_INTEGER    CreationTime;
} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION;

typedef struct _KOBJECT_NAME_INFORMATION {
    UNICODE_STRING    Name;
    WCHAR      NameBuffer[];
} KOBJECT_NAME_INFORMATION, *PKOBJECT_NAME_INFORMATION;

typedef struct _OBJECT_TYPE_INFORMATION {
    UNICODE_STRING    TypeName;
    ULONG      TotalNumberOfHandles;
    ULONG      TotalNumberOfObjects;
    WCHAR      Unused1;
    ULONG      HighWaterNumberOfHandles;
    ULONG      HighWaterNumberOfObjects;
    WCHAR      Unused2;
    ACCESS_MASK    InvalidAttributes;
    GENERIC_MAPPING GenericMapping;
    ACCESS_MASK    ValidAttributes;
    BOOLEAN      SecurityRequired;
    BOOLEAN      MaintainHandleCount;
    USHORT      MaintainTypeList;
    POOL_TYPE    PoolType;
    ULONG      DefaultPagedPoolCharge;
    ULONG      DefaultNonPagedPoolCharge;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;

NTSYSAPI
NTSTATUS
NTAPI
ZwQueryObject(
    IN HANDLE Handle,
    IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
    OUT PVOID ObjectInformation,
    IN ULONG ObjectInformationLength,
    OUT PULONG ReturnLength OPTIONAL
    );


NTSYSAPI
NTSTATUS
NTAPI
ZwQuerySystemInformation(
    ULONG SystemInformationClass,
    PVOID SystemInformation,
    ULONG SystemInformationLength,
    PULONG ReturnLength
    );


NTSYSAPI
NTSTATUS
NTAPI
ZwDuplicateObject(
    IN HANDLE SourceProcessHandle,
    IN HANDLE SourceHandle,
    IN HANDLE TargetProcessHandle OPTIONAL,
    OUT PHANDLE TargetHandle OPTIONAL,
    IN ACCESS_MASK DesiredAccess,
    IN ULONG HandleAttributes,
    IN ULONG Options
    );


NTSYSAPI
NTSTATUS
NTAPI
ZwOpenProcess(
    OUT PHANDLE ProcessHandle,
    IN ACCESS_MASK AccessMask,
    IN POBJECT_ATTRIBUTES ObjectAttributes,
    IN PCLIENT_ID ClientId
    );


NTSTATUS NTAPI AYA_EnumHandle();


void AYA_Unload( IN PDRIVER_OBJECT pDriverObj )
{
    UNICODE_STRING Temp;
    RtlInitUnicodeString( &Temp, AYA_LINK );
    IoDeleteSymbolicLink( &Temp );
    IoDeleteDevice( pDriverObj->DeviceObject );
}


NTSTATUS AYA_Dispatch( IN PDEVICE_OBJECT pDeviceObj, IN PIRP pIrp )
{
    NTSTATUS      ns = STATUS_SUCCESS;
    PIO_STACK_LOCATION    stIrp;

    stIrp = IoGetCurrentIrpStackLocation( pIrp );

    switch ( stIrp->MajorFunction )
    {
    case IRP_MJ_CREATE:
      break;
    case IRP_MJ_CLOSE:
      break;
    case IRP_MJ_DEVICE_CONTROL:
      break;
    default:
      pIrp->IoStatus.Status = STATUS_INVALID_PARAMETER;
      break;
    }

    ns = pIrp->IoStatus.Status;
    IoCompleteRequest( pIrp, IO_NO_INCREMENT );
    return(ns);
}


NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObj, IN PUNICODE_STRING RegistryPath )
{
    NTSTATUS    ns = STATUS_SUCCESS;
    UNICODE_STRING    AYA;
    UNICODE_STRING    AYAL;
    PDEVICE_OBJECT    pDevice;

    ns = AYA_EnumHandle();
    RtlInitUnicodeString( &AYA, AYA_DEVICE );
    ns = IoCreateDevice( pDriverObj, 0, &AYA, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevice );

    RtlInitUnicodeString( &AYAL, AYA_LINK );
    ns = IoCreateSymbolicLink( &AYAL, &AYA );

    pDriverObj->MajorFunction                =
      pDriverObj->MajorFunction                =
            pDriverObj->MajorFunction    = AYA_Dispatch;

    pDriverObj->DriverUnload = AYA_Unload;


    return(ns);
}


NTSTATUS AYA_EnumHandle()
{
    NTSTATUS            ns = STATUS_SUCCESS;
    ULONG                ulSize;
    PVOID                pSysBuffer;
    PSYSTEM_HANDLE_INFORMATION    pSysHandleInfo;
    SYSTEM_HANDLE_TABLE_ENTRY_INFO    pSysHandleTEI;
    OBJECT_BASIC_INFORMATION    BasicInfo;
    PKOBJECT_NAME_INFORMATION    pNameInfo;
    POBJECT_TYPE_INFORMATION    pTypeInfo;
    OBJECT_ATTRIBUTES      oa;
    ULONG                ulProcessID;
    HANDLE                hProcess;
    HANDLE                hHandle;
    HANDLE                hDupObj;
    CLIENT_ID            cid;
    ULONG                i;

    ulSize = 100;
    do
    {
      pSysBuffer    = ExAllocatePoolWithTag( PagedPool, ulSize, 'A0' );
      ns      = ZwQuerySystemInformation( SystemHandleInformation, pSysBuffer, ulSize, NULL );
      ulSize      *= 2;
      if ( !NT_SUCCESS( ns ) )
      {
            ExFreePool( pSysBuffer );
      }
    }
    while ( !NT_SUCCESS( ns ) );


    pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION) pSysBuffer;
    for ( i = 0; i < pSysHandleInfo->NumberOfHandles; i++ )
    {
      pSysHandleTEI = pSysHandleInfo->Handles;

      if ( pSysHandleTEI.ObjectTypeIndex != OB_TYPE_PROCESS )
      {
            continue;
      }

      ulProcessID      = (ULONG) pSysHandleTEI.UniqueProcessId;
      cid.UniqueProcess    = (HANDLE) ulProcessID;
      cid.UniqueThread    = (HANDLE) 0;
      hHandle            = (HANDLE) pSysHandleTEI.HandleValue;


      InitializeObjectAttributes( &oa, NULL, 0, NULL, NULL );
      ns = ZwOpenProcess( &hProcess, PROCESS_DUP_HANDLE, &oa, &cid );
      if ( !NT_SUCCESS( ns ) )
      {
            KdPrint( ("ZwOpenProcess : Fail ") );
            break;
      }
      ns = ZwDuplicateObject( hProcess, hHandle, NtCurrentProcess(), &hDupObj, \
                  PROCESS_ALL_ACCESS, 0, DUPLICATE_SAME_ACCESS );

      if ( !NT_SUCCESS( ns ) )
      {
            KdPrint( ("ZwDuplicateObject : Fail ") );
            break;
      }

      ZwQueryObject( hDupObj, ObjectBasicInformation, &BasicInfo, \
                   sizeof(OBJECT_BASIC_INFORMATION), NULL );

      pNameInfo = ExAllocatePoolWithTag( PagedPool, BasicInfo.NameInformationLength, 'A1' );
      RtlZeroMemory( pNameInfo, BasicInfo.NameInformationLength );

      ZwQueryObject( hDupObj, ObjectNameInformation, pNameInfo, \
                   BasicInfo.NameInformationLength, NULL );

      pTypeInfo = ExAllocatePoolWithTag( PagedPool, BasicInfo.TypeInformationLength, 'A2' );
      RtlZeroMemory( pTypeInfo, BasicInfo.TypeInformationLength );

      ZwQueryObject( hDupObj, ObjectTypeInformation, pTypeInfo, \
                   BasicInfo.TypeInformationLength, NULL );

      KdPrint( ("NAME:%wZ\t\t\tTYPE:%wZ\n", &(pNameInfo->Name), &(pTypeInfo->TypeName) ) );

      ExFreePool( pNameInfo );
      ExFreePool( pTypeInfo );
    }

    ZwClose( hDupObj );
    ZwClose( hProcess );
    ZwClose( hHandle );
    ExFreePool( pSysBuffer );

    if ( !NT_SUCCESS( ns ) )
    {
      return(STATUS_UNSUCCESSFUL);
    }

    return(ns);
}

页: [1]
查看完整版本: c++枚举系统句柄