原文:http://www.cnblogs.com/Y4ng/archive/2012/09/06/EnumProcessHandle_EnumMutex.html

  相信做过游戏多开的朋友就会发现,很多游戏普遍使用互斥mutex来防止程序多开,说实话这种方式已经非常OUT了。但是由于时间和技术的沉淀关系,留下来的游戏依然会存在这种方式。 最近接触到一款游戏是N前非常火热的对战游戏,可以称为经典之作;它就是用的Mutant来实现游戏防止多开的,一般咱们测试的时候都是用Xuetr来关闭游戏,但是要作为成品发布不可能要求客户拿Xuetr来列进程对象句柄,关句柄吧~

网上搜索了半天都没有找到枚举进程句柄的例子,经过群里的大牛提点指到 ZwQuerySystemInformation SystemHandleInformation 可以实现句柄枚举功能;经过一番搜索编码测试 于是有了本文代码;

/*头文件声明*/
typedef LONG NTSTATUS;
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) 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, //
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, //
SystemInvalidInfoClass3, //
SystemTimeZoneInformation, // 44 Y N
SystemLookasideInformation, // 45 Y N
SystemSetTimeSlipEvent, // 46 N Y
SystemCreateSession, // 47 N Y
SystemDeleteSession, // 48 N Y
SystemInvalidInfoClass4, //
SystemRangeStartInformation, // 50 Y N
SystemVerifierInformation, // 51 Y Y
SystemAddVerifier, // 52 N Y
SystemSessionProcessesInformation // 53 Y N
} SYSTEM_INFORMATION_CLASS; typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
}CLIENT_ID,*PCLIENT_ID; typedef struct
{
USHORT Length;
USHORT MaxLen;
USHORT *Buffer;
}UNICODE_STRING, *PUNICODE_STRING; typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; typedef struct _IO_COUNTERSEX {
LARGE_INTEGER ReadOperationCount;
LARGE_INTEGER WriteOperationCount;
LARGE_INTEGER OtherOperationCount;
LARGE_INTEGER ReadTransferCount;
LARGE_INTEGER WriteTransferCount;
LARGE_INTEGER OtherTransferCount;
} IO_COUNTERSEX, *PIO_COUNTERSEX; typedef enum {
StateInitialized,
StateReady,
StateRunning,
StateStandby,
StateTerminated,
StateWait,
StateTransition,
StateUnknown
} THREAD_STATE; typedef struct _VM_COUNTERS {
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG PageFaultCount;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
} VM_COUNTERS;
typedef VM_COUNTERS *PVM_COUNTERS; typedef struct _SYSTEM_THREADS {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
ULONG Priority;
ULONG BasePriority;
ULONG ContextSwitchCount;
THREAD_STATE State;
ULONG WaitReason;
} SYSTEM_THREADS, *PSYSTEM_THREADS; typedef struct _SYSTEM_PROCESSES { // Information Class 5
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved1[];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
ULONG BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[];
VM_COUNTERS VmCounters;
IO_COUNTERSEX IoCounters; // Windows 2000 only
SYSTEM_THREADS Threads[];
} SYSTEM_PROCESSES, *PSYSTEM_PROCESSES; 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 enum _OBJECT_INFORMATION_CLASS {
ObjectBasicInformation,
ObjectNameInformation,
ObjectTypeInformation,
ObjectAllInformation,
ObjectDataInformation
} OBJECT_INFORMATION_CLASS; typedef struct _OBJECT_NAME_INFORMATION {
UNICODE_STRING Name;
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; typedef NTSTATUS (NTAPI *NTQUERYOBJECT)(
_In_opt_ HANDLE Handle,
_In_ OBJECT_INFORMATION_CLASS ObjectInformationClass,
_Out_opt_ PVOID ObjectInformation,
_In_ ULONG ObjectInformationLength,
_Out_opt_ PULONG ReturnLength
); typedef NTSTATUS
(NTAPI *ZWQUERYSYSTEMINFORMATION)(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandle("ntdll.dll"),"ZwQuerySystemInformation");
NTQUERYOBJECT NtQueryObject = (NTQUERYOBJECT)GetProcAddress(GetModuleHandle("ntdll.dll"),"NtQueryObject");
/*功能函数体*/
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwSize = ;
PSYSTEM_HANDLE_INFORMATION pmodule = NULL;
POBJECT_NAME_INFORMATION pNameInfo;
POBJECT_NAME_INFORMATION pNameType;
PVOID pbuffer = NULL;
NTSTATUS Status;
int nIndex = ;
DWORD dwFlags = ;
char szType[] = {};
char szName[] = {}; if(!ZwQuerySystemInformation)
{
goto Exit0;
} pbuffer = VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE); if(!pbuffer)
{
goto Exit0;
} Status = ZwQuerySystemInformation(SystemHandleInformation, pbuffer, 0x1000, &dwSize); if(!NT_SUCCESS(Status))
{
if (STATUS_INFO_LENGTH_MISMATCH != Status)
{
goto Exit0;
}
else
{
// 这里大家可以保证程序的正确性使用循环分配稍好
if (NULL != pbuffer)
{
VirtualFree(pbuffer, , MEM_RELEASE);
} if (dwSize* > 0x4000000) // MAXSIZE
{
goto Exit0;
} pbuffer = VirtualAlloc(NULL, dwSize*, MEM_COMMIT, PAGE_READWRITE); if(!pbuffer)
{
goto Exit0;
} Status = ZwQuerySystemInformation(SystemHandleInformation, pbuffer, dwSize*, NULL); if(!NT_SUCCESS(Status))
{
goto Exit0;
}
}
} pmodule = (PSYSTEM_HANDLE_INFORMATION)((PULONG)pbuffer+);
dwSize = *((PULONG)pbuffer); for(nIndex = ; nIndex < dwSize; nIndex++)
{ Status = NtQueryObject((HANDLE)pmodule[nIndex].Handle, ObjectNameInformation, szName, , &dwFlags); if (!NT_SUCCESS(Status))
{
goto Exit0;
} Status = NtQueryObject((HANDLE)pmodule[nIndex].Handle, ObjectTypeInformation, szType, , &dwFlags); if (!NT_SUCCESS(Status))
{
goto Exit0;
} pNameInfo = (POBJECT_NAME_INFORMATION)szName;
pNameType = (POBJECT_NAME_INFORMATION)szType; printf("%wZ %wZ\n", pNameType, pNameInfo); // 匹配是否为需要关闭的句柄名称
if ( == wcscmp((wchar_t *)pNameType->Name.Buffer, L"Mutant"))
{
if (wcsstr((wchar_t *)pNameInfo->Name.Buffer, CLOSEMUTEXNAME))
{
CloseHandle((HANDLE)pmodule[nIndex].Handle);
goto Exit0;
}
}
} Exit0:
if (NULL != pbuffer)
{
VirtualFree(pbuffer, , MEM_RELEASE);
} return ;
}

