您现在的位置是:首页 >其他 >解除游戏多开限制,关闭互斥体句柄网站首页其他

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

任鸟飞逆向~ 2023-05-12 20:15:03
简介(这里的防护建议是,增加多种多开限制的方法 以及 逻辑中增加多该互斥体的使用,这样可以避免直接被恶意关闭)比如说遍历窗口,遍历进程,配置文件,注册表,互斥体,mac地址,ip,公共文件,内存映射等等.方法很多.我们可以使用工具来查看互斥体,大家可以用XT,PCH等等工具。发现已经检测到我们开了一个窗口,只是没有进行限制。我们逐一关闭,看看关闭哪个之后就可以多开窗口了。出现了很多句柄, 找到Mutant类型的句柄。

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

比如说遍历窗口,遍历进程,配置文件,注册表,互斥体,mac地址,ip,公共文件,内存映射等等.方法很多.
但是绝大部分游戏限制多开都是采用的互斥体.
这节课我们来讲解一下关闭互斥体句柄来实现多开.例子为CQYH

 

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

一.验证限制多开

首先我们打开游戏
然后再开第二个窗口
发现已经检测到我们开了一个窗口,只是没有进行限制

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

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

 

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

我们可以使用工具来查看互斥体,大家可以用XT,PCH等等工具
也可以直接到公众号:任鸟飞逆向 里下载Pyark.zip
打开软件,找到我们的进程,右键查看句柄

出现了很多句柄, 找到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);
}
else
break;

} 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
", 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");

四,调整窗口位置进行多开
然后我们进行窗口布局

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

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。