游戏限制多开有很多种方法

比如说遍历窗口,遍历进程,配置文件,注册表,互斥体,mac地址,ip,公共文件,内存映射等等.方法很多.

但是绝大部分游戏限制多开都是采用的互斥体.

这节课我们来讲解一下关闭互斥体句柄来实现多开.例子为CQYH

(这里的防护建议是,增加多种多开限制的方法 以及 逻辑中增加多该互斥体的使用,这样可以避免直接被恶意关闭)

一.验证限制多开

首先我们打开游戏

然后再开第二个窗口

发现已经检测到我们开了一个窗口,只是没有进行限制

再开第三个窗口的时候出现了限制

很明显限制了多开,只能开2个

二.工具查看互斥体并关闭

我们可以使用工具来查看互斥体,大家可以用XT,PCH等等工具

也可以直接到公众号  任鸟飞逆向  资源下载中下载以下工具

打开软件,找到我们的进程,右键查看句柄

出现了很多句柄, 找到Mutant类型的句柄

发现有很多,没有名字的可以不管

剩下有名字的句柄有20-30个

我们逐一关闭,看看关闭哪个之后就可以多开窗口了

发现关闭这个就可以了,名字是  AOD_Game

可以开3个窗口了

三,编写代码,关闭互斥体句柄

添加一个头文件"Mutex.h"

用作关闭互斥体句柄

