目录
游戏多开检测只是对游戏的进程数进行限制,分为事前检测、事中检测、和事后检测。
事中检测和事后检测往往没有提示,是游戏公司封号、处罚的手段,事前检测即禁止游戏多开,本文介绍常见的几种禁止游戏多开的方法,并给出破解方法,仅供参考。
枚举进程的多开检测
基本原理就是枚举所有系统进程,如果发现游戏进程名已经存在则无法继续打开新的进程。
bool isMulOpenByProcess()
{
HANDLE hProShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (hProShot == INVALID_HANDLE_VALUE) return false;
PROCESSENTRY32 pw{ sizeof(pw)};
int count = 0;
BOOL bRet = Process32First(hProShot, &pw);
if (!bRet) return false;
do{
_wcslwr_s(pw.szExeFile, wcslen(pw.szExeFile) + 1);
if (wcscmp(pw.szExeFile, L"muldectection.exe") == 0) count++;
//wprintf(L"%s\n", pw.szExeFile);
} while (Process32Next(hProShot, &pw));
if (count > 1) return true;
return false;
}
参考破解方法—程序运行时修改进程名
互斥对象多开检测
互斥对象是内核对象,当创建带名称的互斥对象时,如果该互斥对象存在,则创建失败。可以利用这一点实现躲开检测。
bool isMulOpenByMutex()
{
HANDLE hMutex = CreateMutexA(NULL, FALSE, "MulDectection");
if (ERROR_ALREADY_EXISTS == GetLastError()) return true;
return false;
}
参考破解方法—可以在PE文件结构中删除互斥对象的句柄;hook CreateMutexA函数 等
信号量多开检测
信号量是内核对象,同互斥对象的原理类似,创建信号量时可以指定信号量的最大数量,程序运行时,可以让信号量加一,如果没法加一,说明信号量数量达到了设置最大值,以此来进行躲开检测
bool isMulOpenBySemaphore()
{
HANDLE hSema;
hSema = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "MulDectection");
if (!hSema)
hSema = CreateSemaphoreA(NULL, 0, 3, "MulDectection");
if (!ReleaseSemaphore(hSema, 1, 0)) return true;
return false;
}
参考破解方案——可以调用WaitForSingleObject减少信号量数量
窗口多开检测
程序运行时寻找是否有同名窗口,如果已经存在则为程序多开。
HWND hWnd=FindWindowA(NULL,"ConsoleWindowClass");
if (hWnd != NULL) return true;
参考破解方案——修改窗口名
共享内存检测多开
通过进程间共享内存段的方式来检测多开
#pragma data_seg("_hdata")
int g_count = 0;
#pragma data_seg()
#pragma comment(linker,"/SECTION:_hdata,RWS")
bool isMulOpenByMemory()
{
g_count++;
if (g_count > 1)return true;
return false;
}
参考破解方案——修改共享内存段的变量的值
示例代码汇总
#include<Windows.h>
#include<iostream>
#include<tlhelp32.h>
#pragma data_seg("_hdata")
int g_count = 0;
#pragma data_seg()
#pragma comment(linker,"/SECTION:_hdata,RWS")
bool isMulOpenByProcess()
{
HANDLE hProShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (hProShot == INVALID_HANDLE_VALUE) return false;
PROCESSENTRY32 pw{ sizeof(pw)};
int count = 0;
BOOL bRet = Process32First(hProShot, &pw);
if (!bRet) return false;
do{
_wcslwr_s(pw.szExeFile, wcslen(pw.szExeFile) + 1);
if (wcscmp(pw.szExeFile, L"muldectection.exe") == 0) count++;
//wprintf(L"%s\n", pw.szExeFile);
} while (Process32Next(hProShot, &pw));
if (count > 1) return true;
return false;
}
bool isMulOpenByMutex()
{
HANDLE hMutex = CreateMutexA(NULL, FALSE, "MulDectection");
if (ERROR_ALREADY_EXISTS == GetLastError()) return true;
return false;
}
bool isMulOpenBySemaphore()
{
HANDLE hSema;
hSema = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "MulDectection");
if (!hSema)
hSema = CreateSemaphoreA(NULL, 0, 3, "MulDectection");
if (!ReleaseSemaphore(hSema, 1, 0)) return true;
return false;
}
bool isMulOpenByFindWindow()
{
HWND hWnd=FindWindowA(NULL,"ConsoleWindowClass");
if (hWnd != NULL) return true;
return false;
}
bool isMulOpenByMemory()
{
g_count++;
if (g_count > 1)return true;
return false;
}
int main()
{
if (isMulOpenByMemory())
{
MessageBoxA(NULL, "程序禁止多开", "MulDectection", MB_OK);
return -1;
}
MessageBoxA(NULL, "打开成功!", "MulDectection", MB_OK);
return 0;
}