R3下,遍历所有进程的伪句柄表,关闭指定句柄

之所以产生这个想法,是在删除文件的时候有时会提示文件被占用了,然后让我们先关闭之后在来删除,但是我怎么知道哪个进程打开了我的文件?

于是就去网上了找了一份代码然后改了改,接着来说说是怎么实现功能的。首先我们需要遍历所有的进程,所有要找到遍历进程的代码。


	//遍历进程
	WCHAR * szServerName = NULL;
	HANDLE WtsServerHandle = WTSOpenServer(szServerName);
	PWTS_PROCESS_INFO pWtspi;
	DWORD dwCount;
	if (!WTSEnumerateProcesses(WtsServerHandle, 0, 1, &pWtspi, &dwCount))
		return 0;
	//printf("tottal process %d", dwCount);
	for (DWORD i = 0; i < dwCount; i++){
		printf("ProcessID: %d (%ls)\n", pWtspi[i].ProcessId,pWtspi[i].pProcessName);
	}

现在我们能够拿到每一个进程的id,那么怎么通过进程的id拿到它的句柄信息呢?这里可以通过ZwQueryInformationProcess未文档话的函数,得到它的句柄总数,具体的参数如下

typedef NTSTATUS (WINAPI *ZWQUERYINFORMATIONPROCESS)(HANDLE  ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID  ProcessInformation, ULONG  ProcessInformationLength, PULONG ReturnLength);

其中它的第二个参数表示的是我们需要查询的内容,第三个是返回的内容,第四个是长度,最后一个不管。

通过上述函数我们能拿到当前进程的所有句柄的总数,但是需要注意的是句柄的后两位代表的是句柄的属性,也就是说,所有的句柄都是4的倍数,举一个例子,后两位不能使用了是吧,那么现在最小能使用的就是4=100二进制数,每增加一个就是增加4的倍数8=1000。拿pchunter随便看一个进程的伪句柄表,直观的看到句柄都是4的倍数。

我们现在有了每一个进程的进程句柄总数,那么只需要枚举所有的句柄不就行了吗,但是问题又来了,我们现在拿到的是伪句柄不能正常的使用,需要使用DuplicateHandle复制句柄。之后又会用到例外一个未文档话的函数ZwQueryObject,它可以查看得到当前的对象的类型和对象的名字,

typedef NTSTATUS (WINAPI *ZWQUERYOBJECT)(HANDLE OPTIONAL, OBJECT_INFORMATION_CLASS, PVOID OPTIONAL, ULONG, PULONG OPTIONAL);

最后还有一个问题,就算我们知道了每一个进程的句柄种类和名字,我们又怎么修改它呢?DuplicateHandle不仅可以复制句柄,还可以关闭源句柄。

DUPLICATE_CLOSE_SOURCE(0x00000001) Closes the source handle. This occurs regardless of any error status returned.
DUPLICATE_SAME_ACCESS(0x00000002) Ignores the dwDesiredAccess parameter. The duplicate handle has the same access as the source handle.

那么最后重新整理一下思路,首先是遍历所有进程得到每一个进程的伪句柄,之后使用DuplicateHandlede复制真实的句柄,判断句柄的属性,判断句柄名字是不是我们想要的,是在干掉句柄。这里有一个小细节需要说一下就是在使用ZwQueryObject的查询句柄名字的时候会出现卡死的情况。这时我们需要创建一个新的线程来执行这个操作,避免在主线程中一直卡住。最后整理的代码如下。

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