CLOSEMUTEXNAME 为互斥的句柄名称,需要为宽字节;

程序执行结果如下:

为了测试方便直接把程序写入了main函数中,大家使用的时候稍微修改便可, 不过!得理解程序意思才行啊。 copy代码不做思考的程序员不是好裁缝!

参考文章列表:

ZwQuerySystemInformation枚举内核模块及简单应用 http://hi.baidu.com/_achillis/item/8b33ead8ccac28ea3cc2cb17

枚举进程句柄File,Section,Mutant,Timer关闭Mutex句柄实现游戏多开的更多相关文章

  1. R3 x64枚举进程句柄

    转载:https://blog.csdn.net/zhuhuibeishadiao/article/details/51292608 需要注意的是:在R3使用ZwQueryObject很容易锁死,需要 ...

  2. CloseHandle 函数--关闭一个句柄

    CloseHandle函数 来源:https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx 作用 ...

  3. File.Create(path)未关闭遇到的一点点问题

    本人老菜鸟一枚,不是因为偶是菜鸟中的老手,而是偶是老了但是还是很菜的鸟╮(╯▽╰)╭,不过打今儿起偶想要腾飞…… 今天写文本文件编辑类时遇到一个小问题,下面先将问题描述一下: 1.写文本文件时都会习惯 ...

  4. [Inno Setup] 在 File Section 之前解压文件

    Prototype: procedure ExtractTemporaryFile(const FileName: String); Description: Extracts the specifi ...

  5. File类与FileInfo类

    File是一个静态类,常用于文件操作,读取,修改文件等等.File类的大部分方法最终都是转换为流(Stream)的操作,只不过是.net提取帮你封装好了这些常用的流.并且会自动清理占用的资源. 例如: ...

  6. C/C++文件输入输出操作——FILE*、fstream、windowsAPI

    基于C的文件操作在ANSI C中,对文件的操作分为两种方式,即流式文件操作和I/O文件操作,下面就分别介绍之. 一.流式文件操作这种方式的文件操作有一个重要的结构FILE,FILE在头文件stdio. ...

  7. C/C++文件输入输出操作——FILE*、fstream、windowsAPI(转载)

    基于C的文件操作 在ANSI C中,对文件的操作分为两种方式,即流式文件操作和I/O文件操作,下面就分别介绍之. 一.流式文件操作 这种方式的文件操作有一个重要的结构FILE,FILE在头文件stdi ...

  8. Systm.IO.File.cs

    ylbtech-Systm.IO.File.cs 1.程序集 mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c5619 ...

  9. FILE文件流的中fopen、fread、fseek、fclose的使用

    FILE文件流用于对文件的快速操作,主要的操作函数有fopen.fseek.fread.fclose,在对文件结构比较清楚时使用这几个函数会比较快捷的得到文件中具体位置的数据,提取对我们有用的信息,满 ...

