604 lines
14 KiB
C++
604 lines
14 KiB
C++
#include "SunClientPrecompiledHeader.h"
|
|
#include "GameCheckMananger.h"
|
|
#include <shlwapi.h>
|
|
#pragma comment(lib,"shlwapi.lib")
|
|
#include <Psapi.h>
|
|
#pragma comment (lib,"Psapi.lib")
|
|
#include "GlobalFunc.h"
|
|
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lparam);
|
|
HANDLE m_CheckHandle[2];
|
|
DWORD WINAPI GameCheck(LPVOID lpparentet);
|
|
HANDLE CheckThreadHandle = NULL;
|
|
#include "Application.h"
|
|
|
|
GameCheckMananger::GameCheckMananger(void):
|
|
bIsInit(false),bIsChecked(false)
|
|
{
|
|
if (!Initialize())
|
|
{
|
|
SetChecked("检测模块初始化失败","初始化失败");
|
|
}
|
|
}
|
|
|
|
GameCheckMananger::~GameCheckMananger(void)
|
|
{
|
|
//[清理][BY:十里坡剑神][QQ:112582793][2020-4-17 0:09]
|
|
m_ProcessInfo.clear();
|
|
m_ModuleInfo.clear();
|
|
m_WindowsText.clear();
|
|
|
|
m_ProcessList.clear();
|
|
m_ModuleList.clear();
|
|
m_WindwosList.clear();
|
|
}
|
|
|
|
StringVector GameCheckMananger::split(string& str, const char* c)
|
|
{//字符串分割
|
|
char *cstr = NULL;
|
|
char *p = NULL;
|
|
char * buff = NULL;
|
|
StringVector res;
|
|
cstr = new char[str.size() + 1];
|
|
strcpy_s(cstr, str.size() + 1, str.c_str());
|
|
p = strtok_s(cstr, c, &buff);
|
|
while (p != NULL)
|
|
{
|
|
res.push_back(p);
|
|
p = strtok_s(NULL, c, &buff);
|
|
}
|
|
if (p != NULL)
|
|
{
|
|
delete[] p;
|
|
p = NULL;
|
|
}
|
|
if (cstr != NULL)
|
|
{
|
|
delete[]cstr;
|
|
cstr = NULL;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
void GameCheckMananger::SetUserID(string UserID)
|
|
{
|
|
mUserID = UserID;
|
|
}
|
|
void GameCheckMananger::SetCharName(string CharName)
|
|
{
|
|
mCharName=CharName;
|
|
}
|
|
void GameCheckMananger::GetCheatData()
|
|
{//检测列表初始化
|
|
//下载检测列表
|
|
string Ret = Download("http://sun2.online/ProgramList.txt");
|
|
|
|
//清空待检测列表容器
|
|
m_WindwosList.clear();
|
|
m_ProcessList.clear();
|
|
m_ModuleList.clear();
|
|
|
|
StringVector vCheckList, vCheckInfo;
|
|
|
|
vCheckList = split(Ret, "#\r\n");
|
|
|
|
StringVector::iterator iter;
|
|
|
|
iter = vCheckList.begin();
|
|
|
|
if(vCheckList.size()==0)
|
|
{
|
|
return ;
|
|
}
|
|
while (1)
|
|
{
|
|
if (iter==vCheckList.end())
|
|
break;
|
|
else
|
|
{
|
|
vCheckInfo = split(*iter, "|");
|
|
if (vCheckInfo.size() == 3)
|
|
{
|
|
string strCheckName;
|
|
|
|
strCheckName = vCheckInfo[1];
|
|
|
|
std::transform(strCheckName.begin(),strCheckName.end(),strCheckName.begin(),::toupper);
|
|
|
|
switch (atol(vCheckInfo[0].c_str()))
|
|
{
|
|
case 1:
|
|
m_WindwosList.push_back(strCheckName);
|
|
break;
|
|
case 2:
|
|
m_ProcessList.push_back(strCheckName);
|
|
break;
|
|
case 3:
|
|
m_ModuleList.push_back(strCheckName);
|
|
break;
|
|
case 4:
|
|
m_SysList.push_back(strCheckName);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
//else MYDEBUGMSG("vCheckInfo.size()!= 3--%s",iter->c_str());
|
|
std::vector<std::string>(vCheckInfo).swap(vCheckInfo);
|
|
iter++;
|
|
}
|
|
}
|
|
std::vector<std::string>(vCheckList).swap(vCheckList);
|
|
}
|
|
|
|
void GameCheckMananger::InitGameCheck()
|
|
{
|
|
if(bIsInit) return;
|
|
|
|
GetCheatData();
|
|
|
|
m_CheckHandle[0] = CreateEvent(NULL,FALSE,FALSE,NULL);
|
|
m_CheckHandle[1] = CreateEvent(NULL,FALSE,FALSE,NULL);
|
|
|
|
bIsInit = true;
|
|
CheckThreadHandle = CreateThread(NULL, 0, GameCheck, NULL, 0, NULL);
|
|
if (CheckThreadHandle == NULL)
|
|
{
|
|
SetChecked("检测线程创建失败","线程创建失败");
|
|
}
|
|
}
|
|
|
|
void GameCheckMananger::Process()
|
|
{
|
|
if(!bIsInit)
|
|
{
|
|
if(bIsChecked&&GetTickCount()-mdwCloseCount>5000)
|
|
{
|
|
//GlobalFunc::LogOutGame();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if(mUserID.length()>0&&
|
|
mCharName.length()>0&&
|
|
mProgramName.length()>0&&
|
|
mProgramPath.length()>0&&bIsChecked)
|
|
{//检测到外挂信息,以及所需信息收集足够,发送信息到服务端然后退出游戏
|
|
MSG_CG_CONNECTION_HACKER_SYN msg;
|
|
Sprintf(msg.pszCharName,"%s",mCharName.c_str());
|
|
Sprintf(msg.pszProgramName,"%s",mProgramName.c_str());
|
|
Sprintf(msg.pszProgramPath,"%s",mProgramPath.c_str());
|
|
Sprintf(msg.pszUserID,"%s",mUserID.c_str());
|
|
|
|
//GlobalFunc::SendPacket( CI_GAMESERVERIDX, &msg, sizeof(msg));
|
|
//bIsInit=false;
|
|
//mdwCloseCount=GetTickCount();
|
|
return;
|
|
}
|
|
|
|
if(bIsChecked)
|
|
return;
|
|
|
|
SetEvent(m_CheckHandle[1]);
|
|
|
|
DWORD dwRet = ResumeThread(CheckThreadHandle);
|
|
if (dwRet != 0)
|
|
{//[线程被挂起][BY:十里坡剑神][QQ:112582793][2020-4-5 18:21]
|
|
SetChecked("检测线程被挂起","线程被挂起");
|
|
}
|
|
|
|
//操作GM工具会导致游戏线程挂起,导致误判.GM工具下屏蔽该检测
|
|
//具体表现为工具点击发放物品游戏闪退,可以用此方法放一些测试端,共享端.
|
|
//[获取检测线程上下文内容,线程被结束GetLastError返回5,否则返回0,返回1400是因为线程没初始化完成][BY:十里坡剑神][QQ:112582793][2020-4-5 18:23]
|
|
CONTEXT context = { 0 };
|
|
context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS;
|
|
GetThreadContext(CheckThreadHandle, &context);
|
|
dwRet = 0;
|
|
dwRet = GetLastError();
|
|
if (dwRet == 5)
|
|
{//[线程被结束][BY:十里坡剑神][QQ:112582793][2020-4-5 18:21]
|
|
SetChecked("检测线程被结束","线程被结束");
|
|
}
|
|
}
|
|
|
|
BOOL GameCheckMananger::GetProcessInfo()
|
|
{
|
|
m_ProcessInfo.clear();
|
|
m_ModuleInfo.clear();
|
|
m_WindowsText.clear();
|
|
m_SysInfo.clear();
|
|
HANDLE hProcessSnap;
|
|
HANDLE hProcess;
|
|
PROCESSENTRY32 stcPe32={0,};
|
|
stcPe32.dwSize = sizeof(PROCESSENTRY32);
|
|
|
|
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
|
|
|
|
if(hProcessSnap==INVALID_HANDLE_VALUE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
if(!Process32First(hProcessSnap,&stcPe32))
|
|
{
|
|
CloseHandle(hProcessSnap);
|
|
return FALSE;
|
|
}
|
|
do
|
|
{
|
|
try
|
|
{
|
|
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,stcPe32.th32ProcessID);
|
|
if(hProcess)
|
|
{
|
|
int nPriority = GetPriorityClass(hProcess);
|
|
CloseHandle(hProcess);
|
|
}
|
|
PROCINFO info;
|
|
info.dwPId =stcPe32.th32ProcessID;
|
|
info.ProcessName = stcPe32.szExeFile;
|
|
info.ProcessPath = GetProcessFullPath(stcPe32.th32ProcessID);
|
|
std::transform(info.ProcessName.begin(),info.ProcessName.end(),info.ProcessName.begin(),::toupper);
|
|
m_ProcessInfo[info.ProcessName] = info;
|
|
GetModuleInfo(stcPe32.th32ProcessID);
|
|
}
|
|
catch (...)
|
|
{
|
|
//CHATMGR->AddMsg(CTC_SYSMSG,"异常处理");
|
|
}
|
|
|
|
} while (Process32Next(hProcessSnap,&stcPe32));
|
|
CloseHandle(hProcessSnap);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL GameCheckMananger::GetModuleInfo(DWORD dwPId)
|
|
{
|
|
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
|
|
MODULEENTRY32 me32 ;
|
|
me32.dwSize = sizeof(MODULEENTRY32);
|
|
hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32,dwPId);
|
|
if(hModuleSnap==INVALID_HANDLE_VALUE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if(!Module32First(hModuleSnap,&me32))
|
|
{
|
|
CloseHandle(hModuleSnap);
|
|
return FALSE;
|
|
}
|
|
do
|
|
{
|
|
try
|
|
{
|
|
std::string szModule(me32.szModule);
|
|
std::transform(szModule.begin(),szModule.end(),szModule.begin(),::toupper);
|
|
m_ModuleInfo[szModule] = me32.szExePath;
|
|
}
|
|
catch (...)
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
while (Module32Next(hModuleSnap,&me32));
|
|
CloseHandle(hModuleSnap);
|
|
return TRUE;
|
|
}
|
|
BOOL GameCheckMananger::DosPathToNtPath(LPTSTR pszDosPath, LPTSTR pszNtPath)
|
|
{
|
|
TCHAR szDriveStr[500] = {0,};
|
|
TCHAR szDrive[3] = { 0, };
|
|
TCHAR szDevName[100] = { 0, };
|
|
INT cchDevName = 0;
|
|
INT i = 0;
|
|
|
|
//[检查参数][By:十里坡剑神][QQ:112582793][2017/12/27]
|
|
if(!pszDosPath || !pszNtPath )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//[获取本地磁盘字符串 ][By:十里坡剑神][QQ:112582793][2017/12/27]
|
|
if(GetLogicalDriveStrings(sizeof(szDriveStr), szDriveStr))
|
|
{
|
|
for(i = 0; szDriveStr[i]; i += 4)
|
|
{
|
|
if(!lstrcmpi(&(szDriveStr[i]), _T("A:\\")) || !lstrcmpi(&(szDriveStr[i]), _T("B:\\")))
|
|
continue;
|
|
|
|
szDrive[0] = szDriveStr[i];
|
|
szDrive[1] = szDriveStr[i + 1];
|
|
szDrive[2] = '\0';
|
|
if(!QueryDosDevice(szDrive, szDevName, 100))//[查询 Dos 设备名 ][By:十里坡剑神][QQ:112582793][2017/12/27]
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
cchDevName = lstrlen(szDevName);
|
|
if(_tcsnicmp(pszDosPath, szDevName, cchDevName) == 0)//[命中][By:十里坡剑神][QQ:112582793][2017/12/27]
|
|
{
|
|
lstrcpy(pszNtPath, szDrive);//[复制驱动器 ][By:十里坡剑神][QQ:112582793][2017/12/27]
|
|
lstrcat(pszNtPath, pszDosPath + cchDevName);//[复制路径][By:十里坡剑神][QQ:112582793][2017/12/27]
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
lstrcpy(pszNtPath, pszDosPath);
|
|
return FALSE;
|
|
}
|
|
|
|
string GameCheckMananger::GetProcessFullPath(DWORD dwPID)
|
|
{
|
|
TCHAR szImagePath[MAX_PATH];
|
|
TCHAR pszFullPath[MAX_PATH];
|
|
HANDLE hProcess;
|
|
std::string strPath;
|
|
strPath = "";
|
|
if(!pszFullPath)
|
|
return strPath;
|
|
|
|
pszFullPath[0] = '\0';
|
|
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, dwPID);
|
|
if(!hProcess)
|
|
return strPath;
|
|
|
|
if(!GetProcessImageFileName(hProcess, szImagePath, MAX_PATH))
|
|
{
|
|
CloseHandle(hProcess);
|
|
return strPath;
|
|
}
|
|
|
|
if(!DosPathToNtPath(szImagePath, pszFullPath))
|
|
{
|
|
CloseHandle(hProcess);
|
|
return strPath;
|
|
}
|
|
|
|
CloseHandle(hProcess);
|
|
strPath = pszFullPath;
|
|
return strPath;
|
|
}
|
|
void GameCheckMananger::AddSysInfo(std::string sysName)
|
|
{
|
|
|
|
std::transform(sysName.begin(), sysName.end(), sysName.begin(), ::toupper);
|
|
m_SysInfo.push_back(sysName);
|
|
}
|
|
void GameCheckMananger::AddWindowText(std::string str,HWND hwnd)
|
|
{
|
|
std::transform(str.begin(),str.end(),str.begin(),::toupper);
|
|
m_WindowsText[str] = hwnd;
|
|
}
|
|
BOOL GameCheckMananger::CheckProcessList()
|
|
{
|
|
if (m_ProcessInfo.size() == 0 || m_ProcessList.size() == 0 /*|| m_ProcessInfo.size() < 20 || m_ProcessList.size() < 20*/)
|
|
{//进程检测加进程数量检测,虚拟机一般进程数比较少
|
|
//m_ProcessInfo不重复进程数,m_ProcessList检测文件加载的进程检测数目
|
|
char buff[1024]={0};
|
|
sprintf(buff,"m_ProcessInfo=%d---m_ProcessList=%d",m_ProcessInfo.size(),m_ProcessList.size());
|
|
SetChecked(buff,"进程列表异常");
|
|
return TRUE;
|
|
}
|
|
std::vector<std::string>::iterator iter;
|
|
std::map<std::string,PROCINFO>::iterator mIter;
|
|
iter = m_ProcessList.begin();
|
|
while(TRUE)
|
|
{
|
|
if(iter==m_ProcessList.end())
|
|
break;
|
|
else
|
|
{
|
|
mIter = m_ProcessInfo.find(iter->c_str());
|
|
if(mIter!=m_ProcessInfo.end())
|
|
{
|
|
//[检测到指定进程,发送消息到服务端记录][By:十里坡剑神][QQ:112582793][2017/12/27]
|
|
SetChecked(mIter->second.ProcessName,mIter->second.ProcessPath);
|
|
return TRUE;
|
|
}
|
|
}
|
|
iter++;
|
|
}
|
|
return FALSE;
|
|
}
|
|
BOOL GameCheckMananger::CheckModuleList()
|
|
{
|
|
//return FALSE;
|
|
if(m_ModuleInfo.size()==0||m_ModuleList.size()==0)
|
|
{
|
|
char buff[1024]={0};
|
|
sprintf(buff,"m_ModuleInfo=%d---m_ModuleList=%d",m_ModuleInfo.size(),m_ModuleList.size());
|
|
SetChecked(buff,"模块列表异常");
|
|
return TRUE;
|
|
}
|
|
std::map<std::string,std::string>::iterator mIter;
|
|
std::vector<std::string>::iterator iter;
|
|
iter = m_ModuleList.begin();
|
|
while(TRUE)
|
|
{
|
|
if(iter==m_ModuleList.end())
|
|
break;
|
|
else
|
|
{
|
|
mIter = m_ModuleInfo.find(iter->c_str());
|
|
if(mIter!=m_ModuleInfo.end())
|
|
{
|
|
SetChecked(iter->c_str(),mIter->second);
|
|
return TRUE;
|
|
}
|
|
}
|
|
iter++;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void GameCheckMananger::GetSysInfo()
|
|
{
|
|
m_SysInfo.clear();
|
|
LPVOID drivers[1024] = { 0 };
|
|
DWORD cbNeeded;
|
|
int cDrivers, i;
|
|
|
|
if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) && cbNeeded < sizeof(drivers))
|
|
{
|
|
char szDriver[1024] = { 0 };
|
|
|
|
cDrivers = cbNeeded / sizeof(drivers[0]);
|
|
|
|
for (i = 0; i < cDrivers; i++)
|
|
{
|
|
if (GetDeviceDriverBaseName(drivers[i], szDriver, sizeof(szDriver) / sizeof(szDriver[0])))
|
|
{
|
|
AddSysInfo(szDriver);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
BOOL GameCheckMananger::CheckSysList()
|
|
{//驱动模块检测
|
|
|
|
if (m_SysList.size() == 0 || m_SysInfo.size() == 0)
|
|
{
|
|
char buff[1024]={0};
|
|
sprintf(buff,"m_SysList=%d---m_SysInfo=%d",m_SysList.size(),m_SysInfo.size());
|
|
SetChecked(buff,"驱动列表异常");
|
|
return TRUE;
|
|
}
|
|
|
|
std::vector<std::string>::iterator iter;
|
|
iter = m_SysList.begin();
|
|
for (; iter != m_SysList.end(); iter++)
|
|
{
|
|
if (std::find(m_SysInfo.begin(), m_SysInfo.end(), *iter) != m_SysInfo.end())
|
|
{
|
|
//[检测到指定进程,发送消息到服务端记录][By:十里坡剑神][QQ:112582793][2017/12/27]
|
|
SetChecked((*iter).c_str(),(*iter).c_str());
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
void GameCheckMananger::SetChecked(string Name,string Path)
|
|
{
|
|
bIsChecked=true;
|
|
mProgramName=Name;
|
|
mProgramPath=Path;
|
|
MYDEBUGMSG("%s-%s",Name.c_str(),Path.c_str());
|
|
}
|
|
BOOL GameCheckMananger::CheckWindowList()
|
|
{
|
|
|
|
if(m_WindowsText.size()==0||m_WindwosList.size()==0)
|
|
{
|
|
char buff[1024]={0};
|
|
sprintf(buff,"m_SysList=%d---m_SysInfo=%d",m_SysList.size(),m_SysInfo.size());
|
|
SetChecked(buff,"窗口列表异常");
|
|
return FALSE;
|
|
}
|
|
std::vector<std::string>::iterator iter;
|
|
iter = m_WindwosList.begin();
|
|
while(TRUE)
|
|
{
|
|
if(iter==m_WindwosList.end())
|
|
break;
|
|
else
|
|
{
|
|
std::map<std::string,HWND>::iterator mIter1;
|
|
mIter1 = m_WindowsText.begin();
|
|
while(TRUE)
|
|
{
|
|
if(mIter1==m_WindowsText.end())
|
|
break;
|
|
else
|
|
{
|
|
if(mIter1->first.find(iter->c_str())!=mIter1->first.npos)
|
|
{
|
|
SetChecked(iter->c_str(),mIter1->first.c_str());
|
|
return TRUE;
|
|
}
|
|
}
|
|
mIter1++;
|
|
}
|
|
}
|
|
iter++;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
BOOL CALLBACK EnumChildProc(HWND hWnd, LPARAM lParam)
|
|
{
|
|
char temp1[256] = { 0 }, temp2[256] = {0};
|
|
|
|
::SendMessage(hWnd, WM_GETTEXT, sizeof(temp1) / sizeof(char), (LPARAM)temp2);
|
|
|
|
if(strlen(temp2)>0)
|
|
{
|
|
GameCheckMananger::Instance()->AddWindowText(temp2,hWnd);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lparam)
|
|
{
|
|
char str[512] = {0,};
|
|
::GetWindowText(hwnd,str,sizeof(str));
|
|
if(strlen(str)>0)
|
|
{
|
|
GameCheckMananger::Instance()->AddWindowText(str,hwnd);
|
|
::EnumChildWindows(hwnd, EnumChildProc, 0);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD WINAPI GameCheck(LPVOID lpparentet)
|
|
{
|
|
MYDEBUGMSG("GameCheck Start!!");
|
|
while(TRUE)
|
|
{
|
|
DWORD dwID = WaitForMultipleObjects(2,m_CheckHandle,FALSE,INFINITE);
|
|
|
|
switch(dwID)
|
|
{
|
|
case 1:
|
|
{
|
|
GameCheckMananger::Instance()->GetProcessInfo();
|
|
::EnumWindows(EnumWindowsProc,NULL);
|
|
GameCheckMananger::Instance()->GetSysInfo();
|
|
//Sleep(2000);
|
|
SetEvent(m_CheckHandle[0]);
|
|
}
|
|
break;
|
|
case 0:
|
|
{
|
|
byte * FristCode = (byte*)&GetTickCount;
|
|
if (*FristCode == 0xE9)
|
|
{//加速检测
|
|
//发送检测消息给服务端记录.不发送的话直接退出
|
|
GameCheckMananger::Instance()->SetChecked("进程被加速","加速检测");
|
|
}
|
|
if(GameCheckMananger::Instance()->CheckProcessList())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if(GameCheckMananger::Instance()->CheckModuleList())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if(GameCheckMananger::Instance()->CheckWindowList())
|
|
{
|
|
return 0;
|
|
}
|
|
if (GameCheckMananger::Instance()->CheckSysList())
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|