#include "SunClientPrecompiledHeader.h" #include "GameCheckMananger.h" #include #pragma comment(lib,"shlwapi.lib") #include #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(vCheckInfo).swap(vCheckInfo); iter++; } } std::vector(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::iterator iter; std::map::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::iterator mIter; std::vector::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::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::iterator iter; iter = m_WindwosList.begin(); while(TRUE) { if(iter==m_WindwosList.end()) break; else { std::map::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; } } }