随机推荐

  1. 在Mac上安装GTK(go语言GUI)

    1.在终端输入:xcode-select --install 安装command line工具, 如果安装了Xcode, 就直接跳过该步骤 2. 在终端输入:ruby -e "$(curl ...

  2. node调试工具--nodemon

  3. 利用setTimeout延时器 制作广告自动关闭

    模仿广告自动关闭效果 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  4. js改变或添加className

    js改变或添加className <style type="text/css"> .newDiv { font-weight: bold; } </style&g ...

  5. SpringBank 开发日志 重新设计Action调用Service的参数传递 使用泛型解决类型转换问题

    之前想的比较简单,请求到达controller的时候,传给action的参数没有经过任何封装,就是一个Map.然后action再调用service的时候,传递的参数也是map @Controller ...

  6. [转] 通过jQuery Ajax使用FormData对象上传文件

    FormData对象,是可以使用一系列的键值对来模拟一个完整的表单,然后使用XMLHttpRequest发送这个"表单". 在 Mozilla Developer 网站 使用For ...

  7. 基于C++11实现线程池的工作原理

    目录 基于C++11实现线程池的工作原理. 简介 线程池的组成 1.线程池管理器 2.工作线程 3.任务接口, 4.任务队列 线程池工作的四种情况. 1.主程序当前没有任务要执行,线程池中的任务队列为 ...

  8. 关于instanceof判断的条件

    //instanceof是判断左侧对象是不是右侧类的实例 package myPackage;     /**   * instanceof运算符用法   * 运算符是双目运算符,左面的操作元是一个对 ...

  9. Java中设置方法执行的超时时间java.util.concurrent.Future

    java.util.concurrent.Future Future代表一个异步计算的结果.它提供了方法来检查是否计算已经完成,还是正在计算而处于等待状态,并且也提供了获取计算结果 方法.当计算完成后 ...

  10. 5288: [Hnoi2018]游戏

    5288: [Hnoi2018]游戏 链接 分析: 考虑y<=x的怎么做,那么只能从左边走到右边.我们可以从最右边的点开始,一次确定每个点往右边可以走多少. L[x],R[x]分别是x向左向右最 ...