枚举进程句柄File,Section,Mutant,Timer关闭Mutex句柄实现游戏多开
标 题: 枚举进程句柄File,Section,Mutant,Timer关闭Mutex句柄实现游戏多开
作 者: Y4ng
时 间: 2012-09-06 19:50:32 星期四
链 接: http://www.cnblogs.com/Y4ng/archive/2012/09/06/EnumProcessHandle_EnumMutex.html
相信做过游戏多开的朋友就会发现,很多游戏普遍使用互斥mutex来防止程序多开,说实话这种方式已经非常OUT了。但是由于时间和技术的沉淀关系,留下来的游戏依然会存在这种方式。 最近接触到一款游戏是N前非常火热的对战游戏,可以称为经典之作;它就是用的Mutant来实现游戏防止多开的,一般咱们测试的时候都是用Xuetr来关闭游戏,但是要作为成品发布不可能要求客户拿Xuetr来列进程对象句柄,关句柄吧~
网上搜索了半天都没有找到枚举进程句柄的例子,经过群里的大牛提点指到 ZwQuerySystemInformation SystemHandleInformation 可以实现句柄枚举功能;经过一番搜索编码测试 于是有了本文代码;
1 /*头文件声明*/ 2 typedef LONG NTSTATUS; 3 #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) 4 #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) 5 6 typedef enum _SYSTEM_INFORMATION_CLASS { 7 SystemBasicInformation, // 0 Y N 8 SystemProcessorInformation, // 1 Y N 9 SystemPerformanceInformation, // 2 Y N 10 SystemTimeOfDayInformation, // 3 Y N 11 SystemNotImplemented1, // 4 Y N 12 SystemProcessesAndThreadsInformation, // 5 Y N 13 SystemCallCounts, // 6 Y N 14 SystemConfigurationInformation, // 7 Y N 15 SystemProcessorTimes, // 8 Y N 16 SystemGlobalFlag, // 9 Y Y 17 SystemNotImplemented2, // 10 Y N 18 SystemModuleInformation, // 11 Y N 19 SystemLockInformation, // 12 Y N 20 SystemNotImplemented3, // 13 Y N 21 SystemNotImplemented4, // 14 Y N 22 SystemNotImplemented5, // 15 Y N 23 SystemHandleInformation, // 16 Y N 24 SystemObjectInformation, // 17 Y N 25 SystemPagefileInformation, // 18 Y N 26 SystemInstructionEmulationCounts, // 19 Y N 27 SystemInvalidInfoClass1, // 20 28 SystemCacheInformation, // 21 Y Y 29 SystemPoolTagInformation, // 22 Y N 30 SystemProcessorStatistics, // 23 Y N 31 SystemDpcInformation, // 24 Y Y 32 SystemNotImplemented6, // 25 Y N 33 SystemLoadImage, // 26 N Y 34 SystemUnloadImage, // 27 N Y 35 SystemTimeAdjustment, // 28 Y Y 36 SystemNotImplemented7, // 29 Y N 37 SystemNotImplemented8, // 30 Y N 38 SystemNotImplemented9, // 31 Y N 39 SystemCrashDumpInformation, // 32 Y N 40 SystemExceptionInformation, // 33 Y N 41 SystemCrashDumpStateInformation, // 34 Y Y/N 42 SystemKernelDebuggerInformation, // 35 Y N 43 SystemContextSwitchInformation, // 36 Y N 44 SystemRegistryQuotaInformation, // 37 Y Y 45 SystemLoadAndCallImage, // 38 N Y 46 SystemPrioritySeparation, // 39 N Y 47 SystemNotImplemented10, // 40 Y N 48 SystemNotImplemented11, // 41 Y N 49 SystemInvalidInfoClass2, // 42 50 SystemInvalidInfoClass3, // 43 51 SystemTimeZoneInformation, // 44 Y N 52 SystemLookasideInformation, // 45 Y N 53 SystemSetTimeSlipEvent, // 46 N Y 54 SystemCreateSession, // 47 N Y 55 SystemDeleteSession, // 48 N Y 56 SystemInvalidInfoClass4, // 49 57 SystemRangeStartInformation, // 50 Y N 58 SystemVerifierInformation, // 51 Y Y 59 SystemAddVerifier, // 52 N Y 60 SystemSessionProcessesInformation // 53 Y N 61 } SYSTEM_INFORMATION_CLASS; 62 63 typedef struct _CLIENT_ID 64 { 65 HANDLE UniqueProcess; 66 HANDLE UniqueThread; 67 }CLIENT_ID,*PCLIENT_ID; 68 69 typedef struct 70 { 71 USHORT Length; 72 USHORT MaxLen; 73 USHORT *Buffer; 74 }UNICODE_STRING, *PUNICODE_STRING; 75 76 typedef struct _OBJECT_ATTRIBUTES 77 { 78 ULONG Length; 79 HANDLE RootDirectory; 80 PUNICODE_STRING ObjectName; 81 ULONG Attributes; 82 PVOID SecurityDescriptor; 83 PVOID SecurityQualityOfService; 84 } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; 85 86 typedef struct _IO_COUNTERSEX { 87 LARGE_INTEGER ReadOperationCount; 88 LARGE_INTEGER WriteOperationCount; 89 LARGE_INTEGER OtherOperationCount; 90 LARGE_INTEGER ReadTransferCount; 91 LARGE_INTEGER WriteTransferCount; 92 LARGE_INTEGER OtherTransferCount; 93 } IO_COUNTERSEX, *PIO_COUNTERSEX; 94 95 typedef enum { 96 StateInitialized, 97 StateReady, 98 StateRunning, 99 StateStandby, 100 StateTerminated, 101 StateWait, 102 StateTransition, 103 StateUnknown 104 } THREAD_STATE; 105 106 typedef struct _VM_COUNTERS { 107 SIZE_T PeakVirtualSize; 108 SIZE_T VirtualSize; 109 ULONG PageFaultCount; 110 SIZE_T PeakWorkingSetSize; 111 SIZE_T WorkingSetSize; 112 SIZE_T QuotaPeakPagedPoolUsage; 113 SIZE_T QuotaPagedPoolUsage; 114 SIZE_T QuotaPeakNonPagedPoolUsage; 115 SIZE_T QuotaNonPagedPoolUsage; 116 SIZE_T PagefileUsage; 117 SIZE_T PeakPagefileUsage; 118 } VM_COUNTERS; 119 typedef VM_COUNTERS *PVM_COUNTERS; 120 121 typedef struct _SYSTEM_THREADS { 122 LARGE_INTEGER KernelTime; 123 LARGE_INTEGER UserTime; 124 LARGE_INTEGER CreateTime; 125 ULONG WaitTime; 126 PVOID StartAddress; 127 CLIENT_ID ClientId; 128 ULONG Priority; 129 ULONG BasePriority; 130 ULONG ContextSwitchCount; 131 THREAD_STATE State; 132 ULONG WaitReason; 133 } SYSTEM_THREADS, *PSYSTEM_THREADS; 134 135 typedef struct _SYSTEM_PROCESSES { // Information Class 5 136 ULONG NextEntryDelta; 137 ULONG ThreadCount; 138 ULONG Reserved1[6]; 139 LARGE_INTEGER CreateTime; 140 LARGE_INTEGER UserTime; 141 LARGE_INTEGER KernelTime; 142 UNICODE_STRING ProcessName; 143 ULONG BasePriority; 144 ULONG ProcessId; 145 ULONG InheritedFromProcessId; 146 ULONG HandleCount; 147 ULONG Reserved2[2]; 148 VM_COUNTERS VmCounters; 149 IO_COUNTERSEX IoCounters; // Windows 2000 only 150 SYSTEM_THREADS Threads[1]; 151 } SYSTEM_PROCESSES, *PSYSTEM_PROCESSES; 152 153 typedef struct _SYSTEM_HANDLE_INFORMATION 154 { 155 ULONG ProcessId; 156 UCHAR ObjectTypeNumber; 157 UCHAR Flags; 158 USHORT Handle; 159 PVOID Object; 160 ACCESS_MASK GrantedAccess; 161 } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; 162 163 typedef enum _OBJECT_INFORMATION_CLASS { 164 ObjectBasicInformation, 165 ObjectNameInformation, 166 ObjectTypeInformation, 167 ObjectAllInformation, 168 ObjectDataInformation 169 } OBJECT_INFORMATION_CLASS; 170 171 typedef struct _OBJECT_NAME_INFORMATION { 172 UNICODE_STRING Name; 173 } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; 174 175 typedef NTSTATUS (NTAPI *NTQUERYOBJECT)( 176 _In_opt_ HANDLE Handle, 177 _In_ OBJECT_INFORMATION_CLASS ObjectInformationClass, 178 _Out_opt_ PVOID ObjectInformation, 179 _In_ ULONG ObjectInformationLength, 180 _Out_opt_ PULONG ReturnLength 181 ); 182 183 184 typedef NTSTATUS 185 (NTAPI *ZWQUERYSYSTEMINFORMATION)( 186 IN SYSTEM_INFORMATION_CLASS SystemInformationClass, 187 OUT PVOID SystemInformation, 188 IN ULONG SystemInformationLength, 189 OUT PULONG ReturnLength OPTIONAL 190 ); 191 ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandle("ntdll.dll"),"ZwQuerySystemInformation"); 192 NTQUERYOBJECT NtQueryObject = (NTQUERYOBJECT)GetProcAddress(GetModuleHandle("ntdll.dll"),"NtQueryObject");
1 /*功能函数体*/ 2 int _tmain(int argc, _TCHAR* argv[]) 3 { 4 DWORD dwSize = 0; 5 PSYSTEM_HANDLE_INFORMATION pmodule = NULL; 6 POBJECT_NAME_INFORMATION pNameInfo; 7 POBJECT_NAME_INFORMATION pNameType; 8 PVOID pbuffer = NULL; 9 NTSTATUS Status; 10 int nIndex = 0; 11 DWORD dwFlags = 0; 12 char szType[128] = {0}; 13 char szName[512] = {0}; 14 15 if(!ZwQuerySystemInformation) 16 { 17 goto Exit0; 18 } 19 20 pbuffer = VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE); 21 22 if(!pbuffer) 23 { 24 goto Exit0; 25 } 26 27 Status = ZwQuerySystemInformation(SystemHandleInformation, pbuffer, 0x1000, &dwSize); 28 29 if(!NT_SUCCESS(Status)) 30 { 31 if (STATUS_INFO_LENGTH_MISMATCH != Status) 32 { 33 goto Exit0; 34 } 35 else 36 { 37 // 这里大家可以保证程序的正确性使用循环分配稍好 38 if (NULL != pbuffer) 39 { 40 VirtualFree(pbuffer, 0, MEM_RELEASE); 41 } 42 43 if (dwSize*2 > 0x4000000) // MAXSIZE 44 { 45 goto Exit0; 46 } 47 48 pbuffer = VirtualAlloc(NULL, dwSize*2, MEM_COMMIT, PAGE_READWRITE); 49 50 if(!pbuffer) 51 { 52 goto Exit0; 53 } 54 55 Status = ZwQuerySystemInformation(SystemHandleInformation, pbuffer, dwSize*2, NULL); 56 57 if(!NT_SUCCESS(Status)) 58 { 59 goto Exit0; 60 } 61 } 62 } 63 64 pmodule = (PSYSTEM_HANDLE_INFORMATION)((PULONG)pbuffer+1); 65 dwSize = *((PULONG)pbuffer); 66 67 for(nIndex = 0; nIndex < dwSize; nIndex++) 68 { 69 70 Status = NtQueryObject((HANDLE)pmodule[nIndex].Handle, ObjectNameInformation, szName, 512, &dwFlags); 71 72 if (!NT_SUCCESS(Status)) 73 { 74 goto Exit0; 75 } 76 77 Status = NtQueryObject((HANDLE)pmodule[nIndex].Handle, ObjectTypeInformation, szType, 128, &dwFlags); 78 79 if (!NT_SUCCESS(Status)) 80 { 81 goto Exit0; 82 } 83 84 pNameInfo = (POBJECT_NAME_INFORMATION)szName; 85 pNameType = (POBJECT_NAME_INFORMATION)szType; 86 87 printf("%wZ %wZ\n", pNameType, pNameInfo); 88 89 // 匹配是否为需要关闭的句柄名称 90 if (0 == wcscmp((wchar_t *)pNameType->Name.Buffer, L"Mutant")) 91 { 92 if (wcsstr((wchar_t *)pNameInfo->Name.Buffer, CLOSEMUTEXNAME)) 93 { 94 CloseHandle((HANDLE)pmodule[nIndex].Handle); 95 goto Exit0; 96 } 97 } 98 } 99 100 Exit0: 101 if (NULL != pbuffer) 102 { 103 VirtualFree(pbuffer, 0, MEM_RELEASE); 104 } 105 106 return 0; 107 }
CLOSEMUTEXNAME 为互斥的句柄名称,需要为宽字节;
程序执行结果如下:
为了测试方便直接把程序写入了main函数中,大家使用的时候稍微修改便可, 不过!得理解程序意思才行啊。 copy代码不做思考的程序员不是好裁缝!
参考文章列表:
ZwQuerySystemInformation枚举内核模块及简单应用 http://hi.baidu.com/_achillis/item/8b33ead8ccac28ea3cc2cb17