#define STATUS_INFO_LENGTH_MISMATCH		((NTSTATUS)0xC0000004L)
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) 
typedef enum _POOL_TYPE {
	NonPagedPool,
	NonPagedPoolExecute,
	PagedPool,
	NonPagedPoolMustSucceed,
	DontUseThisType,
	NonPagedPoolCacheAligned,
	PagedPoolCacheAligned,
	NonPagedPoolCacheAlignedMustS,
	MaxPoolType,
	NonPagedPoolBase,
	NonPagedPoolBaseMustSucceed,
	NonPagedPoolBaseCacheAligned,
	NonPagedPoolBaseCacheAlignedMustS,
	NonPagedPoolSession,
	PagedPoolSession,
	NonPagedPoolMustSucceedSession,
	DontUseThisTypeSession,
	NonPagedPoolCacheAlignedSession,
	PagedPoolCacheAlignedSession,
	NonPagedPoolCacheAlignedMustSSession,
	NonPagedPoolNx,
	NonPagedPoolNxCacheAligned,
	NonPagedPoolSessionNx
} POOL_TYPE;
typedef enum _OBJECT_INFORMATION_CLASS {
	ObjectBasicInformation,
	ObjectNameInformation,
	ObjectTypeInformation,
	ObjectAllInformation,
	ObjectDataInformation
} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;
typedef struct
{
	USHORT Length;    //当前名称长度
	USHORT MaxLen;    //缓冲区最大长度
	USHORT *Buffer;    //Unicode 名称指针
}UNICODE_STRING, *PUNICODE_STRING;
typedef struct _OBJECT_NAME_INFORMATION {
	UNICODE_STRING          Name;
	WCHAR                   NameBuffer[0];
} OBJECT_NAME_INFORMATION, *POBJECT_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;
typedef enum _SYSTEM_INFORMATION_CLASS {
	SystemBasicInformation,              // 0        Y        N
	SystemProcessorInformation,          // 1        Y        N
	SystemPerformanceInformation,        // 2        Y        N
	SystemTimeOfDayInformation,          // 3        Y        N
	SystemNotImplemented1,               // 4        Y        N
	SystemProcessesAndThreadsInformation, // 5       Y        N
	SystemCallCounts,                    // 6        Y        N
	SystemConfigurationInformation,      // 7        Y        N
	SystemProcessorTimes,                // 8        Y        N
	SystemGlobalFlag,                    // 9        Y        Y
	SystemNotImplemented2,               // 10       Y        N
	SystemModuleInformation,             // 11       Y        N
	SystemLockInformation,               // 12       Y        N
	SystemNotImplemented3,               // 13       Y        N
	SystemNotImplemented4,               // 14       Y        N
	SystemNotImplemented5,               // 15       Y        N
	SystemHandleInformation,             // 16       Y        N
	SystemObjectInformation,             // 17       Y        N
	SystemPagefileInformation,           // 18       Y        N
	SystemInstructionEmulationCounts,    // 19       Y        N
	SystemInvalidInfoClass1,             // 20
	SystemCacheInformation,              // 21       Y        Y
	SystemPoolTagInformation,            // 22       Y        N
	SystemProcessorStatistics,           // 23       Y        N
	SystemDpcInformation,                // 24       Y        Y
	SystemNotImplemented6,               // 25       Y        N
	SystemLoadImage,                     // 26       N        Y
	SystemUnloadImage,                   // 27       N        Y
	SystemTimeAdjustment,                // 28       Y        Y
	SystemNotImplemented7,               // 29       Y        N
	SystemNotImplemented8,               // 30       Y        N
	SystemNotImplemented9,               // 31       Y        N
	SystemCrashDumpInformation,          // 32       Y        N
	SystemExceptionInformation,          // 33       Y        N
	SystemCrashDumpStateInformation,     // 34       Y        Y/N
	SystemKernelDebuggerInformation,     // 35       Y        N
	SystemContextSwitchInformation,      // 36       Y        N
	SystemRegistryQuotaInformation,      // 37       Y        Y
	SystemLoadAndCallImage,              // 38       N        Y
	SystemPrioritySeparation,            // 39       N        Y
	SystemNotImplemented10,              // 40       Y        N
	SystemNotImplemented11,              // 41       Y        N
	SystemInvalidInfoClass2,             // 42
	SystemInvalidInfoClass3,             // 43
	SystemTimeZoneInformation,           // 44       Y        N
	SystemLookasideInformation,          // 45       Y        N
	SystemSetTimeSlipEvent,              // 46       N        Y
	SystemCreateSession,                 // 47       N        Y
	SystemDeleteSession,                 // 48       N        Y
	SystemInvalidInfoClass4,             // 49
	SystemRangeStartInformation,         // 50       Y        N
	SystemVerifierInformation,           // 51       Y        Y
	SystemAddVerifier,                   // 52       N        Y
	SystemSessionProcessesInformation    // 53       Y        N
} SYSTEM_INFORMATION_CLASS;
typedef enum _PROCESSINFOCLASS
{
	ProcessBasicInformation = 0, // 0, q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION
	ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX
	ProcessIoCounters, // q: IO_COUNTERS
	ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX
	ProcessTimes, // q: KERNEL_USER_TIMES
	ProcessBasePriority, // s: KPRIORITY
	ProcessRaisePriority, // s: ULONG
	ProcessDebugPort, // q: HANDLE
	ProcessExceptionPort, // s: HANDLE
	ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN
	ProcessLdtInformation, // 10
	ProcessLdtSize,
	ProcessDefaultHardErrorMode, // qs: ULONG
	ProcessIoPortHandlers, // (kernel-mode only)
	ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS
	ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void
	ProcessUserModeIOPL,
	ProcessEnableAlignmentFaultFixup, // s: BOOLEAN
	ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS
	ProcessWx86Information,
	ProcessHandleCount, // 20, q: ULONG, PROCESS_HANDLE_INFORMATION
	ProcessAffinityMask, // s: KAFFINITY
	ProcessPriorityBoost, // qs: ULONG
	ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX
	ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION
	ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND
	ProcessWow64Information, // q: ULONG_PTR
	ProcessImageFileName, // q: UNICODE_STRING
	ProcessLUIDDeviceMapsEnabled, // q: ULONG
	ProcessBreakOnTermination, // qs: ULONG
	ProcessDebugObjectHandle, // 30, q: HANDLE
	ProcessDebugFlags, // qs: ULONG
	ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables
	ProcessIoPriority, // qs: ULONG
	ProcessExecuteFlags, // qs: ULONG
	ProcessResourceManagement,
	ProcessCookie, // q: ULONG
	ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION
	ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION
	ProcessPagePriority, // q: ULONG
	ProcessInstrumentationCallback, // 40
	ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX
	ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[]
	ProcessImageFileNameWin32, // q: UNICODE_STRING
	ProcessImageFileMapping, // q: HANDLE (input)
	ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE
	ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE
	ProcessGroupInformation, // q: USHORT[]
	ProcessTokenVirtualizationEnabled, // s: ULONG
	ProcessConsoleHostProcess, // q: ULONG_PTR
	ProcessWindowInformation, // 50, q: PROCESS_WINDOW_INFORMATION
	ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8
	ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION
	ProcessDynamicFunctionTableInformation,
	ProcessHandleCheckingMode,
	ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION
	ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION
	MaxProcessInfoClass
}PROCESSINFOCLASS;
//上面为需要用到的结构体和枚举