#pragma once
#include <string.h>
#include <windows.h>
#include <winternl.h>
#include <TlHelp32.h>// 定义需要的宏
#define STATUS_SUCCESS 0x00UL
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004#define SystemHandleInformation 16
#define SE_DEBUG_PRIVILEGE 0x14// 定义需要用到的结构体
typedef enum _OBJECT_INFORMATION_CLASSEX {ObjBasicInformation = 0,ObjNameInformation,ObjTypeInformation,
} OBJECT_INFORMATION_CLASSEX;typedef enum _PROCESSINFOCLASSEX
{ProcessHandleInformation = 20,
}PROCESSINFOCLASSEX;typedef struct _SYSTEM_HANDLE
{ULONG ProcessId;BYTE ObjectTypeNumber;BYTE Flags;USHORT Handle;PVOID Object;ACCESS_MASK GrantAccess;
}SYSTEM_HANDLE;typedef struct _SYSTEM_HANDLE_INFORMATION
{DWORD HandleCount;SYSTEM_HANDLE Handles[1];
}SYSTEM_HANDLE_INFORMATION;typedef struct _OBJECT_NAME_INFORMATION
{UNICODE_STRING ObjectName;
}OBJECT_NAME_INFORMATION;// 声明未导出API
typedef NTSTATUS(WINAPI* ZwQueryInformationProcessProc)(HANDLE, PROCESSINFOCLASSEX, LPVOID, DWORD, PDWORD);
ZwQueryInformationProcessProc ZwQueryInformationProcess;typedef NTSTATUS(WINAPI* ZwQuerySystemInformationProc)(DWORD, PVOID, DWORD, DWORD*);
ZwQuerySystemInformationProc ZwQuerySystemInformation;typedef NTSTATUS(WINAPI* ZwQueryObjectProc)(HANDLE, OBJECT_INFORMATION_CLASSEX, PVOID, ULONG, PULONG);
ZwQueryObjectProc ZwQueryObject;typedef NTSTATUS(WINAPI* RtlAdjustPrivilegeProc)(DWORD, BOOL, BOOL, PDWORD);
RtlAdjustPrivilegeProc RtlAdjustPrivilege;typedef DWORD(WINAPI* ZwSuspendProcessProc)(HANDLE);
ZwSuspendProcessProc ZwSuspendProcess;typedef DWORD(WINAPI* ZwResumeProcessProc)(HANDLE);
ZwResumeProcessProc ZwResumeProcess;#pragma warning (disable: 6011)
#pragma warning (disable: 6001)
#pragma warning (disable: 6387)
#include <stdio.h>// 提升进程权限
BOOL ElevatePrivileges()
{HANDLE hToken;TOKEN_PRIVILEGES tkp;tkp.PrivilegeCount = 1;if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))return FALSE;LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid);tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)){return FALSE;}return TRUE;
}// 初始化未导出API
BOOL GetUnDocumentAPI()
{ZwSuspendProcess = (ZwSuspendProcessProc)GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwSuspendProcess");ZwQuerySystemInformation = (ZwQuerySystemInformationProc)GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwQuerySystemInformation");ZwQueryObject = (ZwQueryObjectProc)GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwQueryObject");ZwResumeProcess = (ZwResumeProcessProc)GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwResumeProcess");ZwQueryInformationProcess = (ZwQueryInformationProcessProc)GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwQueryInformationProcess");if ((ZwSuspendProcess == NULL) || \(ZwQuerySystemInformation == NULL) || \(ZwQueryObject == NULL) || \(ZwResumeProcess == NULL) || \(ZwQueryInformationProcess == NULL))return FALSE;return TRUE;
}// 关闭指定Mutex  有问题关注公众号  任鸟飞逆向
BOOL closeMutexHandle(UINT Proc_id, const wchar_t* Mutex_name)
{HANDLE duplicateHnd, sourceHnd = 0;DWORD procHndNum;SYSTEM_HANDLE* currnetHnd;DWORD buffLen = 0x1000;NTSTATUS status;SYSTEM_HANDLE_INFORMATION* buff = (SYSTEM_HANDLE_INFORMATION*)malloc(buffLen);UINT count = 0;if ((ElevatePrivileges() == FALSE) || (GetUnDocumentAPI() == FALSE))return FALSE;do{status = ZwQuerySystemInformation(SystemHandleInformation, buff, buffLen, &buffLen);if (status == STATUS_INFO_LENGTH_MISMATCH){free(buff);buff = (SYSTEM_HANDLE_INFORMATION*)malloc(buffLen);}elsebreak;} while (1);OBJECT_NAME_INFORMATION* objNameInfo = (OBJECT_NAME_INFORMATION*)malloc(0x1000);OBJECT_NAME_INFORMATION* objTypeInfo = (OBJECT_NAME_INFORMATION*)malloc(0x1000);for (int idx = 0; idx < (int)buff->HandleCount; idx++){currnetHnd = &(buff->Handles[idx]);if (currnetHnd->ProcessId == Proc_id){sourceHnd = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_DUP_HANDLE | PROCESS_SUSPEND_RESUME, FALSE, Proc_id);(ZwSuspendProcess)(sourceHnd);(ZwQueryInformationProcess)(sourceHnd, ProcessHandleInformation, &procHndNum, sizeof(DWORD), NULL);//进程有效句柄从4开始,每次以4递增unsigned short hndNum = 4;for (int idx = 0; idx < (int)procHndNum; hndNum += 4){//判断是否为有效句柄,返回TRUE,就是有效句柄if (!DuplicateHandle(sourceHnd,(HANDLE)hndNum,GetCurrentProcess(),&duplicateHnd, 0, FALSE, DUPLICATE_SAME_ACCESS)){continue;}else{memset(objNameInfo, 0, 0x1000);memset(objTypeInfo, 0, 0x1000);ZwQueryObject((HANDLE)duplicateHnd, ObjNameInformation, objNameInfo, 0x1000, NULL);ZwQueryObject((HANDLE)duplicateHnd, ObjTypeInformation, objTypeInfo, 0x1000, NULL);//找到互斥体 比较名字if (wcscmp(objTypeInfo->ObjectName.Buffer, L"Mutant") == 0){if (objNameInfo->ObjectName.Length != 0 && wcsstr(objNameInfo->ObjectName.Buffer, Mutex_name) != 0){printf("%ws\n", objNameInfo->ObjectName.Buffer);CloseHandle(duplicateHnd);if (DuplicateHandle(sourceHnd,(HANDLE)hndNum,GetCurrentProcess(),&duplicateHnd, 0, FALSE, DUPLICATE_CLOSE_SOURCE)){CloseHandle(duplicateHnd);(ZwResumeProcess)(sourceHnd);return TRUE;}}count++;if (count == 20) { return FALSE; }}CloseHandle(duplicateHnd);idx++;}}}}return FALSE;
}

然后我们调用


closeMutexHandle(sm[i].pid,L"AOD_Game");

四,调整窗口位置进行多开

然后我们进行窗口布局

好的,我们的效果实现了.

解除游戏多开限制,关闭互斥体句柄相关推荐

  1. 关闭互斥体实现微信多开,适用于现在所有版本

    关闭互斥体实现微信多开,适用于现在所有版本 上一篇文章写了一个有版本限制的多开方法,现在有了个适用于所有版本的多开方法. 只要关闭互斥体句柄就能实现多开. 就是枚举微信进程所有的句柄,找出_WeCha ...

  2. python多开游戏_易语言通过句柄名来关闭互斥体实现游戏多开的代码

    DLL命令代码 .版本 2 .DLL命令 GetProcessHandleCount, 逻辑型 .参数 hProcess, 整数型 .参数 pdwHandleCount, 整数型, 传址 .DLL命令 ...

  3. 游戏多开的若干对抗方法

    第一,进程隐藏 部分游戏通过探测游戏客户端进程是否已经存在来防止重复打开. 游戏多开的办法为启动一个游戏客户端后,将该游戏所有启动的进程全部隐藏.(进程隐藏的办法多了,这个后面一点点学习) 第二,窗口 ...

  4. CreateMutex创建互斥体可以用于只运行进程的一个实例

    CreateMutex 作用 找出当前系统是否已经存在指定进程的实例.如果没有则创建一个互斥体.CreateMutex()函数可用来创建一个有名或无名的互斥量对象,其函数原型为 VC声明 HANDLE ...

  5. 【免杀前置课——Windows编程】十三、事件与信号量——事件与互斥体区别、操纵信号量实现游戏多开访问控制(附代码)

    事件 事件可以完全控制,其他无法控制线程的执行顺序,但是事件对象可以做到. ***事件(Event)***是在线程同步中最常使用的一种同步对象,事件包含一个使用计数,一个是用来表示自动重置/手动重置的 ...

  6. 游戏多开的分析与实现

    大部分游戏为了防止工作室通过多开游戏牟利,都会采取各种手段来防止游戏被多次打开.检测窗口标题,创建互斥体,创建内存映射这些都是防止游戏多开的常用手段. 主要内容 游戏运行后,无非执行两步操作 若已经存 ...

  7. 使用互斥体使程序只运行一个

    何为互斥体 引用了百科的话 互斥体实现了"互相排斥"(mutual exclusion)同步的简单形式(所以名为互斥体(mutex)).互斥体禁止多个线程同时进入受保护的代码&qu ...

  8. VC防止程序被多次运行 互斥体方法

    BOOL CXXXApp::InitInstance() //函数内添加代码HANDLE hMutex=CreateMutex(NULL,TRUE,"test"); // 用于检测 ...

  9. Windows事件等待学习笔记(四)—— 事件信号量互斥体

    Windows事件等待学习笔记(四)-- 事件&信号量&互斥体 要点回顾 事件 实验:验证SignalState 第一步:编译并运行以下代码 第二步:观察结果 第三步:修改代码并执行 ...

最新文章

  1. RxJava 从源码到使用
  2. java canvas 画图片_[Java教程][HTML5] Canvas绘制简单图片
  3. C++之dynamic_cast、static_cast、const_cast、reinterpret_cast的用法和区别
  4. 去除图片水印_只需一键,即可快速去除图片水印!如此简单的方法,谁不知谁吃亏...
  5. 解决移动端 手机号input 属性为 number,maxlength无效情况
  6. java seek指针 换行符_Java网络编程探究|乐字节
  7. c语言学习-编写递归函数用于计算n!
  8. redhat7扩容linux,vmware中Centos 7 linux的LVM磁盘扩容
  9. 刷屏了!这篇Python学习贴,90%的程序员都用的上!
  10. 推理集 —— 特殊的工具
  11. linux下的系统服务管理及日志管理
  12. 手机能识别sim卡但是没信号_一篇文章扫盲手机SIM卡相关知识
  13. Flink系列之流式
  14. STVD环境下开发STM8,如何查看工程占用的Flash、EEPROM、RAM的情况
  15. 拉钩网爬取所有python职位信息
  16. 计算机英语单词练习五
  17. c++ 求四边形面积和周长_C++几何图形面积周长计算
  18. 什么是轻量应用服务器
  19. 微信图片 自动上传到服务器,微信小程序怎样使图片上传至服务器
  20. 图像分类篇:pytorch实现ResNet

热门文章

  1. 微信支付0.2%费率开通详细操作教程
  2. 拳王虚拟项目公社:一个持续收益的虚拟资源平台三种虚拟资源项目
  3. Unity 3D开发--Shader入门基础
  4. 怎么用python横排输出古诗_PYTHON小工具-竖排表格内容转横向输出
  5. Linux 新建用户组并安装jdk
  6. Webpack打包之坑 _ webpackChunkName【魔法注释】
  7. 运维实操——zabbix监控结合tidb分布式数据库
  8. Alien Skin ExposureX8最新ps中文版调色滤镜插件
  9. 太白与我语,为我开天关——五一太白南北穿
  10. 微信公众号点击菜单出现多条文章