c++枚举系统句柄

Home / C++ MrLee 2016-10-22 3246

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[MAX_PATH] = _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[1024], cbNeeded, cProcesses;
   unsigned int i;
   if(!EnumProcesses(aProcesses,sizeof(aProcesses),&cbNeeded))
         return;
   cProcesses = cbNeeded/sizeof(DWORD);
   for(i=0;i<cProcesses;i++)
         PrintProcessNameAndID(aProcesses[i]);
     getchar();
}

此方法由于需要进行OpenProcess操作,所以需要一定的权限,当权限不够时,有些进程将不能被打开。 下面给出提升权限的相关代码:
void RaisePrivilege()
{
	HANDLE			hToken;
	TOKEN_PRIVILEGES	tp;
	tp.PrivilegeCount		= 1;
	tp.Privileges[0].Attributes	= SE_PRIVILEGE_ENABLED;
	if ( OpenProcessToken( GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken ) )
	{
		if ( LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &tp.Privileges[0].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[6];
FILETIME ftCreateTime;
FILETIME ftUserTime;
FILETIME ftKernelTime;
UNICODE_STRING ProcessName;
DWORD BasePriority;
DWORD ProcessId;
DWORD InheritedFromProcessId;
DWORD HandleCount;
DWORD Reserved2[2];
DWORD VmCounters;
DWORD dCommitCharge;
PVOID ThreadInfos[1];
}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[6];
	FILETIME	ftCreateTime;
	FILETIME	ftUserTime;
	FILETIME	ftKernelTime;
	UNICODE_STRING	ProcessName;
	DWORD		BasePriority;
	DWORD		ProcessId;
	DWORD		InheritedFromProcessId;
	DWORD		HandleCount;
	DWORD		Reserved2[2];
	DWORD		VmCounters;
	DWORD		dCommitCharge;
	PVOID		ThreadInfos[1];
}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[1];
}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[i].ProcessId )
		{
			OldPID = pInfo->Information[i].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[3];
	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[8];
	ULONG		HighWaterNumberOfHandles;
	ULONG		HighWaterNumberOfObjects;
	WCHAR		Unused2[8];
	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[IRP_MJ_CREATE]				=
		pDriverObj->MajorFunction[IRP_MJ_CLOSE]				=
			pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL]	= 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[i];
		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);
}

 

本文链接:https://www.it72.com/10955.htm

推荐阅读
最新回复 (0)
返回