//定义函数指针
typedef NTSTATUS (NTAPI *ZWQUERYSYSTEMINFORMATION)( SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation,  ULONG SystemInformationLength, PULONG ReturnLength OPTIONAL);
ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;

typedef NTSTATUS (WINAPI *ZWQUERYOBJECT)(HANDLE OPTIONAL, OBJECT_INFORMATION_CLASS, PVOID OPTIONAL, ULONG, PULONG OPTIONAL);
ZWQUERYOBJECT ZwQueryObject = NULL;

typedef NTSTATUS (WINAPI *ZWQUERYINFORMATIONPROCESS)(HANDLE  ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID  ProcessInformation, ULONG  ProcessInformationLength, PULONG ReturnLength);
ZWQUERYINFORMATIONPROCESS ZwQueryInformationProcess = NULL;

//初始化未文档化函数
BOOL InitUnDocumentProc()
{
	HMODULE hNtdll = GetModuleHandle("Ntdll.dll");
	if (hNtdll == NULL)    return FALSE;

	ZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)GetProcAddress(hNtdll, "NtQuerySystemInformation");
	ZwQueryObject = (ZWQUERYOBJECT)GetProcAddress(hNtdll, "NtQueryObject");
	ZwQueryInformationProcess = (ZWQUERYINFORMATIONPROCESS)GetProcAddress(hNtdll, "NtQueryInformationProcess");

	if ((ZwQuerySystemInformation == NULL) || (ZwQueryObject == NULL) || (ZwQueryInformationProcess == NULL))
		return FALSE;
	return TRUE;
}

