diff --git a/MemoryCheck.vcxproj b/MemoryCheck.vcxproj index 8b461b7..ab5cc45 100644 --- a/MemoryCheck.vcxproj +++ b/MemoryCheck.vcxproj @@ -77,6 +77,7 @@ $(Platform)\$(Configuration)obj\ $(ProjectDir)include\easylog;$(ProjectDir)include\INIH;$(IncludePath) + $(ProjectDir)lib\;$(LibraryPath) @@ -134,7 +135,7 @@ true true true - rpcrt4.lib;%(AdditionalDependencies) + rpcrt4.lib;WtsApi32.Lib;UserEnv.Lib;%(AdditionalDependencies) diff --git a/lib/UserEnv.Lib b/lib/UserEnv.Lib new file mode 100644 index 0000000..b4f8d8f Binary files /dev/null and b/lib/UserEnv.Lib differ diff --git a/lib/WtsApi32.Lib b/lib/WtsApi32.Lib new file mode 100644 index 0000000..51a20a7 Binary files /dev/null and b/lib/WtsApi32.Lib differ diff --git a/lib/userenv.dll b/lib/userenv.dll new file mode 100644 index 0000000..deb5c6d Binary files /dev/null and b/lib/userenv.dll differ diff --git a/lib/wtsapi32.dll b/lib/wtsapi32.dll new file mode 100644 index 0000000..47cace6 Binary files /dev/null and b/lib/wtsapi32.dll differ diff --git a/logs/MemoryCheck.log b/logs/MemoryCheck.log new file mode 100644 index 0000000..d2995d0 --- /dev/null +++ b/logs/MemoryCheck.log @@ -0,0 +1,3 @@ +2025-09-26 10:45:08,181 DEBUG [main.cpp|274] start error(1063)... +2025-09-26 11:04:45,725 DEBUG [main.cpp|274] start error(1063)... +2025-09-26 12:01:41,746 DEBUG [main.cpp|274] start error(1063)... diff --git a/resource/config.ini b/resource/config.ini index ea3b1e3..c3f17d5 100644 --- a/resource/config.ini +++ b/resource/config.ini @@ -1,9 +1,9 @@ -; Test config file for ini_example.c and INIReaderTest.cpp [MemCheck] -UpLimit=80 ; 内存检测上限% -CheckInterval = 4 ; 检测时间间隔s +UpLimit=90 ; 内存检测上限% +CheckInterval = 10 ; 检测时间间隔s +RestartExplorer = true ; 重启explorer [whitelist] ; 白名单 value = HBDSystemE1000Pro -value = HBDSystemE1000Pro +value = notepad++ diff --git a/src/Config.h b/src/Config.h index 21dcfae..c467db8 100644 --- a/src/Config.h +++ b/src/Config.h @@ -10,7 +10,7 @@ using namespace std; class Config { public : - Config():m_MemCheckUpLimit(90), m_CheckInterval(60){} + Config():m_MemCheckUpLimit(90), m_CheckInterval(60), m_RestartExplorer(false){} ~Config() {} void Init() { @@ -26,6 +26,7 @@ public : m_MemCheckUpLimit = reader.GetReal("MemCheck", "UpLimit", 90); m_CheckInterval = reader.GetReal("MemCheck", "CheckInterval", 120); + m_RestartExplorer = reader.GetBoolean("MemCheck", "RestartExplorer", false); LOG(TRACE) << m_MemCheckUpLimit; string whiteList = reader.Get("whitelist", "value", "UNKNOW"); istringstream iss(whiteList); @@ -34,6 +35,7 @@ public : m_Whitelists.emplace_back(line); LOG(TRACE) << "line:" << line; } + } bool InWhitelists(string& processName) { @@ -53,5 +55,6 @@ public : float m_MemCheckUpLimit; //内存检测上限 float m_CheckInterval; //检测时间间隔s + bool m_RestartExplorer; //重启explorer vector m_Whitelists; //白名单 }; \ No newline at end of file diff --git a/src/MemoryCheck.cpp b/src/MemoryCheck.cpp index 3ade2dd..ef8c22f 100644 --- a/src/MemoryCheck.cpp +++ b/src/MemoryCheck.cpp @@ -13,6 +13,8 @@ #include #include "../utils/StringHelper.h" #include "easylogging++.h" +#include +#include /* NTSYSCALLAPI NTSTATUS NTAPI @@ -68,6 +70,8 @@ void MemoryCheck::Start() { if (m_Running) return; m_Running = true; + + if(m_Config->m_RestartExplorer) TestRestartProcess(); MonitorProc(); //m_MonitorThread = std::thread(&MemoryCheck::MonitorProc, this); //SetThreadPriority(m_MonitorThread.native_handle(), THREAD_PRIORITY_BELOW_NORMAL); @@ -327,7 +331,6 @@ void MemoryCheck::CheckAndAlert() { log.m_ProcessName = "notepad++"; } #endif - if (needClose) { LOG(INFO) << u8"尝试关闭" << log.m_ProcessName.c_str(); @@ -374,13 +377,19 @@ void MemoryCheck::CheckAndAlert() { sprintf_s(buffer, sizeof(buffer),u8"关闭%s成功", log.m_ProcessName.c_str()); LOG(DEBUG) << buffer; - if (log.m_ProcessName == "explorer" || log.m_ProcessName == "Explorer" || log.m_ProcessName == "EXPLORER") { - Sleep(2000); - SHELLEXECUTEINFO sei = { sizeof(sei) }; - sei.lpFile = "explorer.exe"; - sei.lpDirectory = "C:\\Windows"; - sei.nShow = SW_SHOWNORMAL; - ShellExecuteEx(&sei); + if (log.m_ProcessName == "explorer" || log.m_ProcessName == "Explorer" || log.m_ProcessName == "EXPLORER" || + log.m_ProcessName == "explorer.exe" || log.m_ProcessName == "Explorer.exe" || log.m_ProcessName == "EXPLORER.exe") { + Sleep(1000); + //SHELLEXECUTEINFO sei = { sizeof(sei) }; + //sei.lpFile = "explorer.exe"; + //sei.lpDirectory = "C:\\Windows"; + //sei.nShow = SW_SHOWNORMAL; + //ShellExecuteEx(&sei); + + if (StartInteractiveProcess()) { + sprintf_s(buffer, sizeof(buffer), u8"启动%s成功", log.m_ProcessName.c_str()); + LOG(DEBUG) << buffer; + } } break; } @@ -599,3 +608,125 @@ BOOLEAN MemoryCheck::PhIsExecutingInWow64(VOID) return FALSE; #endif } + + + +void MemoryCheck::TestRestartProcess() { + string processName = "explorer"; + + LOG(INFO) << u8"尝试关闭" << processName.c_str(); + string pskillPath = StringHelper::GetAppPath() + "pskill.exe"; + char cmd[512]; + sprintf_s(cmd, sizeof(cmd), "%s /accepteula %s", pskillPath.c_str(), processName.c_str()); + HANDLE hReadPipe, hWritePipe; + SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; + if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) { + return; + } + STARTUPINFOA si = { sizeof(si) }; + PROCESS_INFORMATION pi = {}; + + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdOutput = hWritePipe; + si.hStdError = hWritePipe; + si.hStdInput = NULL; + if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) + { + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + return; + } + + CloseHandle(hWritePipe); // 关闭写端,让读操作能结束 + char buffer[4096]; + DWORD bytesRead; + stringstream output; + while (ReadFile(hReadPipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL) && bytesRead > 0) { + buffer[bytesRead] = '\0'; + output << buffer; + } + + CloseHandle(hReadPipe); + WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + string outstr = output.str(); + if (outstr.find("killed") != string::npos) + { + sprintf_s(buffer, sizeof(buffer), u8"关闭%s成功", processName.c_str()); + LOG(DEBUG) << buffer; + + if (processName == "explorer" || processName == "Explorer" || processName == "EXPLORER" || + processName == "explorer.exe" || processName == "Explorer.exe" || processName == "EXPLORER.exe") { + Sleep(1000); + + if (StartInteractiveProcess()) { + sprintf_s(buffer, sizeof(buffer), u8"启动%s成功", processName.c_str()); + LOG(DEBUG) << buffer; + } + } + } + else { + sprintf_s(buffer, sizeof(buffer), u8"关闭%s失败", processName.c_str()); + LOG(WARNING) << buffer; + } + +} + +BOOL MemoryCheck::StartInteractiveProcess() { + DWORD sessionId = WTSGetActiveConsoleSessionId(); + if (sessionId == 0xFFFFFFFF) return FALSE; + + HANDLE hToken; + if (!WTSQueryUserToken(sessionId, &hToken)) return FALSE; + + // 获取用户配置文件目录 + char profilePath[MAX_PATH]; + DWORD profileSize = MAX_PATH; + if (!GetUserProfileDirectory(hToken, profilePath, &profileSize)) { + CloseHandle(hToken); + return FALSE; + } + + // 复制令牌 + HANDLE hDuplicatedToken; + if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, + SecurityIdentification, TokenPrimary, &hDuplicatedToken)) { + CloseHandle(hToken); + return FALSE; + } + + // 创建环境块 + LPVOID envBlock; + if (!CreateEnvironmentBlock(&envBlock, hToken, FALSE)) { + CloseHandle(hDuplicatedToken); + CloseHandle(hToken); + return FALSE; + } + + STARTUPINFO si = { sizeof(si) }; + si.lpDesktop = (char*)"winsta0\\default"; + + PROCESS_INFORMATION pi; + char command[] = "explorer.exe"; + + // 使用用户的主目录作为工作目录 + BOOL success = CreateProcessAsUser(hDuplicatedToken, + NULL, command, + NULL, NULL, FALSE, + CREATE_UNICODE_ENVIRONMENT, + envBlock, + profilePath, // 使用用户目录作为工作目录 + &si, &pi); + + if (success) { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + + if(envBlock) DestroyEnvironmentBlock(envBlock); + if(hDuplicatedToken) CloseHandle(hDuplicatedToken); + if(hToken) CloseHandle(hToken); + return success; +} + diff --git a/src/MemoryCheck.h b/src/MemoryCheck.h index 9b01ed9..8f4cc2b 100644 --- a/src/MemoryCheck.h +++ b/src/MemoryCheck.h @@ -720,6 +720,9 @@ private: void InitializeWindowsInformation(); BOOLEAN PhIsExecutingInWow64(VOID); FORCEINLINE NTSTATUS PhGetProcessIsWow64(_In_ HANDLE ProcessHandle, _Out_ PBOOLEAN IsWow64Process); + + void TestRestartProcess(); + BOOL StartInteractiveProcess(); private: std::atomic m_Running{ false }; //std::thread m_MonitorThread;