//象征性的提权,其实用处不大
BOOL EnableDebugPrivilege()
{
	HANDLE hToken;
	LUID sedebugnameValue;
	TOKEN_PRIVILEGES tkp;
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)){
		return   FALSE;
	}
	if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)){
		CloseHandle(hToken);
		return FALSE;
	}
	tkp.PrivilegeCount = 1;
	tkp.Privileges[0].Luid = sedebugnameValue;
	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)){
		CloseHandle(hToken);
		return FALSE;
	}
	return TRUE;
}



//查询名字的时候会卡死
HANDLE hDuplicate = NULL;
OBJECT_NAME_INFORMATION *ObjectName;
char BufferForObjectName[1024];


UINT WINAPI ZwThreadProc(PVOID lpParma){
	ZwQueryObject((HANDLE)hDuplicate, ObjectNameInformation, BufferForObjectName, sizeof(BufferForObjectName), NULL);
	ObjectName = (POBJECT_NAME_INFORMATION)BufferForObjectName;
	//MessageBoxA(0,0,0,0);
}





int main()
{
	EnableDebugPrivilege();
	InitUnDocumentProc();
	NTSTATUS Status;
	HANDLE hSource = NULL;
	DWORD HandleCount;
	OBJECT_TYPE_INFORMATION *ObjectType;
	char BufferForObjectType[1024];

	//遍历进程
	WCHAR * szServerName = NULL;
	HANDLE WtsServerHandle = WTSOpenServer(szServerName);
	PWTS_PROCESS_INFO pWtspi;
	DWORD dwCount;
	if (!WTSEnumerateProcesses(WtsServerHandle, 0, 1, &pWtspi, &dwCount))
		return 0;
	//printf("tottal process %d", dwCount);
	/*for (DWORD i = 0; i < dwCount; i++){
		printf("ProcessID: %d (%ls)\n", pWtspi[i].ProcessId,pWtspi[i].pProcessName);
	}*/



	for (DWORD j = 0; j < dwCount; j++) {
		hSource = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_DUP_HANDLE | PROCESS_SUSPEND_RESUME, FALSE, pWtspi[j].ProcessId);
		if (hSource != NULL) {
			DWORD dwHandle;
			Status = ZwQueryInformationProcess(hSource, ProcessHandleCount, &HandleCount, sizeof(HandleCount), NULL);
			//printf("total size %d  \n", HandleCount);
			
			for (DWORD i = 1; i <= HandleCount; i++) {//穷举句柄
				dwHandle = i * 4;
				//复制一个句柄对象 && 判断此句柄是否有效
				if (DuplicateHandle(hSource, (HANDLE)dwHandle, GetCurrentProcess(), &hDuplicate, 0, FALSE, DUPLICATE_SAME_ACCESS)) {

					ZeroMemory(BufferForObjectName, 1024);
					ZeroMemory(BufferForObjectType, 1024);

					//获取句柄类型
					Status = ZwQueryObject(hDuplicate, ObjectTypeInformation, BufferForObjectType, sizeof(BufferForObjectType), NULL);

					ObjectType = (OBJECT_TYPE_INFORMATION*)BufferForObjectType;
					if (Status == STATUS_INFO_LENGTH_MISMATCH || !NT_SUCCESS(Status))
						continue;
					

					//获取句柄名,会卡死,所以这里只有开一个线程
					//Status = ZwQueryObject((HANDLE)hDuplicate, ObjectNameInformation, BufferForObjectName, sizeof(BufferForObjectName), NULL);
					
					//ObjectName = (POBJECT_NAME_INFORMATION)BufferForObjectName;
					//if (Status == STATUS_INFO_LENGTH_MISMATCH || !NT_SUCCESS(Status))
						//continue;

					
					HANDLE hThread = CreateThread(NULL, 0, ZwThreadProc, NULL, 0, NULL);
					DWORD dwSatu = WaitForSingleObject(hThread, 53); // 等待,直到线程被激发
					if (dwSatu == WAIT_TIMEOUT) {
						hThread = OpenThread(THREAD_TERMINATE, FALSE, hThread);
						if (!TerminateThread(hThread, 0)) {
							CloseHandle(hThread);
						}
						CloseHandle(hThread);
						//MessageBoxA(0, 0, 0, 0);
						continue;

					}
					
					//关闭复制的句柄
					CloseHandle(hDuplicate);

					//printf("Type:%S\tName:%S\tHandle:%X\n", ObjectType->TypeName.Buffer,ObjectName->Name.Buffer, hDuplicate);
					if (ObjectName->Name.Buffer!=NULL&&!strcmp(ObjectType->TypeName.Buffer, L"File")&& wcsstr(ObjectName->Name.Buffer,L"msyh.ttc")) {//判断是不是文件类型,判断关闭文件对不对
						printf("pid %d \tName:%S\tHandle:%X\n", pWtspi[j].ProcessId, ObjectName->Name.Buffer, hDuplicate);
						//printf("pid %d \tName:%S\n", pWtspi[j].ProcessId, ObjectType->TypeName.Buffer);
						//关闭符合的句柄
						DuplicateHandle(hSource, (HANDLE)dwHandle, GetCurrentProcess(), &hDuplicate,0,FALSE,DUPLICATE_CLOSE_SOURCE);
						CloseHandle(hDuplicate);
					}

				}
			}
			CloseHandle(hSource);
		}
	
	}

	system("pause");
	return 0;
}

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
遍历进程的所有句柄可以使用Windows API函数EnumProcessModules和EnumProcessModulesEx来实现。具体步骤如下: 1. 使用函数CreateToolhelp32Snapshot获取当前系统进程的快照句柄。 2. 使用函数Process32First和Process32Next获取当前系统中所有进程进程ID。 3. 对于每个进程,使用函数OpenProcess打开进程句柄。 4. 使用函数EnumProcessModules或EnumProcessModulesEx遍历进程的所有模块,获取每个模块的句柄。 5. 对于每个模块句柄,使用函数GetModuleFileNameEx或GetMappedFileName获取模块的文件名。 6. 关闭进程句柄和模块句柄。 下面是一个简单的C++代码示例: ```c++ #include <Windows.h> #include <TlHelp32.h> #include <Psapi.h> #include <iostream> int main() { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot == INVALID_HANDLE_VALUE) { std::cout << "CreateToolhelp32Snapshot failed: " << GetLastError() << std::endl; return 1; } PROCESSENTRY32 pe32 = { 0 }; pe32.dwSize = sizeof(PROCESSENTRY32); if (!Process32First(hSnapshot, &pe32)) { std::cout << "Process32First failed: " << GetLastError() << std::endl; CloseHandle(hSnapshot); return 1; } do { HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID); if (hProcess == NULL) { continue; } HMODULE hModules[1024]; DWORD cbNeeded; if (EnumProcessModulesEx(hProcess, hModules, sizeof(hModules), &cbNeeded, LIST_MODULES_ALL)) { for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) { TCHAR szModuleName[MAX_PATH] = { 0 }; if (GetModuleFileNameEx(hProcess, hModules[i], szModuleName, MAX_PATH)) { std::wcout << pe32.szExeFile << " module: " << szModuleName << std::endl; } } } CloseHandle(hProcess); } while (Process32Next(hSnapshot, &pe32)); CloseHandle(hSnapshot); return 0; } ``` 该代码可以遍历系统中所有进程的模块句柄,并输出每个模块的文件名。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值