diff --git a/AntiScreenCap.sln b/AntiScreenCap.sln index bc85b5b..30a9200 100644 --- a/AntiScreenCap.sln +++ b/AntiScreenCap.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31702.278 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36221.1 d17.14 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RtlHide", "RtlHook\RtlHook.vcxproj", "{E91231DC-E9CF-4E12-B0E4-A0C63F7A7E69}" EndProject @@ -10,6 +10,14 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnHide", "UnHide\UnHide.vcxproj", "{3566D20B-6C53-4B3B-BC9C-A252486789D5}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AntiScreenCap", "AntiScreenCap\AntiScreenCap.vcxproj", "{EC0D81D9-E367-4307-925F-2CF1149B5E57}" + ProjectSection(ProjectDependencies) = postProject + {3566D20B-6C53-4B3B-BC9C-A252486789D5} = {3566D20B-6C53-4B3B-BC9C-A252486789D5} + {B5AFEB98-C976-4839-9A8E-4F48B057D7FD} = {B5AFEB98-C976-4839-9A8E-4F48B057D7FD} + {E91231DC-E9CF-4E12-B0E4-A0C63F7A7E69} = {E91231DC-E9CF-4E12-B0E4-A0C63F7A7E69} + {F161A811-6CDA-44DA-8A9E-E463E92A4B80} = {F161A811-6CDA-44DA-8A9E-E463E92A4B80} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConfigManager", "ConfigManager\ConfigManager.vcxproj", "{B5AFEB98-C976-4839-9A8E-4F48B057D7FD}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -51,6 +59,14 @@ Global {EC0D81D9-E367-4307-925F-2CF1149B5E57}.Release|x64.Build.0 = Release|x64 {EC0D81D9-E367-4307-925F-2CF1149B5E57}.Release|x86.ActiveCfg = Release|Win32 {EC0D81D9-E367-4307-925F-2CF1149B5E57}.Release|x86.Build.0 = Release|Win32 + {B5AFEB98-C976-4839-9A8E-4F48B057D7FD}.Debug|x64.ActiveCfg = Debug|x64 + {B5AFEB98-C976-4839-9A8E-4F48B057D7FD}.Debug|x64.Build.0 = Debug|x64 + {B5AFEB98-C976-4839-9A8E-4F48B057D7FD}.Debug|x86.ActiveCfg = Debug|Win32 + {B5AFEB98-C976-4839-9A8E-4F48B057D7FD}.Debug|x86.Build.0 = Debug|Win32 + {B5AFEB98-C976-4839-9A8E-4F48B057D7FD}.Release|x64.ActiveCfg = Release|x64 + {B5AFEB98-C976-4839-9A8E-4F48B057D7FD}.Release|x64.Build.0 = Release|x64 + {B5AFEB98-C976-4839-9A8E-4F48B057D7FD}.Release|x86.ActiveCfg = Release|Win32 + {B5AFEB98-C976-4839-9A8E-4F48B057D7FD}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/AntiScreenCap/AntiScreenCap.vcxproj b/AntiScreenCap/AntiScreenCap.vcxproj index 764d64a..9cb1a30 100644 --- a/AntiScreenCap/AntiScreenCap.vcxproj +++ b/AntiScreenCap/AntiScreenCap.vcxproj @@ -19,10 +19,12 @@ + + @@ -37,26 +39,26 @@ Application true - v142 + v143 Unicode Application false - v142 + v143 true Unicode Application true - v142 + v143 Unicode Application false - v142 + v143 true Unicode @@ -129,7 +131,7 @@ true - Console + Windows true @@ -144,7 +146,7 @@ stdcpp17 - Console + Windows true true true diff --git a/AntiScreenCap/AntiScreenCap.vcxproj.filters b/AntiScreenCap/AntiScreenCap.vcxproj.filters index 2fd2011..5047139 100644 --- a/AntiScreenCap/AntiScreenCap.vcxproj.filters +++ b/AntiScreenCap/AntiScreenCap.vcxproj.filters @@ -21,6 +21,9 @@ 头文件 + + 头文件 + @@ -29,5 +32,8 @@ 源文件 + + 源文件 + \ No newline at end of file diff --git a/AntiScreenCap/config_manager.cpp b/AntiScreenCap/config_manager.cpp new file mode 100644 index 0000000..68af4aa --- /dev/null +++ b/AntiScreenCap/config_manager.cpp @@ -0,0 +1,377 @@ +#include "config_manager.h" +#include +#include +#include +#include +#include +#include + +#pragma comment(lib,"shlwapi.lib") + +namespace ConfigManager { + + // ProcessFilterConfig ʵ + void ProcessFilterConfig::clear() { + processList.clear(); + mode = WHITELIST; + caseSensitive = false; + } + + // Config ʵ + Config::Config() { + m_configFilePath = getDefaultConfigPath(); + } + + Config::Config(const std::string& configPath) : m_configFilePath(configPath) { + } + + std::string Config::toLowerCase(const std::string& str) const { + std::string result = str; + std::transform(result.begin(), result.end(), result.begin(), ::tolower); + return result; + } + + std::string Config::trim(const std::string& str) const { + size_t start = str.find_first_not_of(" \t\r\n"); + if (start == std::string::npos) return ""; + size_t end = str.find_last_not_of(" \t\r\n"); + return str.substr(start, end - start + 1); + } + + bool Config::fileExists(const std::string& filePath) const { + return GetFileAttributesA(filePath.c_str()) != INVALID_FILE_ATTRIBUTES; + } + + void Config::setConfigPath(const std::string& configPath) { + m_configFilePath = configPath; + } + + std::string Config::getConfigPath() const { + return m_configFilePath; + } + + std::string Config::getDefaultConfigPath() const { + char exePath[MAX_PATH] = { 0 }; + GetModuleFileNameA(NULL, exePath, MAX_PATH); + PathRemoveFileSpecA(exePath); + PathAppendA(exePath, "process_filter.ini"); + return std::string(exePath); + } + + bool Config::loadConfig() { + return loadConfig(m_configFilePath); + } + + bool Config::loadConfig(const std::string& configPath) { + m_filterConfig.clear(); + + std::ifstream configFile(configPath); + if (!configFile.is_open()) { + std::cerr << "Warning: ޷ļ: " << configPath << std::endl; + return false; + } + + std::string line; + bool inProcessSection = false; + + std::cout << "Info: ʼȡļ: " << configPath << std::endl; + + while (std::getline(configFile, line)) { + line = trim(line); + + // кע + if (line.empty() || line.front() == '#' || line.front() == ';') { + continue; + } + + // Ƿǽڱ + if (line.front() == '[' && line.back() == ']') { + std::string section = line.substr(1, line.length() - 2); + section = trim(section); + inProcessSection = (toLowerCase(section) == "process"); + continue; + } + + if (!inProcessSection) { + continue; + } + + // + size_t equalPos = line.find('='); + if (equalPos == std::string::npos) { + continue; + } + + std::string key = trim(line.substr(0, equalPos)); + std::string value = trim(line.substr(equalPos + 1)); + + key = toLowerCase(key); + + if (key == "mode") { + value = toLowerCase(value); + if (value == "whitelist" || value == "white") { + m_filterConfig.mode = ProcessFilterConfig::WHITELIST; + std::cout << "Info: Ϊģʽ" << std::endl; + } + else if (value == "blacklist" || value == "black") { + m_filterConfig.mode = ProcessFilterConfig::BLACKLIST; + std::cout << "Info: Ϊģʽ" << std::endl; + } + } + else if (key == "casesensitive") { + value = toLowerCase(value); + m_filterConfig.caseSensitive = (value == "true" || value == "1" || value == "yes"); + std::cout << "Info: Сд: " << (m_filterConfig.caseSensitive ? "" : "ر") << std::endl; + } + else if (key == "list") { + // бֶ֧ŷָ + std::stringstream ss(value); + std::string processName; + while (std::getline(ss, processName, ',')) { + processName = trim(processName); + if (!processName.empty()) { + if (!m_filterConfig.caseSensitive) { + processName = toLowerCase(processName); + } + m_filterConfig.processList.insert(processName); + std::cout << "Info: ӽ: " << processName << std::endl; + } + } + } + } + + configFile.close(); + + std::cout << "Info: ļɣ " << m_filterConfig.processList.size() << " " << std::endl; + return true; + } + + bool Config::saveDefaultConfig() const { + return saveDefaultConfig(m_configFilePath); + } + + bool Config::saveDefaultConfig(const std::string& configPath) const { + std::ofstream configFile(configPath); + if (!configFile.is_open()) { + std::cerr << "Error: ޷ļ: " << configPath << std::endl; + return false; + } + + configFile << "# ̹ļ\n"; + configFile << "# ֵ֧\n"; + configFile << "# mode: whitelist() blacklist()\n"; + configFile << "# casesensitive: true(Сд) false(Сд)\n"; + configFile << "# list: бöŷָ\n\n"; + + configFile << "[Process]\n"; + configFile << "# ģʽ: whitelist(ֻбеĽ) blacklist(бĽ)\n"; + configFile << "mode = whitelist\n\n"; + + configFile << "# ǷСд\n"; + configFile << "casesensitive = false\n\n"; + + configFile << "# б.exe׺öŷָ\n"; + configFile << "list = chrome.exe, msedge.exe, mstsc.exe, notepad.exe, calc.exe\n\n"; + + configFile << "# ʾã\n"; + configFile << "# mode = blacklist\n"; + configFile << "# list = explorer.exe, winlogon.exe, csrss.exe, smss.exe\n"; + + configFile.close(); + + std::cout << "Info: ĬļѴ: " << configPath << std::endl; + return true; + } + + bool Config::reloadConfig() { + // ļڣĬ + if (!fileExists(m_configFilePath)) { + std::cout << "Warning: ļڣĬ" << std::endl; + if (!saveDefaultConfig()) { + return false; + } + } + + return loadConfig(); + } + + const ProcessFilterConfig& Config::getProcessFilterConfig() const { + return m_filterConfig; + } + + ProcessFilterConfig& Config::getProcessFilterConfig() { + return m_filterConfig; + } + + bool Config::shouldProcessBeHooked(const std::string& processName) const { + if (m_filterConfig.processList.empty()) { + // ûãʹĬΪ + return true; + } + + std::string nameToCheck = processName; + if (!m_filterConfig.caseSensitive) { + nameToCheck = toLowerCase(processName); + } + + bool inList = m_filterConfig.processList.find(nameToCheck) != m_filterConfig.processList.end(); + + if (m_filterConfig.mode == ProcessFilterConfig::WHITELIST) { + return inList; // ģʽֻбеĽ + } + else { + return !inList; // ģʽбĽ + } + } + + void Config::setFilterMode(ProcessFilterConfig::FilterMode mode) { + m_filterConfig.mode = mode; + } + + ProcessFilterConfig::FilterMode Config::getFilterMode() const { + return m_filterConfig.mode; + } + + void Config::setCaseSensitive(bool sensitive) { + m_filterConfig.caseSensitive = sensitive; + } + + bool Config::isCaseSensitive() const { + return m_filterConfig.caseSensitive; + } + + void Config::addProcess(const std::string& processName) { + std::string nameToAdd = processName; + if (!m_filterConfig.caseSensitive) { + nameToAdd = toLowerCase(processName); + } + m_filterConfig.processList.insert(nameToAdd); + } + + void Config::removeProcess(const std::string& processName) { + std::string nameToRemove = processName; + if (!m_filterConfig.caseSensitive) { + nameToRemove = toLowerCase(processName); + } + m_filterConfig.processList.erase(nameToRemove); + } + + void Config::clearProcessList() { + m_filterConfig.processList.clear(); + } + + std::vector Config::getProcessList() const { + std::vector result; + result.reserve(m_filterConfig.processList.size()); + for (const auto& process : m_filterConfig.processList) { + result.push_back(process); + } + return result; + } + + size_t Config::getProcessCount() const { + return m_filterConfig.processList.size(); + } + + bool Config::isConfigValid() const { + return !m_configFilePath.empty(); + } + + void Config::printConfig() const { + std::cout << "=== Ϣ ===" << std::endl; + std::cout << "ļ·: " << m_configFilePath << std::endl; + std::cout << "ģʽ: " << (m_filterConfig.mode == ProcessFilterConfig::WHITELIST ? "" : "") << std::endl; + std::cout << "Сд: " << (m_filterConfig.caseSensitive ? "" : "") << std::endl; + std::cout << "б (" << m_filterConfig.processList.size() << "):" << std::endl; + for (const auto& process : m_filterConfig.processList) { + std::cout << " - " << process << std::endl; + } + std::cout << "================" << std::endl; + } + + // GlobalConfig ̬Աʼ + Config* GlobalConfig::s_instance = nullptr; + bool GlobalConfig::s_initialized = false; + + bool GlobalConfig::initialize() { + if (s_initialized) { + return true; + } + + s_instance = new Config(); + s_initialized = s_instance->reloadConfig(); + + if (!s_initialized) { + delete s_instance; + s_instance = nullptr; + } + + return s_initialized; + } + + bool GlobalConfig::initialize(const std::string& configPath) { + if (s_initialized) { + return true; + } + + s_instance = new Config(configPath); + s_initialized = s_instance->reloadConfig(); + + if (!s_initialized) { + delete s_instance; + s_instance = nullptr; + } + + return s_initialized; + } + + void GlobalConfig::cleanup() { + if (s_instance) { + delete s_instance; + s_instance = nullptr; + } + s_initialized = false; + } + + Config* GlobalConfig::getInstance() { + return s_instance; + } + + bool GlobalConfig::isInitialized() { + return s_initialized; + } + + // ݺʵ + bool initializeGlobalConfig() { + return GlobalConfig::initialize(); + } + + bool initializeGlobalConfig(const std::string& configPath) { + return GlobalConfig::initialize(configPath); + } + + Config* getGlobalConfig() { + return GlobalConfig::getInstance(); + } + + void cleanupGlobalConfig() { + GlobalConfig::cleanup(); + } + + bool shouldProcessBeHooked(const std::string& processName) { + Config* config = GlobalConfig::getInstance(); + if (!config) { + return true; // ĬΪ + } + return config->shouldProcessBeHooked(processName); + } + + bool reloadGlobalConfig() { + Config* config = GlobalConfig::getInstance(); + if (!config) { + return false; + } + return config->reloadConfig(); + } + +} // namespace ConfigManager \ No newline at end of file diff --git a/AntiScreenCap/config_manager.h b/AntiScreenCap/config_manager.h new file mode 100644 index 0000000..96718e3 --- /dev/null +++ b/AntiScreenCap/config_manager.h @@ -0,0 +1,106 @@ +#pragma once + +#include +#include +#include + +/** + * ù - ڹ̹˺ѡ + */ +namespace ConfigManager { + + // ̹ýṹ + struct ProcessFilterConfig { + enum FilterMode { + WHITELIST, // ģʽֻбеĽ + BLACKLIST // ģʽбĽ + }; + + FilterMode mode = WHITELIST; + std::unordered_set processList; + bool caseSensitive = false; + + void clear(); + }; + + // ù + class Config { + private: + ProcessFilterConfig m_filterConfig; + std::string m_configFilePath; + + // ߺ + std::string toLowerCase(const std::string& str) const; + std::string trim(const std::string& str) const; + bool fileExists(const std::string& filePath) const; + + public: + Config(); + explicit Config(const std::string& configPath); + ~Config() = default; + + // ļ· + void setConfigPath(const std::string& configPath); + std::string getConfigPath() const; + std::string getDefaultConfigPath() const; + + // üغͱ + bool loadConfig(); + bool loadConfig(const std::string& configPath); + bool saveDefaultConfig() const; + bool saveDefaultConfig(const std::string& configPath) const; + bool reloadConfig(); + + // ̹÷ + const ProcessFilterConfig& getProcessFilterConfig() const; + ProcessFilterConfig& getProcessFilterConfig(); + + // ̹ط + bool shouldProcessBeHooked(const std::string& processName) const; + void setFilterMode(ProcessFilterConfig::FilterMode mode); + ProcessFilterConfig::FilterMode getFilterMode() const; + void setCaseSensitive(bool sensitive); + bool isCaseSensitive() const; + + // б + void addProcess(const std::string& processName); + void removeProcess(const std::string& processName); + void clearProcessList(); + std::vector getProcessList() const; + size_t getProcessCount() const; + + // ֤ + bool isConfigValid() const; + + // Ϣ + void printConfig() const; + }; + + // ȫʵ + class GlobalConfig { + private: + static Config* s_instance; + static bool s_initialized; + + public: + static bool initialize(); + static bool initialize(const std::string& configPath); + static void cleanup(); + static Config* getInstance(); + static bool isInitialized(); + }; + + // ݺ + bool initializeGlobalConfig(); + bool initializeGlobalConfig(const std::string& configPath); + Config* getGlobalConfig(); + void cleanupGlobalConfig(); + + // ֱӲȫõıݺ + bool shouldProcessBeHooked(const std::string& processName); + bool reloadGlobalConfig(); +} + +// Ժ궨 +#define PROCESS_FILTER_WHITELIST ConfigManager::ProcessFilterConfig::WHITELIST +#define PROCESS_FILTER_BLACKLIST ConfigManager::ProcessFilterConfig::BLACKLIST \ No newline at end of file diff --git a/AntiScreenCap/hook_current.cpp b/AntiScreenCap/hook_current.cpp index 43372f3..a4122f7 100644 --- a/AntiScreenCap/hook_current.cpp +++ b/AntiScreenCap/hook_current.cpp @@ -1,6 +1,7 @@ #define _CRT_SECURE_NO_WARNINGS #include "main.h" +#include "config_manager.h" #include "hook_current.h" #include #include @@ -10,12 +11,15 @@ #include #include #include +#include #include #include +#include +#include +#include #pragma comment(lib,"shlwapi.lib") using namespace std; - bool Is64BitOS() { SYSTEM_INFO sysInfo = { 0 }; @@ -52,11 +56,11 @@ unordered_map getSuspendProcess() ); pfnNtQuerySystemInformation NtQuerySystemInformation = (pfnNtQuerySystemInformation)GetProcAddress(LoadLibrary(L"ntdll.dll"), "NtQuerySystemInformation"); - LPVOID dwBufferProcess = 0; //ݵĻ - DWORD dwBufferProcessSize = 0; //ҪյݵĻС + LPVOID dwBufferProcess = 0; + DWORD dwBufferProcessSize = 0; NtQuerySystemInformation(SystemProcessInformation, NULL, 0, &dwBufferProcessSize); - dwBufferProcess = new BYTE[dwBufferProcessSize + 0x10000](); //Ϊ˷ֹ/߳Ϣͻ䣬0x10000ڴ(64K) - LPVOID dwOldBufferProcess = dwBufferProcess; //滺ַ + dwBufferProcess = new BYTE[dwBufferProcessSize + 0x10000](); + LPVOID dwOldBufferProcess = dwBufferProcess; NtQuerySystemInformation(SystemProcessInformation, dwBufferProcess, dwBufferProcessSize + 0x10000, &dwBufferProcessSize); while (TRUE) @@ -68,87 +72,29 @@ unordered_map getSuspendProcess() int suspendThreads = 0; for (DWORD i = 0; i < processInfo->NumberOfThreads; i++) { - //״̬͵´״̬ԭ if (((SYSTEM_THREAD_INFORMATION*)dwBufferProcess)->ThreadState == 5 && ((SYSTEM_THREAD_INFORMATION*)dwBufferProcess)->WaitReason == 5) { suspendThreads++; } - dwBufferProcess = (BYTE*)dwBufferProcess + sizeof(SYSTEM_THREAD_INFORMATION); //ָ˽̵һ߳̽ṹ + dwBufferProcess = (BYTE*)dwBufferProcess + sizeof(SYSTEM_THREAD_INFORMATION); } if (suspendThreads == processInfo->NumberOfThreads) { wstring wstrName{ processInfo->ImageName.Buffer }; suspendProcess[(DWORD)(processInfo->UniqueProcessId)] = string(wstrName.begin(), wstrName.end()); } - dwBufferProcess = ((BYTE*)dwAddress + ((SYSTEM_PROCESS_INFORMATION*)dwAddress)->NextEntryOffset); //ָһ - if (((SYSTEM_PROCESS_INFORMATION*)dwAddress)->NextEntryOffset == 0) //ɽ + dwBufferProcess = ((BYTE*)dwAddress + ((SYSTEM_PROCESS_INFORMATION*)dwAddress)->NextEntryOffset); + if (((SYSTEM_PROCESS_INFORMATION*)dwAddress)->NextEntryOffset == 0) break; } - delete[] dwOldBufferProcess; //ͷڴ + delete[] dwOldBufferProcess; return suspendProcess; } -struct ProcessInfo -{ - string name; - bool isSuspend; -}; - -unordered_map getProcessInfo() -{ - unordered_map processInfoMap; - typedef NTSTATUS(NTAPI* pfnNtQuerySystemInformation)( - IN SYSTEM_INFORMATION_CLASS SystemInformationClass, - OUT PVOID SystemInformation, - IN ULONG SystemInformationLength, - OUT PULONG ReturnLength OPTIONAL - ); - pfnNtQuerySystemInformation NtQuerySystemInformation = (pfnNtQuerySystemInformation)GetProcAddress(LoadLibrary(L"ntdll.dll"), "NtQuerySystemInformation"); - - LPVOID dwBufferProcess = 0; //ݵĻ - DWORD dwBufferProcessSize = 0; //ҪյݵĻС - NtQuerySystemInformation(SystemProcessInformation, NULL, 0, &dwBufferProcessSize); - dwBufferProcess = new BYTE[dwBufferProcessSize + 0x10000](); //Ϊ˷ֹ/߳Ϣͻ䣬0x10000ڴ(64K) - LPVOID dwOldBufferProcess = dwBufferProcess; //滺ַ - NtQuerySystemInformation(SystemProcessInformation, dwBufferProcess, dwBufferProcessSize + 0x10000, &dwBufferProcessSize); - - while (TRUE) - { - LPVOID dwAddress = dwBufferProcess; - dwBufferProcess = (BYTE*)dwBufferProcess + sizeof(SYSTEM_PROCESS_INFORMATION); - PSYSTEM_PROCESS_INFORMATION processInfo = (PSYSTEM_PROCESS_INFORMATION)dwAddress; - - int suspendThreads = 0; - for (DWORD i = 0; i < processInfo->NumberOfThreads; i++) - { - //״̬͵´״̬ԭ - if (((SYSTEM_THREAD_INFORMATION*)dwBufferProcess)->ThreadState == 5 && ((SYSTEM_THREAD_INFORMATION*)dwBufferProcess)->WaitReason == 5) - { - suspendThreads++; - } - dwBufferProcess = (BYTE*)dwBufferProcess + sizeof(SYSTEM_THREAD_INFORMATION); //ָ˽̵һ߳̽ṹ - } - - if ((DWORD)(processInfo->UniqueProcessId) > 0) - { - wstring wstrName = processInfo->ImageName.Buffer; - bool isSuspend = (suspendThreads == processInfo->NumberOfThreads); - processInfoMap[(DWORD)(processInfo->UniqueProcessId)] = { string(wstrName.begin(), wstrName.end()), isSuspend }; - } - - dwBufferProcess = ((BYTE*)dwAddress + ((SYSTEM_PROCESS_INFORMATION*)dwAddress)->NextEntryOffset); //ָһ - if (((SYSTEM_PROCESS_INFORMATION*)dwAddress)->NextEntryOffset == 0) //ɽ - break; - } - delete[] dwOldBufferProcess; //ͷڴ - return processInfoMap; -} - bool ZwCreateThreadExInjectDll(HANDLE hProcess, const wchar_t* pszDllFileName) { int pathSize = (wcslen(pszDllFileName) + 1) * sizeof(wchar_t); - // 2.Ŀռ LPVOID lpPathAddr = VirtualAllocEx(hProcess, 0, pathSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (NULL == lpPathAddr) { @@ -156,14 +102,14 @@ bool ZwCreateThreadExInjectDll(HANDLE hProcess, const wchar_t* pszDllFileName) CloseHandle(hProcess); return false; } - // 3.ĿдDll· - if (FALSE == WriteProcessMemory(hProcess, lpPathAddr, pszDllFileName, pathSize, NULL)) // ʵдС + + if (FALSE == WriteProcessMemory(hProcess, lpPathAddr, pszDllFileName, pathSize, NULL)) { Log(LogLevel::LOG_ERROR, __LINE__, "ĿдDll·ʧܣ%d", GetLastError()); CloseHandle(hProcess); return false; } - // 4.ntdll.dll + HMODULE hNtdll = LoadLibraryW(L"ntdll.dll"); if (NULL == hNtdll) { @@ -171,8 +117,7 @@ bool ZwCreateThreadExInjectDll(HANDLE hProcess, const wchar_t* pszDllFileName) CloseHandle(hProcess); return false; } - // 5.ȡLoadLibraryAĺַ - // FARPROCӦ32λ64λ + HMODULE hmKernel32 = LoadLibrary(_T("Kernel32.dll")); if (NULL == hmKernel32) { @@ -187,8 +132,7 @@ bool ZwCreateThreadExInjectDll(HANDLE hProcess, const wchar_t* pszDllFileName) CloseHandle(hProcess); return false; } - // 6.ȡZwCreateThreadExַ,ú32λ64λԭͲͬ - // _WIN64жϱ뻷_WIN32жǷWindowsϵͳ + #ifdef _WIN64 typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)( PHANDLE ThreadHandle, @@ -225,7 +169,7 @@ bool ZwCreateThreadExInjectDll(HANDLE hProcess, const wchar_t* pszDllFileName) CloseHandle(hProcess); return false; } - // 7.ĿдԶ߳ + HANDLE hRemoteThread = NULL; DWORD dwStatus = ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, hProcess, (LPTHREAD_START_ROUTINE)pFuncProcAddr, lpPathAddr, 0, 0, 0, 0, NULL); @@ -235,99 +179,49 @@ bool ZwCreateThreadExInjectDll(HANDLE hProcess, const wchar_t* pszDllFileName) CloseHandle(hProcess); return false; } - // 8.ȴ߳̽ + DWORD reason = WaitForSingleObject(hRemoteThread, INFINITE); - /*if (reason == WAIT_TIMEOUT) - { - if (string name = getProcNameByHandle(hProcess); !name.empty()) - Log(LogLevel::LOG_WARN, __LINE__, "WaitForRemoteThreadExit TIMEOUT(2s), Process May Be Suspend: %s", name.c_str()); - else - Log(LogLevel::LOG_WARN, __LINE__, "WaitForRemoteThreadExit TIMEOUT(2s), Process May Be Suspend: %d", GetProcessId(hProcess)); - }*/ - // 9. - VirtualFreeEx(hProcess, lpPathAddr, 0, MEM_RELEASE); //MEM_RELEASE + + VirtualFreeEx(hProcess, lpPathAddr, 0, MEM_RELEASE); CloseHandle(hRemoteThread); CloseHandle(hProcess); FreeLibrary(hNtdll); return true; } -//bool HookCurWindow(const std::wstring& dllPath) -//{ -// Log(LogLevel::LOG_INFO, __LINE__, ">>>>>>>>>>>>>>>>HOOK CURRENT WINDOWS<<<<<<<<<<<<<<<<"); -// std::wstring DllPath{ getFullFilePath(dllPath) }; -// COND_LOG_RET(!DllPath.empty(), __LINE__, "DllPath.empty(): %d", GetLastError(), false); -// -// unordered_map processInfoMap = getProcessInfo(); -// for (auto i : processInfoMap) -// { -// Log(LogLevel::LOG_INFO, __LINE__, "Ready To Inject: %s", i.second.name.c_str()); -// if (i.second.isSuspend) -// { -// Log(LogLevel::LOG_WARN, __LINE__, "This is a suspend process: %s", i.second.name.c_str()); -// continue; -// } -// // 1.Ŀ, ø߼OpenProcess API, CSRSS -// HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, i.first); -// if (hProcess) { -// BOOL procIs32bit; -// /*64-bit process on 64-bit Windows : FALSE -// 32-bit process on 64-bit Windows : TRUE -// 32-bit process on 32-bit Windows : FALSE*/ -// if (IsWow64Process(hProcess, &procIs32bit)) { -//#ifdef _WIN64 -// if (!procIs32bit && is64BitOS) { -// if (ZwCreateThreadExInjectDll(hProcess, DllPath.c_str())) { -// Log(LogLevel::LOG_INFO, __LINE__, "Hook Window Success: %s", i.second.name.c_str()); -// } -// else { -// Log(LogLevel::LOG_WARN, __LINE__, "Hook Window Failed: %s", i.second.name.c_str()); -// } -// } -// else { -// Log(LogLevel::LOG_WARN, __LINE__, "It's a 32 app: %s", i.second.name.c_str()); -// } -//#else -// if (procIs32bit || (!procIs32bit && !is64BitOS)) { -// if (ZwCreateThreadExInjectDll(hProcess, DllPath.c_str())) { -// Log(LogLevel::LOG_INFO, __LINE__, "Hook Window Success: %s", i.second.name.c_str()); -// } -// else { -// Log(LogLevel::LOG_WARN, __LINE__, "Hook Window Failed: %s", i.second.name.c_str()); -// } -// } -// else { -// Log(LogLevel::LOG_WARN, __LINE__, "It's a 64 app: %s", i.second.name.c_str()); -// } -//#endif -// } -// else { -// Log(LogLevel::LOG_ERROR, __LINE__, "жĿǷ64λϵͳе32λʧ: %d", GetLastError()); -// continue; -// } -// } -// else { -// Log(LogLevel::LOG_WARN, __LINE__, "Ŀ: %s, ʧ: %d", i.second.name.c_str(), GetLastError()); -// continue; -// } -// } -// Log(LogLevel::LOG_INFO, __LINE__, ">>>>>>>>>>>>>>>>HOOK CURRENT WINDOW END<<<<<<<<<<<<<<<<<<"); -// return true; -//} - bool HookCurWindow(const std::wstring& dllPath) { Log(LogLevel::LOG_INFO, __LINE__, ">>>>>>>>>>>>>>>>HOOK CURRENT WINDOWS<<<<<<<<<<<<<<<<"); - std::wstring DllPath{ getFullFilePath(dllPath) }; - COND_LOG_RET(!DllPath.empty(), __LINE__, "DllPath.empty(): %d", GetLastError(), false); + + + // ¼ļ + if (!ConfigManager::reloadGlobalConfig()) { + Log(LogLevel::LOG_WARN, __LINE__, "ļʧܣʹĬ"); + } + + // ӡǰϢã + ConfigManager::Config* config = ConfigManager::getGlobalConfig(); + if (config) { + config->printConfig(); + } + + std::wstring DllPath{ getFullFilePath(dllPath) }; + if (DllPath.empty()) { + Log(LogLevel::LOG_ERROR, __LINE__, "DLL·ȡʧ: %d", GetLastError()); + return false; + } + unordered_map suspendProc = getSuspendProcess(); for (auto i : suspendProc) { Log(LogLevel::LOG_INFO, __LINE__, "suspend process: %s", i.second.c_str()); } - unordered_map tryHookedProc;//עPID - vector goodHookedProc;//ɹhookĽ + + unordered_map tryHookedProc; + vector goodHookedProc; + vector filteredProc; // ˵Ľ + HWND windowHandle = NULL; do { windowHandle = FindWindowEx(NULL, windowHandle, NULL, NULL); @@ -335,23 +229,30 @@ bool HookCurWindow(const std::wstring& dllPath) if (GetWindowThreadProcessId(windowHandle, &dwPid)) { if (tryHookedProc.find(dwPid) == tryHookedProc.end()) { tryHookedProc[dwPid] = 1; - + if (suspendProc.find(dwPid) != suspendProc.end()) { Log(LogLevel::LOG_WARN, __LINE__, "This is a suspend process: %s", suspendProc[dwPid].c_str()); continue; } - // 0.Ȩ - // 1.Ŀ, ø߼OpenProcess API + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); if (hProcess) { string exeName = getProcNameByHandle(hProcess); - exeName = (!exeName.empty() ? exeName : "Unknow ProcName"); - + exeName = (!exeName.empty() ? exeName : "Unknown ProcName"); + + // ʹµĹ߼ + if (!ConfigManager::shouldProcessBeHooked(exeName)) { + ConfigManager::Config* cfg = ConfigManager::getGlobalConfig(); + Log(LogLevel::LOG_INFO, __LINE__, "̱: %s (ģʽ: %s)", + exeName.c_str(), + cfg && cfg->getFilterMode() == ConfigManager::ProcessFilterConfig::WHITELIST ? "" : ""); + filteredProc.push_back(exeName); + CloseHandle(hProcess); + continue; + } + BOOL procIs32bit; - /*64-bit process on 64-bit Windows : FALSE - 32-bit process on 64-bit Windows : TRUE - 32-bit process on 32-bit Windows : FALSE*/ if (IsWow64Process(hProcess, &procIs32bit)) { #ifdef _WIN64 if (!procIs32bit && is64BitOS) { @@ -379,7 +280,6 @@ bool HookCurWindow(const std::wstring& dllPath) Log(LogLevel::LOG_WARN, __LINE__, "It's a 64 app: %s", exeName.c_str()); } #endif - } else { Log(LogLevel::LOG_ERROR, __LINE__, "жĿǷ64λϵͳе32λʧ: %d", GetLastError()); @@ -391,21 +291,24 @@ bool HookCurWindow(const std::wstring& dllPath) continue; } } - else { - //cout << "ע" << endl; - continue; - } } else { Log(LogLevel::LOG_WARN, __LINE__, "GetWindowThreadProcessId Error%d, HWND: %x", GetLastError(), windowHandle); } } while (windowHandle); + //Summary Log(LogLevel::LOG_INFO, __LINE__, ">>>>>>>>>>>>>>>>HOOK CURRENT WINDOW END<<<<<<<<<<<<<<<<<<"); Log(LogLevel::LOG_INFO, __LINE__, "Summary:"); + Log(LogLevel::LOG_INFO, __LINE__, "ɹHookĽ (%zu):", goodHookedProc.size()); for (auto& i : goodHookedProc) { - Log(LogLevel::LOG_INFO, __LINE__, i.c_str()); + Log(LogLevel::LOG_INFO, __LINE__, " - %s", i.c_str()); } + + if (!filteredProc.empty()) { + Log(LogLevel::LOG_INFO, __LINE__, "˵Ľ (%zu):", filteredProc.size()); + } + return true; } \ No newline at end of file diff --git a/AntiScreenCap/main.cpp b/AntiScreenCap/main.cpp index 637751e..5bcf941 100644 --- a/AntiScreenCap/main.cpp +++ b/AntiScreenCap/main.cpp @@ -4,12 +4,40 @@ #include "main.h" #include #include -#include #include #include +#include +#include "config_manager.h" #pragma comment(lib,"shlwapi.lib") +#pragma comment(lib,"comctl32.lib") using namespace std; +// 窗口类名和标题 +const wchar_t g_szClassName[] = L"WindowControlApp"; +const wchar_t g_szTitle[] = L"窗口控制程序"; + +// 控件ID定义 +#define IDC_BUTTON_HIDE 1001 +#define IDC_BUTTON_SHOW 1002 +#define IDC_BUTTON_HOOK_RTL 1003 +#define IDC_BUTTON_UNHOOK_RTL 1004 +#define IDC_BUTTON_DEBUG 1005 +#define IDC_BUTTON_STOP 1006 +#define IDC_LISTBOX_LOG 1007 +#define IDC_BUTTON_CLEAR_LOG 1008 +#define IDC_STATIC_STATUS 1009 +// 控制程序自身可见性按钮 +#define IDC_BUTTON_VISBLE_SELF 1010 +#define HOTKEY_ID 1011 + +// 全局变量 +HWND g_hMainWnd = NULL; +HWND g_hLogListBox = NULL; +HWND g_hStatusText = NULL; +HINSTANCE g_hInst = NULL; +bool g_bRtlHookEnabled = false; +bool g_bIPCInitialized = false; + typedef BOOL(WINAPI* pfnSetHook) (BOOL); pfnSetHook SetHook = NULL; @@ -19,14 +47,11 @@ const int LOG_SIZE = 512; //for ipc char* pBuf; HANDLE hServerEvent, hClientEvent, hFileMap; -//for save console origin color -WORD wOldColorAttrs; - #ifdef _WIN64 const std::wstring hideDllName{ L"Hide.dll" }; const std::wstring unhideDllName{ L"Unhide.dll" }; -const std::wstring RtlHideDllName{L"RtlHide.dll"}; +const std::wstring RtlHideDllName{ L"RtlHide.dll" }; #else const std::wstring hideDllName{ L"Hide32.dll" }; const std::wstring unhideDllName{ L"Unhide32.dll" }; @@ -34,8 +59,8 @@ const std::wstring RtlHideDllName{ L"RtlHide32.dll" }; #endif //添加MessageBoxTimeout支持 -typedef int (WINAPI *MessageBoxTimeoutA)(IN HWND hWnd, IN LPCSTR lpText, IN LPCSTR lpCaption, IN UINT uType, IN WORD wLanguageId, IN DWORD dwMilliseconds); -typedef int (WINAPI *MessageBoxTimeoutW)(IN HWND hWnd, IN LPCWSTR lpText, IN LPCWSTR lpCaption, IN UINT uType, IN WORD wLanguageId, IN DWORD dwMilliseconds); +typedef int (WINAPI* MessageBoxTimeoutA)(IN HWND hWnd, IN LPCSTR lpText, IN LPCSTR lpCaption, IN UINT uType, IN WORD wLanguageId, IN DWORD dwMilliseconds); +typedef int (WINAPI* MessageBoxTimeoutW)(IN HWND hWnd, IN LPCWSTR lpText, IN LPCWSTR lpCaption, IN UINT uType, IN WORD wLanguageId, IN DWORD dwMilliseconds); HMODULE hUser32 = LoadLibraryA("user32.dll"); #ifdef UNICODE @@ -44,395 +69,451 @@ HMODULE hUser32 = LoadLibraryA("user32.dll"); #define MessageBoxTimeout ((MessageBoxTimeoutA)(GetProcAddress(hUser32, "MessageBoxTimeoutA"))) #endif -BOOL WINAPI ConsoleHandler(DWORD CEvent) -{ - switch (CEvent) - { - case CTRL_CLOSE_EVENT://close消息有限时机制 - HookRtlWindow(false); - MessageBoxTimeout(NULL, L"关闭实时窗口注入", L"step 1", MB_OK, 0, 1000);//MessageBox(NULL, L"关闭实时窗口注入", L"step 1", MB_OK); - Sleep(1500); - HookCurWindow(unhideDllName); - MessageBox(NULL, L"还原当前所有窗口", L"step 2", MB_OK);//MessageBoxTimeout(NULL, L"还原当前所有窗口", L"step 2", MB_OK, 0, 1500); - break; - case CTRL_C_EVENT: - ShowWindow(GetConsoleWindow(), SW_HIDE); - break; - case CTRL_BREAK_EVENT: - case CTRL_LOGOFF_EVENT: - case CTRL_SHUTDOWN_EVENT: - default: - return FALSE; - } - return TRUE; +bool g_bSelfHidden = false; +bool g_bHotkeyRegistered = false; // 新增:跟踪快捷键注册状态 + + +// 日志函数 +void Log(LogLevel level, int line, const char* format, ...) { + if (!g_hLogListBox) return; + + char msg[LOG_SIZE] = { 0 }; + char finalMsg[LOG_SIZE + 50] = { 0 }; + + va_list ap; + va_start(ap, format); + vsprintf(msg, format, ap); + va_end(ap); + + const char* levelStr = ""; + switch (level) { + case LogLevel::LOG_INFO: + levelStr = "[INFO] "; + break; + case LogLevel::LOG_WARN: + levelStr = "[WARN] "; + sprintf(finalMsg, "%s[Line %d] %s", levelStr, line, msg); + break; + case LogLevel::LOG_ERROR: + levelStr = "[ERROR] "; + sprintf(finalMsg, "%s[Line %d] %s", levelStr, line, msg); + break; + } + + if (level == LogLevel::LOG_INFO) { + strcpy(finalMsg, msg); + } + + // 转换为宽字符并添加到列表框 + wchar_t wMsg[LOG_SIZE + 50]; + MultiByteToWideChar(CP_ACP, 0, finalMsg, -1, wMsg, LOG_SIZE + 50); + + int index = SendMessage(g_hLogListBox, LB_ADDSTRING, 0, (LPARAM)wMsg); + SendMessage(g_hLogListBox, LB_SETCURSEL, index, 0); } -bool SetPrivilege() -{ - HANDLE hToken; - TOKEN_PRIVILEGES NewState; - LUID luidPrivilegeLUID; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken) || !LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidPrivilegeLUID)) - { - Log(LogLevel::LOG_WARN, __LINE__, "SetPrivilege Error: %d", GetLastError()); - return false; - } - NewState.PrivilegeCount = 1; - NewState.Privileges[0].Luid = luidPrivilegeLUID; - NewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - if (!AdjustTokenPrivileges(hToken, FALSE, &NewState, NULL, NULL, NULL)) - { - Log(LogLevel::LOG_WARN, __LINE__, "AdjustTokenPrivilege Error: %d", GetLastError()); - return false; - } - return true; +// 更新状态文本 +void UpdateStatus(const wchar_t* status) { + if (g_hStatusText) { + SetWindowText(g_hStatusText, status); + } } -bool initFoundSet() -{ - SetPrivilege(); - - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - HANDLE hStd = GetStdHandle(STD_OUTPUT_HANDLE); - HANDLE_LOG_RET(hStd, __LINE__, "GetStdHandle: %x", hStd, false); - COND_LOG_RET(GetConsoleScreenBufferInfo(hStd, &csbiInfo), __LINE__, "GetConsoleScreenBufferInfo: %x", csbiInfo.wAttributes, false); - wOldColorAttrs = csbiInfo.wAttributes; - - COND_LOG_RET(SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler, TRUE), __LINE__, "SetConsoleCtrlHandler: %x", ConsoleHandler, false); - return true; +bool SetPrivilege() { + HANDLE hToken; + TOKEN_PRIVILEGES NewState; + LUID luidPrivilegeLUID; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken) || + !LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidPrivilegeLUID)) { + Log(LogLevel::LOG_WARN, __LINE__, "SetPrivilege Error: %d", GetLastError()); + return false; + } + NewState.PrivilegeCount = 1; + NewState.Privileges[0].Luid = luidPrivilegeLUID; + NewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + if (!AdjustTokenPrivileges(hToken, FALSE, &NewState, NULL, NULL, NULL)) { + Log(LogLevel::LOG_WARN, __LINE__, "AdjustTokenPrivilege Error: %d", GetLastError()); + return false; + } + return true; } -void SetConsoleColor(WORD wAttributes) -{ - HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); //获取缓冲区句柄 - if (wAttributes == 0) - SetConsoleTextAttribute(hCon, wOldColorAttrs); - else - SetConsoleTextAttribute(hCon, wAttributes); -} - -void Log(LogLevel level, int line, const char* format, ...) -{ - char msg[LOG_SIZE] = {0}; - - va_list ap; - int ret = -1; - va_start(ap, format); - ret = vsprintf(msg, format, ap); - va_end(ap); - - switch (level) - { - case LogLevel::LOG_INFO: - cout << msg << endl; - break; - case LogLevel::LOG_WARN: - SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); - cout << "[Line " << line << "] " << msg << endl; - SetConsoleColor(0); - break; - case LogLevel::LOG_ERROR: - SetConsoleColor(FOREGROUND_RED | FOREGROUND_INTENSITY); - cout << "[Line " << line << "] " << msg << endl; - SetConsoleColor(0); - break; - - default: - SetConsoleColor(FOREGROUND_BLUE | FOREGROUND_INTENSITY); - cout << "No this LOG_LEVEL" << endl; - SetConsoleColor(0); - break; - } -} - -//bool Exec(const wstring& fullPath, const wstring& param, DWORD dwMilliseconds) -//{ -// SHELLEXECUTEINFO ShExecInfo = { 0 }; -// { -// ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI | SEE_MASK_NO_CONSOLE; -// ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); //结构大小 -// ShExecInfo.lpVerb = _T("runas"); //指定该函数的执行动作,以管理员方式运行 -// ShExecInfo.nShow = SW_HIDE; //隐藏窗口 -// ShExecInfo.lpFile = fullPath.c_str(); //卸载程序路径 -// ShExecInfo.lpParameters = param.c_str(); //卸载程序参数 -// } -// if (ShellExecuteEx(&ShExecInfo)) -// { -// if (ShExecInfo.hProcess) -// { -// switch (WaitForSingleObject(ShExecInfo.hProcess, dwMilliseconds)) -// { -// case WAIT_OBJECT_0: //The state of the specified object is signaled. -// LogW(LogLevel::LOG_INFO, __LINE__, L"执行程序%s成功", fullPath); -// return true; -// case WAIT_TIMEOUT: //The time-out interval elapsed, and the object's state is nonsignaled. -// LogW(LogLevel::LOG_ERROR, __LINE__, L"执行程序%s超时", fullPath); -// break; -// case WAIT_FAILED: //Waiting on an invalid handle causes WaitForSingleObject to return WAIT_FAILED. -// LogW(LogLevel::LOG_ERROR, __LINE__, L"执行程序%s错误: %d", fullPath, GetLastError()); -// break; -// } -// } -// else -// { -// LogW(LogLevel::LOG_ERROR, __LINE__, L"执行程序%s句柄异常: %d", fullPath, GetLastError()); -// } -// } -// else -// { -// LogW(LogLevel::LOG_ERROR, __LINE__, L"执行程序%s失败: %d", fullPath, GetLastError()); -// } -// return false; -//} - -bool FileExists(std::wstring& filePath) -{ - DWORD dwAttrib = GetFileAttributes(filePath.c_str()); - return (dwAttrib != INVALID_FILE_ATTRIBUTES && - !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); +bool FileExists(std::wstring& filePath) { + DWORD dwAttrib = GetFileAttributes(filePath.c_str()); + return (dwAttrib != INVALID_FILE_ATTRIBUTES && + !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); } std::wstring getFullFilePath(const std::wstring& filename) { - wchar_t fullPath[MAX_PATH] = {0}; - GetModuleFileName(NULL, fullPath, MAX_PATH); - PathRemoveFileSpec(fullPath); - PathAppend(fullPath, filename.c_str()); - std::wstring strFullPath{ fullPath }; - COND_LOG_RET(FileExists(strFullPath), __LINE__, "FileExists: %S", strFullPath.c_str(), std::wstring{}); - return strFullPath; -}; + wchar_t fullPath[MAX_PATH] = { 0 }; + GetModuleFileName(NULL, fullPath, MAX_PATH); + PathRemoveFileSpec(fullPath); + PathAppend(fullPath, filename.c_str()); + std::wstring strFullPath{ fullPath }; + if (!FileExists(strFullPath)) { + Log(LogLevel::LOG_ERROR, __LINE__, "FileExists: %S", strFullPath.c_str()); + return std::wstring{}; + } + return strFullPath; +} + +bool HookRtlWindow(bool hook) { + HMODULE RtlHideDll = LoadLibrary(RtlHideDllName.c_str()); + if (!RtlHideDll) { + Log(LogLevel::LOG_ERROR, __LINE__, "LoadLibrary %S Error: %d", RtlHideDllName.c_str(), GetLastError()); + return false; + } -bool HookRtlWindow(bool hook) -{ - if (HMODULE RtlHideDll = LoadLibrary(RtlHideDllName.c_str()); RtlHideDll) - { #ifdef _WIN64 - SetHook = (pfnSetHook)GetProcAddress(RtlHideDll, "SetHook"); + SetHook = (pfnSetHook)GetProcAddress(RtlHideDll, "SetHook"); #else - SetHook = (pfnSetHook)GetProcAddress(RtlHideDll, "_SetHook@4"); + SetHook = (pfnSetHook)GetProcAddress(RtlHideDll, "_SetHook@4"); #endif - if (SetHook) - { - if (hook) - { - if (SetHook(TRUE)) - { - Log(LogLevel::LOG_INFO, __LINE__, "Set Hook Success"); - return true; - } - else - { - Log(LogLevel::LOG_ERROR, __LINE__, "Set Hook Error. See More in DebugView"); - } - } - else - { - if (SetHook(FALSE)) - { - Log(LogLevel::LOG_INFO, __LINE__, "Set Unhook Success"); - return true; - } - else - { - Log(LogLevel::LOG_ERROR, __LINE__, "Set Unhook Error. See More in DebugView"); - } - } - - } - else - { - Log(LogLevel::LOG_ERROR, __LINE__, "GetProcAddress SetHook Error: %d", GetLastError()); - } - } - else - { - Log(LogLevel::LOG_ERROR, __LINE__, "LoadLibrary %S Error: %d", RtlHideDllName.c_str(), GetLastError()); - } - return false; + + if (!SetHook) { + Log(LogLevel::LOG_ERROR, __LINE__, "GetProcAddress SetHook Error: %d", GetLastError()); + return false; + } + + if (hook) { + if (SetHook(TRUE)) { + Log(LogLevel::LOG_INFO, __LINE__, "Set Hook Success"); + g_bRtlHookEnabled = true; + UpdateStatus(L"状态: 实时钩子已启用"); + return true; + } + else { + Log(LogLevel::LOG_ERROR, __LINE__, "Set Hook Error. See More in DebugView"); + } + } + else { + if (SetHook(FALSE)) { + Log(LogLevel::LOG_INFO, __LINE__, "Set Unhook Success"); + g_bRtlHookEnabled = false; + UpdateStatus(L"状态: 实时钩子已禁用"); + return true; + } + else { + Log(LogLevel::LOG_ERROR, __LINE__, "Set Unhook Error. See More in DebugView"); + } + } + return false; +} +// 修改HideSelf函数:只有快捷键注册成功时才允许隐藏 +void HideSelf() { + if (!g_bHotkeyRegistered) { + Log(LogLevel::LOG_ERROR, __LINE__, "无法隐藏:全局快捷键未注册"); + return; + } + + if (g_hMainWnd) { + ShowWindow(g_hMainWnd, SW_HIDE); + g_bSelfHidden = true; + UpdateStatus(L"状态: 程序已隐藏"); + Log(LogLevel::LOG_INFO, __LINE__, "程序窗口已隐藏"); + } } -struct HandleName -{ - HANDLE handle; - string name; -}; -struct ShareMemory { - HANDLE hFileMap; - char* pShareBuf; - void clear() { - if (pShareBuf) UnmapViewOfFile(pShareBuf); - CloseHandle(hFileMap); - } -}; -struct IPC { - IPC(string fullName, int bufSize = 32, DWORD ms = 5000) : - sFullExeName(fullName), iBufSize(bufSize), dwMilliseconds(ms) {} - void clear() { - fileMap.clear(); - CloseHandle(serverEvent.handle); - CloseHandle(clientEvent.handle); - } - const string sFullExeName; - HandleName serverEvent, clientEvent; - //HandleName fileMap; - ShareMemory fileMap; - DWORD dwMilliseconds; - const int iBufSize; - string sCmd; -}; - -bool __SetEvent(HANDLE hEvent) -{ - return SetEvent(hEvent); -} -bool __SetEvent(const string& eventName) -{ - HANDLE hEvent = OpenEventA(SYNCHRONIZE, FALSE, eventName.c_str()); - return hEvent && __SetEvent(hEvent); -} -bool __GetEvent(HANDLE hEvent, DWORD dwMilliseconds) -{ - switch (WaitForSingleObject(hEvent, dwMilliseconds)) //同步等待事件受信 - { - case WAIT_OBJECT_0: //The state of the specified object is signaled. - Log(LogLevel::LOG_INFO, __LINE__, "等待事件受信成功(lim:%dms): %x", dwMilliseconds, hEvent); - return true; - case WAIT_TIMEOUT: //The time-out interval elapsed, and the object's state is nonsignaled. - Log(LogLevel::LOG_INFO, __LINE__, "等待事件受信超时(lim:%dms): %x", dwMilliseconds, hEvent); - return false; - case WAIT_FAILED: //Waiting on an invalid handle causes WaitForSingleObject to return WAIT_FAILED. - Log(LogLevel::LOG_INFO, __LINE__, "等待事件受信失败: %d", GetLastError()); - return false; - default: - break; - } - return false; -} -bool __GetEvent(const string& eventName, DWORD dwMilliseconds) -{ - HANDLE hEvent = OpenEventA(SYNCHRONIZE, FALSE, eventName.c_str()); - return hEvent && __GetEvent(hEvent, dwMilliseconds); +HANDLE CreateGlobalEvent(string& eventName) { + SECURITY_ATTRIBUTES sa; + sa.bInheritHandle = FALSE; + sa.lpSecurityDescriptor = NULL; + sa.nLength = sizeof(sa); + if (eventName.find("Global\\") == eventName.npos) { + eventName = "Global\\" + eventName; + } + return CreateEventA(&sa, FALSE, FALSE, eventName.c_str()); } -HANDLE CreateGlobalEvent(string& eventName) -{ - SECURITY_ATTRIBUTES sa; - sa.bInheritHandle = FALSE; - sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof(sa); - if (eventName.find("Global\\") == eventName.npos) - { - eventName = "Global\\" + eventName; - } - return CreateEventA(&sa, FALSE, FALSE, eventName.c_str()); +HANDLE CreateGlobalFileMap(string& fileMapName) { + if (fileMapName.find("Global\\") == fileMapName.npos) { + fileMapName = "Global\\" + fileMapName; + } + return CreateFileMappingA( + INVALID_HANDLE_VALUE, + NULL, + PAGE_READWRITE, + 0, + FILEMAP_BUF, + fileMapName.c_str() + ); } -HANDLE CreateGlobalFileMap(string& fileMapName) -{ - if (fileMapName.find("Global\\") == fileMapName.npos) - { - fileMapName = "Global\\" + fileMapName; - } - return CreateFileMappingA( - INVALID_HANDLE_VALUE, //物理文件句柄,设为INVALID_HANDLE_VALUE(无效句柄)以创建一个进程间共享的对象 - NULL, //默认安全级别 - PAGE_READWRITE, //权限可读可写 - 0, //高位文件大小 - FILEMAP_BUF, //低位文件大小 - fileMapName.c_str() //共享内存名 - ); +bool initIPCEnvironment() { + string baseName = to_string(GetCurrentProcessId()); + string serverEventName = baseName + "-ServerEvent"; + string clientEventName = baseName + "-ClientEvent"; + string fileMapName = baseName + "-FileMap"; + + hServerEvent = CreateGlobalEvent(serverEventName); + if (!hServerEvent) { + Log(LogLevel::LOG_ERROR, __LINE__, "CreateGlobalEvent: %s failed", serverEventName.c_str()); + return false; + } + + hClientEvent = CreateGlobalEvent(clientEventName); + if (!hClientEvent) { + Log(LogLevel::LOG_ERROR, __LINE__, "CreateGlobalEvent: %s failed", clientEventName.c_str()); + return false; + } + + hFileMap = CreateGlobalFileMap(fileMapName); + if (!hFileMap) { + Log(LogLevel::LOG_ERROR, __LINE__, "CreateGlobalFileMap: %s failed", fileMapName.c_str()); + return false; + } + + pBuf = (char*)MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, FILEMAP_BUF); + if (!pBuf) { + Log(LogLevel::LOG_ERROR, __LINE__, "MapViewOfFile failed"); + return false; + } + + g_bIPCInitialized = true; + Log(LogLevel::LOG_INFO, __LINE__, "IPC环境初始化成功"); + return true; } -bool initIPCEnvironment() -{ - string baseName = to_string(GetCurrentProcessId()); - string serverEventName = baseName + "-ServerEvent"; - string clientEventName = baseName + "-ClientEvent"; - string fileMapName = baseName + "-FileMap"; - //服务端信号 - hServerEvent = CreateGlobalEvent(serverEventName); - COND_LOG_RET(hServerEvent, __LINE__, "CreateGlobalEvent: %s", serverEventName.c_str(), 1); - //客户端信号 - hClientEvent = CreateGlobalEvent(clientEventName); - COND_LOG_RET(hClientEvent, __LINE__, "CreateGlobalEvent: %s", clientEventName.c_str(), 1); - - //1.创建共享文件句柄 hMapFile,CreateFileMapping()函数创建一个文件映射内核对象 - hFileMap = CreateGlobalFileMap(fileMapName); - COND_LOG_RET(hFileMap, __LINE__, "CreateGlobalFileMap: %s", fileMapName.c_str(), 1); - - //2.获取指向文件视图的指针 pBuf,MapViewOfFile()函数负责把文件数据映射到进程的地址空间 - pBuf = (char*)MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, FILEMAP_BUF); - COND_LOG_RET(pBuf, __LINE__, "MapViewOfFile: %x", pBuf, 1); - - /*strcpy_s(pBuf, FILEMAP_BUF, "hello"); - COND_LOG_RET(SetEvent(hServerEvent), __LINE__, "SetEvent: %s", serverEventName.c_str(), 1);*/ - - return true; +void CleanupIPC() { + if (pBuf) { + UnmapViewOfFile(pBuf); + pBuf = NULL; + } + if (hFileMap) { + CloseHandle(hFileMap); + hFileMap = NULL; + } + if (hServerEvent) { + CloseHandle(hServerEvent); + hServerEvent = NULL; + } + if (hClientEvent) { + CloseHandle(hClientEvent); + hClientEvent = NULL; + } + g_bIPCInitialized = false; } -int main() -{ - COND_LOG_RET(initFoundSet(), __LINE__, "initFoundSet()(ZeroSuccess): %d", GetLastError(), 1); +// 处理按钮点击事件 +void OnButtonClick(int buttonId) { + switch (buttonId) { + case IDC_BUTTON_HIDE: + Log(LogLevel::LOG_INFO, __LINE__, "执行隐藏窗口操作..."); + if (HookCurWindow(hideDllName)) { + Log(LogLevel::LOG_INFO, __LINE__, "窗口隐藏操作完成"); + UpdateStatus(L"状态: 窗口已隐藏"); + } + break; - COND_LOG_RET(initIPCEnvironment(), __LINE__, "initIPCEnvironment()(ZeroSuccess): %d", GetLastError(), 1); - - COND_LOG_RET(HookCurWindow(hideDllName), __LINE__, "HookCurWindow(hideDllName)(ZeroSuccess): %d", GetLastError(), 1); + case IDC_BUTTON_SHOW: + Log(LogLevel::LOG_INFO, __LINE__, "执行显示窗口操作..."); + if (HookCurWindow(unhideDllName)) { + Log(LogLevel::LOG_INFO, __LINE__, "窗口显示操作完成"); + UpdateStatus(L"状态: 窗口已显示"); + } + break; - COND_LOG_RET(HookRtlWindow(true), __LINE__, "HookRtlWindow(true)(ZeroSuccess): %d", GetLastError(), 1); - - strcpy_s(pBuf, FILEMAP_BUF, "hello"); - COND_LOG_RET(SetEvent(hServerEvent), __LINE__, "SetEvent: %x", hServerEvent, 1); + case IDC_BUTTON_HOOK_RTL: + if (!g_bRtlHookEnabled) { + Log(LogLevel::LOG_INFO, __LINE__, "启用实时钩子..."); + HookRtlWindow(true); + } + else { + Log(LogLevel::LOG_WARN, __LINE__, "实时钩子已经启用"); + } + break; - Log(LogLevel::LOG_INFO, __LINE__, "主线程开始监听与Service通信..."); + case IDC_BUTTON_UNHOOK_RTL: + if (g_bRtlHookEnabled) { + Log(LogLevel::LOG_INFO, __LINE__, "禁用实时钩子..."); + HookRtlWindow(false); + } + else { + Log(LogLevel::LOG_WARN, __LINE__, "实时钩子已经禁用"); + } + break; - while (1) - { - __GetEvent(hClientEvent, INFINITE); - if (pBuf) - { - Log(LogLevel::LOG_INFO, __LINE__, "收到控制信息: %s", pBuf); - if (string(pBuf) == "stop") - { - break; - } - else if (string(pBuf) == "debug")//显示本身控制台程序 - { - ShowWindow(GetConsoleWindow(), SW_SHOWNA); - /*DWORD lasterror = GetLastError(); - auto getLogDir = []() ->string { - char dir[MAX_PATH]; - GetModuleFileNameA(NULL, dir, MAX_PATH); - PathRemoveFileSpecA(dir); -#ifdef _WIN64 - PathAppendA(dir, "log.txt"); -#else - PathAppendA(dir, "log32.txt"); -#endif - return string{ dir }; - }; - auto dir = getLogDir(); - if (!dir.empty()) - { - FILE* fp = NULL; - if ((fp = fopen(dir.c_str(), "a+")) != NULL) - { - fprintf(fp, "ShowWindow %x ret[%d]: %d\n", (DWORD)consoleWindow, lasterror, ret); - fclose(fp); - } - - }*/ - __SetEvent(hServerEvent); - } - } - } - COND_LOG_RET(HookRtlWindow(false), __LINE__, "HookRtlWindow(false)(ZeroSuccess): %d", GetLastError(), 1); - Sleep(1500); - COND_LOG_RET(HookCurWindow(unhideDllName), __LINE__, "HookCurWindow(unhideDllName)(ZeroSuccess): %d", GetLastError(), 1); - __SetEvent(hServerEvent); - //释放资源 - CloseHandle(hServerEvent); - CloseHandle(hClientEvent); - if (pBuf) UnmapViewOfFile(pBuf); - CloseHandle(hFileMap); - return 0; + case IDC_BUTTON_DEBUG: + if (g_bIPCInitialized && pBuf) { + strcpy_s(pBuf, FILEMAP_BUF, "debug"); + SetEvent(hServerEvent); + Log(LogLevel::LOG_INFO, __LINE__, "发送调试命令"); + } + else { + Log(LogLevel::LOG_ERROR, __LINE__, "IPC未初始化,无法发送命令"); + } + break; + + case IDC_BUTTON_STOP: + if (g_bIPCInitialized && pBuf) { + strcpy_s(pBuf, FILEMAP_BUF, "stop"); + SetEvent(hServerEvent); + Log(LogLevel::LOG_INFO, __LINE__, "发送停止命令"); + } + break; + + case IDC_BUTTON_CLEAR_LOG: + SendMessage(g_hLogListBox, LB_RESETCONTENT, 0, 0); + Log(LogLevel::LOG_INFO, __LINE__, "日志已清空"); + break; + + case IDC_BUTTON_VISBLE_SELF: + Log(LogLevel::LOG_INFO, __LINE__, "执行隐藏自身操作..."); + HideSelf(); + break; + } + +} + +// 窗口过程函数 +LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + switch (msg) { + case WM_CREATE: + { + // 创建控件 + CreateWindow(L"BUTTON", L"隐藏窗口", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, + 10, 10, 100, 30, hwnd, (HMENU)IDC_BUTTON_HIDE, g_hInst, NULL); + + CreateWindow(L"BUTTON", L"显示窗口", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, + 120, 10, 100, 30, hwnd, (HMENU)IDC_BUTTON_SHOW, g_hInst, NULL); + + CreateWindow(L"BUTTON", L"启用实时钩子", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, + 230, 10, 100, 30, hwnd, (HMENU)IDC_BUTTON_HOOK_RTL, g_hInst, NULL); + + CreateWindow(L"BUTTON", L"禁用实时钩子", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, + 340, 10, 100, 30, hwnd, (HMENU)IDC_BUTTON_UNHOOK_RTL, g_hInst, NULL); + + CreateWindow(L"BUTTON", L"调试", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, + 450, 10, 60, 30, hwnd, (HMENU)IDC_BUTTON_DEBUG, g_hInst, NULL); + + CreateWindow(L"BUTTON", L"停止", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, + 520, 10, 60, 30, hwnd, (HMENU)IDC_BUTTON_STOP, g_hInst, NULL); + + CreateWindow(L"BUTTON", L"清空日志", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, + 590, 10, 80, 30, hwnd, (HMENU)IDC_BUTTON_CLEAR_LOG, g_hInst, NULL); + + CreateWindow(L"BUTTON", L"隐藏自身", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, + 10, 375, 80, 30, hwnd, (HMENU)IDC_BUTTON_VISBLE_SELF, g_hInst, NULL); + + // 状态文本 + g_hStatusText = CreateWindow(L"STATIC", L"状态: 就绪", WS_VISIBLE | WS_CHILD | SS_LEFT, + 10, 50, 660, 20, hwnd, (HMENU)IDC_STATIC_STATUS, g_hInst, NULL); + + // 日志列表框 + g_hLogListBox = CreateWindow(L"LISTBOX", NULL, + WS_VISIBLE | WS_CHILD | WS_BORDER | WS_VSCROLL | LBS_NOTIFY, + 10, 80, 660, 300, hwnd, (HMENU)IDC_LISTBOX_LOG, g_hInst, NULL); + + // 初始化 + SetPrivilege(); + initIPCEnvironment(); + + Log(LogLevel::LOG_INFO, __LINE__, "窗口控制程序已启动"); + UpdateStatus(L"状态: 程序已初始化"); + } + break; + + case WM_COMMAND: + if (HIWORD(wParam) == BN_CLICKED) { + OnButtonClick(LOWORD(wParam)); + } + break; + case WM_HOTKEY: + if (wParam == HOTKEY_ID) { + Log(LogLevel::LOG_INFO, __LINE__, "全局快捷键 Ctrl+Alt+Z 被触发"); + if (g_bSelfHidden) { + ShowWindow(g_hMainWnd, SW_SHOW); + g_bSelfHidden = false; + UpdateStatus(L"状态: 程序已显示"); + Log(LogLevel::LOG_INFO, __LINE__, "程序窗口已显示"); + } + else { + HideSelf(); + } + } + break; + + case WM_CLOSE: + UnregisterHotKey(hwnd, HOTKEY_ID); // 注销热键 + Log(LogLevel::LOG_INFO, __LINE__, "已注销全局快捷键"); + + // 清理资源 + if (g_bRtlHookEnabled) { + HookRtlWindow(false); + Sleep(500); + } + HookCurWindow(unhideDllName); + CleanupIPC(); + DestroyWindow(hwnd); + break; + + case WM_DESTROY: + PostQuitMessage(0); + break; + + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + return 0; +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + g_hInst = hInstance; + + // 注册窗口类 + WNDCLASSEX wc = { 0 }; + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WndProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszClassName = g_szClassName; + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); + + if (!RegisterClassEx(&wc)) { + MessageBox(NULL, L"窗口类注册失败!", L"错误", MB_ICONERROR); + return 0; + } + + // 创建窗口 + g_hMainWnd = CreateWindowEx( + WS_EX_CLIENTEDGE, + g_szClassName, + g_szTitle, + WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, 700, 450, + NULL, NULL, hInstance, NULL + ); + + if (!g_hMainWnd) { + MessageBox(NULL, L"窗口创建失败!", L"错误", MB_ICONERROR); + return 0; + } + if (RegisterHotKey(g_hMainWnd, HOTKEY_ID, MOD_CONTROL | MOD_ALT, 0x5A)) { // 0x5A是'Z'键 + Log(LogLevel::LOG_INFO, __LINE__, "全局快捷键 Ctrl+Alt+Z 已注册"); + g_bHotkeyRegistered = true; + } + else { + DWORD error = GetLastError(); + Log(LogLevel::LOG_ERROR, __LINE__, "全局快捷键注册失败: %d", error); + } + + + ShowWindow(g_hMainWnd, nCmdShow); + UpdateWindow(g_hMainWnd); + // 初始化全局配置(程序启动时调用一次即可) + if (!ConfigManager::initializeGlobalConfig()) { + Log(LogLevel::LOG_WARN, __LINE__, "配置初始化失败,使用默认设置"); + } + Log(LogLevel::LOG_INFO, __LINE__, "全局配置初始化完成"); + // 消息循环 + MSG msg; + while (GetMessage(&msg, NULL, 0, 0) > 0) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + return msg.wParam; } \ No newline at end of file diff --git a/ConfigManager/ConfigManager.cpp b/ConfigManager/ConfigManager.cpp new file mode 100644 index 0000000..e87e631 --- /dev/null +++ b/ConfigManager/ConfigManager.cpp @@ -0,0 +1,385 @@ +// ConfigManager.cpp : 定义静态库的函数。 +// + +#include "pch.h" +#include "framework.h" +#include "ConfigManager.h" +#include +#include +#include +#include +#include +#include + +#pragma comment(lib,"shlwapi.lib") + +// TODO: 这是一个库函数示例 +namespace ConfigManager { + + // ProcessFilterConfig 实现 + void ProcessFilterConfig::clear() { + processList.clear(); + mode = WHITELIST; + caseSensitive = false; + } + + // Config 类实现 + Config::Config() { + m_configFilePath = getDefaultConfigPath(); + } + + Config::Config(const std::string& configPath) : m_configFilePath(configPath) { + } + + std::string Config::toLowerCase(const std::string& str) const { + std::string result = str; + std::transform(result.begin(), result.end(), result.begin(), ::tolower); + return result; + } + + std::string Config::trim(const std::string& str) const { + size_t start = str.find_first_not_of(" \t\r\n"); + if (start == std::string::npos) return ""; + size_t end = str.find_last_not_of(" \t\r\n"); + return str.substr(start, end - start + 1); + } + + bool Config::fileExists(const std::string& filePath) const { + return GetFileAttributesA(filePath.c_str()) != INVALID_FILE_ATTRIBUTES; + } + + void Config::setConfigPath(const std::string& configPath) { + m_configFilePath = configPath; + } + + std::string Config::getConfigPath() const { + return m_configFilePath; + } + + std::string Config::getDefaultConfigPath() const { + char exePath[MAX_PATH] = { 0 }; + GetModuleFileNameA(NULL, exePath, MAX_PATH); + PathRemoveFileSpecA(exePath); + PathAppendA(exePath, "process_filter.ini"); + return std::string(exePath); + } + + bool Config::loadConfig() { + return loadConfig(m_configFilePath); + } + + bool Config::loadConfig(const std::string& configPath) { + m_filterConfig.clear(); + + std::ifstream configFile(configPath); + if (!configFile.is_open()) { + std::cerr << "Warning: 无法打开配置文件: " << configPath << std::endl; + return false; + } + + std::string line; + bool inProcessSection = false; + + std::cout << "Info: 开始读取配置文件: " << configPath << std::endl; + + while (std::getline(configFile, line)) { + line = trim(line); + + // 跳过空行和注释 + if (line.empty() || line.front() == '#' || line.front() == ';') { + continue; + } + + // 检查是否是节标题 + if (line.front() == '[' && line.back() == ']') { + std::string section = line.substr(1, line.length() - 2); + section = trim(section); + inProcessSection = (toLowerCase(section) == "process"); + continue; + } + + if (!inProcessSection) { + continue; + } + + // 解析配置项 + size_t equalPos = line.find('='); + if (equalPos == std::string::npos) { + continue; + } + + std::string key = trim(line.substr(0, equalPos)); + std::string value = trim(line.substr(equalPos + 1)); + + key = toLowerCase(key); + + if (key == "mode") { + value = toLowerCase(value); + if (value == "whitelist" || value == "white") { + m_filterConfig.mode = ProcessFilterConfig::WHITELIST; + std::cout << "Info: 设置为白名单模式" << std::endl; + } + else if (value == "blacklist" || value == "black") { + m_filterConfig.mode = ProcessFilterConfig::BLACKLIST; + std::cout << "Info: 设置为黑名单模式" << std::endl; + } + } + else if (key == "casesensitive") { + value = toLowerCase(value); + m_filterConfig.caseSensitive = (value == "true" || value == "1" || value == "yes"); + std::cout << "Info: 大小写敏感: " << (m_filterConfig.caseSensitive ? "开启" : "关闭") << std::endl; + } + else if (key == "list") { + // 解析进程列表,支持逗号分隔 + std::stringstream ss(value); + std::string processName; + while (std::getline(ss, processName, ',')) { + processName = trim(processName); + if (!processName.empty()) { + if (!m_filterConfig.caseSensitive) { + processName = toLowerCase(processName); + } + m_filterConfig.processList.insert(processName); + std::cout << "Info: 添加进程: " << processName << std::endl; + } + } + } + } + + configFile.close(); + + std::cout << "Info: 配置文件加载完成,共加载 " << m_filterConfig.processList.size() << " 个进程名" << std::endl; + return true; + } + + bool Config::saveDefaultConfig() const { + return saveDefaultConfig(m_configFilePath); + } + + bool Config::saveDefaultConfig(const std::string& configPath) const { + std::ofstream configFile(configPath); + if (!configFile.is_open()) { + std::cerr << "Error: 无法创建配置文件: " << configPath << std::endl; + return false; + } + + configFile << "# 进程过滤配置文件\n"; + configFile << "# 支持的配置项:\n"; + configFile << "# mode: whitelist(白名单) 或 blacklist(黑名单)\n"; + configFile << "# casesensitive: true(大小写敏感) 或 false(大小写不敏感)\n"; + configFile << "# list: 进程名列表,用逗号分隔\n\n"; + + configFile << "[Process]\n"; + configFile << "# 过滤模式: whitelist(只处理列表中的进程) 或 blacklist(处理除列表外的进程)\n"; + configFile << "mode = whitelist\n\n"; + + configFile << "# 是否大小写敏感\n"; + configFile << "casesensitive = false\n\n"; + + configFile << "# 进程名列表(包含.exe后缀),用逗号分隔\n"; + configFile << "list = chrome.exe, msedge.exe, mstsc.exe, notepad.exe, calc.exe\n\n"; + + configFile << "# 示例黑名单配置:\n"; + configFile << "# mode = blacklist\n"; + configFile << "# list = explorer.exe, winlogon.exe, csrss.exe, smss.exe\n"; + + configFile.close(); + + std::cout << "Info: 默认配置文件已创建: " << configPath << std::endl; + return true; + } + + bool Config::reloadConfig() { + // 如果配置文件不存在,创建默认配置 + if (!fileExists(m_configFilePath)) { + std::cout << "Warning: 配置文件不存在,创建默认配置" << std::endl; + if (!saveDefaultConfig()) { + return false; + } + } + + return loadConfig(); + } + + const ProcessFilterConfig& Config::getProcessFilterConfig() const { + return m_filterConfig; + } + + ProcessFilterConfig& Config::getProcessFilterConfig() { + return m_filterConfig; + } + + bool Config::shouldProcessBeHooked(const std::string& processName) const { + if (m_filterConfig.processList.empty()) { + // 如果没有配置,使用默认行为 + return true; + } + + std::string nameToCheck = processName; + if (!m_filterConfig.caseSensitive) { + nameToCheck = toLowerCase(processName); + } + + bool inList = m_filterConfig.processList.find(nameToCheck) != m_filterConfig.processList.end(); + + if (m_filterConfig.mode == ProcessFilterConfig::WHITELIST) { + return inList; // 白名单模式:只处理列表中的进程 + } + else { + return !inList; // 黑名单模式:处理列表外的进程 + } + } + + void Config::setFilterMode(ProcessFilterConfig::FilterMode mode) { + m_filterConfig.mode = mode; + } + + ProcessFilterConfig::FilterMode Config::getFilterMode() const { + return m_filterConfig.mode; + } + + void Config::setCaseSensitive(bool sensitive) { + m_filterConfig.caseSensitive = sensitive; + } + + bool Config::isCaseSensitive() const { + return m_filterConfig.caseSensitive; + } + + void Config::addProcess(const std::string& processName) { + std::string nameToAdd = processName; + if (!m_filterConfig.caseSensitive) { + nameToAdd = toLowerCase(processName); + } + m_filterConfig.processList.insert(nameToAdd); + } + + void Config::removeProcess(const std::string& processName) { + std::string nameToRemove = processName; + if (!m_filterConfig.caseSensitive) { + nameToRemove = toLowerCase(processName); + } + m_filterConfig.processList.erase(nameToRemove); + } + + void Config::clearProcessList() { + m_filterConfig.processList.clear(); + } + + std::vector Config::getProcessList() const { + std::vector result; + result.reserve(m_filterConfig.processList.size()); + for (const auto& process : m_filterConfig.processList) { + result.push_back(process); + } + return result; + } + + size_t Config::getProcessCount() const { + return m_filterConfig.processList.size(); + } + + bool Config::isConfigValid() const { + return !m_configFilePath.empty(); + } + + void Config::printConfig() const { + std::cout << "=== 配置信息 ===" << std::endl; + std::cout << "配置文件路径: " << m_configFilePath << std::endl; + std::cout << "过滤模式: " << (m_filterConfig.mode == ProcessFilterConfig::WHITELIST ? "白名单" : "黑名单") << std::endl; + std::cout << "大小写敏感: " << (m_filterConfig.caseSensitive ? "是" : "否") << std::endl; + std::cout << "进程列表 (" << m_filterConfig.processList.size() << "个):" << std::endl; + for (const auto& process : m_filterConfig.processList) { + std::cout << " - " << process << std::endl; + } + std::cout << "================" << std::endl; + } + + // GlobalConfig 静态成员初始化 + Config* GlobalConfig::s_instance = nullptr; + bool GlobalConfig::s_initialized = false; + + bool GlobalConfig::initialize() { + if (s_initialized) { + return true; + } + + s_instance = new Config(); + s_initialized = s_instance->reloadConfig(); + + if (!s_initialized) { + delete s_instance; + s_instance = nullptr; + } + + return s_initialized; + } + + bool GlobalConfig::initialize(const std::string& configPath) { + if (s_initialized) { + return true; + } + + s_instance = new Config(configPath); + s_initialized = s_instance->reloadConfig(); + + if (!s_initialized) { + delete s_instance; + s_instance = nullptr; + } + + return s_initialized; + } + + void GlobalConfig::cleanup() { + if (s_instance) { + delete s_instance; + s_instance = nullptr; + } + s_initialized = false; + } + + Config* GlobalConfig::getInstance() { + return s_instance; + } + + bool GlobalConfig::isInitialized() { + return s_initialized; + } + + // 便捷函数实现 + bool initializeGlobalConfig() { + return GlobalConfig::initialize(); + } + + bool initializeGlobalConfig(const std::string& configPath) { + return GlobalConfig::initialize(configPath); + } + + Config* getGlobalConfig() { + return GlobalConfig::getInstance(); + } + + void cleanupGlobalConfig() { + GlobalConfig::cleanup(); + } + + bool shouldProcessBeHooked(const std::string& processName) { + + Config* config = GlobalConfig::getInstance(); + if (!config) { + initializeGlobalConfig(); + config = GlobalConfig::getInstance(); + } + return config->shouldProcessBeHooked(processName); + } + + bool reloadGlobalConfig() { + Config* config = GlobalConfig::getInstance(); + if (!config) { + return false; + } + return config->reloadConfig(); + } + +} // namespace ConfigManager diff --git a/ConfigManager/ConfigManager.h b/ConfigManager/ConfigManager.h new file mode 100644 index 0000000..793a645 --- /dev/null +++ b/ConfigManager/ConfigManager.h @@ -0,0 +1,107 @@ +#pragma once +#pragma once + +#include +#include +#include + +/** + * ù - ڹ̹˺ѡ + */ +namespace ConfigManager { + + // ̹ýṹ + struct ProcessFilterConfig { + enum FilterMode { + WHITELIST, // ģʽֻбеĽ + BLACKLIST // ģʽбĽ + }; + + FilterMode mode = WHITELIST; + std::unordered_set processList; + bool caseSensitive = false; + + void clear(); + }; + + // ù + class Config { + private: + ProcessFilterConfig m_filterConfig; + std::string m_configFilePath; + + // ߺ + std::string toLowerCase(const std::string& str) const; + std::string trim(const std::string& str) const; + bool fileExists(const std::string& filePath) const; + + public: + Config(); + explicit Config(const std::string& configPath); + ~Config() = default; + + // ļ· + void setConfigPath(const std::string& configPath); + std::string getConfigPath() const; + std::string getDefaultConfigPath() const; + + // üغͱ + bool loadConfig(); + bool loadConfig(const std::string& configPath); + bool saveDefaultConfig() const; + bool saveDefaultConfig(const std::string& configPath) const; + bool reloadConfig(); + + // ̹÷ + const ProcessFilterConfig& getProcessFilterConfig() const; + ProcessFilterConfig& getProcessFilterConfig(); + + // ̹ط + bool shouldProcessBeHooked(const std::string& processName) const; + void setFilterMode(ProcessFilterConfig::FilterMode mode); + ProcessFilterConfig::FilterMode getFilterMode() const; + void setCaseSensitive(bool sensitive); + bool isCaseSensitive() const; + + // б + void addProcess(const std::string& processName); + void removeProcess(const std::string& processName); + void clearProcessList(); + std::vector getProcessList() const; + size_t getProcessCount() const; + + // ֤ + bool isConfigValid() const; + + // Ϣ + void printConfig() const; + }; + + // ȫʵ + class GlobalConfig { + private: + static Config* s_instance; + static bool s_initialized; + + public: + static bool initialize(); + static bool initialize(const std::string& configPath); + static void cleanup(); + static Config* getInstance(); + static bool isInitialized(); + }; + + // ݺ + bool initializeGlobalConfig(); + bool initializeGlobalConfig(const std::string& configPath); + Config* getGlobalConfig(); + void cleanupGlobalConfig(); + + // ֱӲȫõıݺ + bool shouldProcessBeHooked(const std::string& processName); + bool reloadGlobalConfig(); +} + +// Ժ궨 +#define PROCESS_FILTER_WHITELIST ConfigManager::ProcessFilterConfig::WHITELIST +#define PROCESS_FILTER_BLACKLIST ConfigManager::ProcessFilterConfig::BLACKLIST \ No newline at end of file diff --git a/ConfigManager/ConfigManager.vcxproj b/ConfigManager/ConfigManager.vcxproj new file mode 100644 index 0000000..8ad0690 --- /dev/null +++ b/ConfigManager/ConfigManager.vcxproj @@ -0,0 +1,155 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {b5afeb98-c976-4839-9a8e-4f48b057d7fd} + ConfigManager + 10.0 + + + + StaticLibrary + true + v143 + Unicode + + + StaticLibrary + false + v143 + true + Unicode + + + StaticLibrary + true + v143 + Unicode + + + StaticLibrary + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + Use + pch.h + + + + + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + Use + pch.h + + + + + true + + + + + Level3 + true + _DEBUG;_LIB;%(PreprocessorDefinitions) + true + Use + pch.h + ProgramDatabase + + + + + true + + + + + Level3 + true + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + true + Use + pch.h + + + + + true + + + + + + + + + + + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/ConfigManager/ConfigManager.vcxproj.filters b/ConfigManager/ConfigManager.vcxproj.filters new file mode 100644 index 0000000..3c24fa5 --- /dev/null +++ b/ConfigManager/ConfigManager.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 头文件 + + + 头文件 + + + 头文件 + + + + + 源文件 + + + 源文件 + + + \ No newline at end of file diff --git a/ConfigManager/framework.h b/ConfigManager/framework.h new file mode 100644 index 0000000..d2d95bd --- /dev/null +++ b/ConfigManager/framework.h @@ -0,0 +1,3 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 diff --git a/ConfigManager/pch.cpp b/ConfigManager/pch.cpp new file mode 100644 index 0000000..b6fb8f4 --- /dev/null +++ b/ConfigManager/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: 与预编译标头对应的源文件 + +#include "pch.h" + +// 当使用预编译的头时,需要使用此源文件,编译才能成功。 diff --git a/ConfigManager/pch.h b/ConfigManager/pch.h new file mode 100644 index 0000000..9660927 --- /dev/null +++ b/ConfigManager/pch.h @@ -0,0 +1,13 @@ +// pch.h: 这是预编译标头文件。 +// 下方列出的文件仅编译一次,提高了将来生成的生成性能。 +// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。 +// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。 +// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。 + +#ifndef PCH_H +#define PCH_H + +// 添加要在此处预编译的标头 +#include "framework.h" + +#endif //PCH_H diff --git a/Hide/Hide.vcxproj b/Hide/Hide.vcxproj index 7202141..e81823c 100644 --- a/Hide/Hide.vcxproj +++ b/Hide/Hide.vcxproj @@ -29,26 +29,26 @@ DynamicLibrary true - v142 + v143 Unicode DynamicLibrary false - v142 + v143 true Unicode DynamicLibrary true - v142 + v143 Unicode DynamicLibrary false - v142 + v143 true Unicode diff --git a/Hide/dllmain.cpp b/Hide/dllmain.cpp index 1ce831d..7e6cba2 100644 --- a/Hide/dllmain.cpp +++ b/Hide/dllmain.cpp @@ -36,7 +36,7 @@ BOOL CALLBACK lpEnumFunc(HWND hwnd, LPARAM lParam) GetWindowThreadProcessId(hwnd, &processId); if (processId == GetCurrentProcessId()) { - if ((GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE) == WS_VISIBLE && SetWindowDisplayAffinity(hwnd, WDA_MONITOR)) + if ((GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE) == WS_VISIBLE && SetWindowDisplayAffinity(hwnd, WDA_EXCLUDEFROMCAPTURE)) { //获取窗口标题 char title[MAX_PATH] = { 0 }; @@ -49,7 +49,10 @@ BOOL CALLBACK lpEnumFunc(HWND hwnd, LPARAM lParam) { haveRect = (rect.right - rect.left > 0) && (rect.bottom - rect.top > 0); isMinimized = !haveRect; - } + } + SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) + & ~WS_EX_APPWINDOW | WS_EX_TOOLWINDOW); + //summary char summary[512] = { 0 }; @@ -66,7 +69,7 @@ void setDAForWindows() { HWND windowHandle = NULL; do { windowHandle = FindWindowEx(NULL, windowHandle, NULL, NULL); - if ((GetWindowLong(windowHandle, GWL_STYLE) & WS_VISIBLE) == WS_VISIBLE && SetWindowDisplayAffinity(windowHandle, WDA_MONITOR)) + if ((GetWindowLong(windowHandle, GWL_STYLE) & WS_VISIBLE) == WS_VISIBLE && SetWindowDisplayAffinity(windowHandle, WDA_EXCLUDEFROMCAPTURE)) { //获取窗口标题 char title[MAX_PATH] = { 0 }; @@ -81,6 +84,9 @@ void setDAForWindows() { isMinimized = !haveRect; } + SetWindowLong(windowHandle, GWL_EXSTYLE, GetWindowLong(windowHandle, GWL_EXSTYLE) + & ~WS_EX_APPWINDOW | WS_EX_TOOLWINDOW); + //summary char summary[512] = { 0 }; sprintf(summary, "进程名:%s, 窗口句柄:%x, 标题:%s, 最小化:%d, 状态:隐藏", procName.c_str(), windowHandle, title, isMinimized);//bool isMinimized不能转成%s diff --git a/RtlHook/RtlHook.vcxproj b/RtlHook/RtlHook.vcxproj index 77896cc..8d29965 100644 --- a/RtlHook/RtlHook.vcxproj +++ b/RtlHook/RtlHook.vcxproj @@ -30,26 +30,26 @@ DynamicLibrary true - v142 + v143 Unicode DynamicLibrary false - v142 + v143 true Unicode DynamicLibrary true - v142 + v143 Unicode DynamicLibrary false - v142 + v143 true Unicode @@ -168,6 +168,11 @@ Create + + + {b5afeb98-c976-4839-9a8e-4f48b057d7fd} + + diff --git a/RtlHook/dllmain.cpp b/RtlHook/dllmain.cpp index bbd6337..bab066e 100644 --- a/RtlHook/dllmain.cpp +++ b/RtlHook/dllmain.cpp @@ -4,29 +4,62 @@ #include #include #include +#include "../ConfigManager/ConfigManager.h" +#include // 必须 +#pragma comment(lib, "psapi.lib") #pragma comment(lib,"shlwapi.lib") using namespace std; void OutputErrorString(const char* text, const char* file, int line) { - char msg[512] = { 0 }; - sprintf(msg, "[%s:%d] %s:%d", file, line, text, GetLastError()); - OutputDebugStringA(msg); + char msg[512] = { 0 }; + sprintf(msg, "[%s:%d] %s:%d", file, line, text, GetLastError()); + OutputDebugStringA(msg); } +std::string GetExeNameFromHwnd(HWND hwnd) +{ + DWORD pid = 0; + GetWindowThreadProcessId(hwnd, &pid); + if (pid == 0) return "unknown"; + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); + if (!hProcess) return "unknown"; + + char exePath[MAX_PATH] = { 0 }; + if (GetModuleFileNameExA(hProcess, NULL, exePath, MAX_PATH) == 0) + { + CloseHandle(hProcess); + return "unknown"; + } + CloseHandle(hProcess); + + // 提取文件名部分 + char* exeName = strrchr(exePath, '\\'); + return (exeName ? exeName + 1 : exePath); +} string getProcName() { - char szProcName[MAX_PATH] = { 0 }; - if (GetModuleFileNameA(NULL, szProcName, MAX_PATH)) - { - PathStripPathA(szProcName); - return szProcName; - } - else - { - OutputErrorString("GetModuleFileNameA failed", __FILE__, __LINE__); - } - return string{ "false" }; + char szProcName[MAX_PATH] = { 0 }; + if (GetModuleFileNameA(NULL, szProcName, MAX_PATH)) + { + PathStripPathA(szProcName); + return szProcName; + } + else + { + OutputErrorString("GetModuleFileNameA failed", __FILE__, __LINE__); + } + return string{ "false" }; +} +string getProcNameByHandle(HANDLE hProcess) +{ + char exeName[MAX_PATH] = { 0 }; + if (GetModuleFileNameExA(hProcess, NULL, exeName, MAX_PATH)) + { + PathStripPathA(exeName); + return exeName; + } + return {}; } string procName = getProcName(); @@ -35,101 +68,118 @@ unordered_map hastryHookedProc; LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam) { - // 一般来说,所有运行的进程(有窗口过程的)都会加载这个钩子过程了 - CWPSTRUCT* pCwp = reinterpret_cast(lParam); - switch (pCwp->message) - { - case WM_CREATE: - { - if (hastryHookedProc.find(pCwp->hwnd) == hastryHookedProc.end()) - { - if (SetWindowDisplayAffinity(pCwp->hwnd, WDA_MONITOR)) - { - char title[MAX_PATH] = { 0 }; - GetWindowTextA(pCwp->hwnd, title, MAX_PATH); - char msg[512] = { 0 }; - if (title[0] != '\0') - sprintf(msg, "WM_CREATE[%s]:%s", procName.c_str(), title); - else - sprintf(msg, "WM_CREATE[%s]:%s", procName.c_str(), "NoTitle"); - OutputDebugStringA(msg); - } - hastryHookedProc[pCwp->hwnd] = 1; - } - break; - } - case WM_SHOWWINDOW: - { - if (hastryHookedProc.find(pCwp->hwnd) == hastryHookedProc.end()) - { - if (SetWindowDisplayAffinity(pCwp->hwnd, WDA_MONITOR)) - { - char title[MAX_PATH] = { 0 }; - GetWindowTextA(pCwp->hwnd, title, MAX_PATH); - char msg[512] = { 0 }; - if (title[0] != '\0') - sprintf(msg, "WM_SHOWWINDOW[%s]:%s", procName.c_str(), title); - else - sprintf(msg, "WM_SHOWWINDOW[%s]:%s", procName.c_str(), "NoTitle"); - OutputDebugStringA(msg); - } - hastryHookedProc[pCwp->hwnd] = 1; - } - break; - } - /*case WM_CLOSE: - { - char title[MAX_PATH] = { 0 }; - GetWindowTextA(pCwp->hwnd, title, MAX_PATH); - OutputDebugStringA((string(pname) + title + " close").c_str()); - break; - }*/ - - default: - break; - } - return CallNextHookEx(hHook, nCode, wParam, lParam); + // 一般来说,所有运行的进程(有窗口过程的)都会加载这个钩子过程了 + CWPSTRUCT* pCwp = reinterpret_cast(lParam); + + switch (pCwp->message) + { + case WM_CREATE: + { + if (hastryHookedProc.find(pCwp->hwnd) == hastryHookedProc.end()) + { + + DWORD dwPid; + GetWindowThreadProcessId(pCwp->hwnd, &dwPid); // Change windowHandle to pCwp->hwnd + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); + if (!hProcess) return CallNextHookEx(hHook, nCode, wParam, lParam); + string exeName = getProcNameByHandle(hProcess); + if (ConfigManager::shouldProcessBeHooked(exeName)) { + if (SetWindowDisplayAffinity(pCwp->hwnd, WDA_EXCLUDEFROMCAPTURE)) + { + + SetWindowLong(pCwp->hwnd, GWL_EXSTYLE, GetWindowLong(pCwp->hwnd, GWL_EXSTYLE) + & ~WS_EX_APPWINDOW | WS_EX_TOOLWINDOW); + + char title[MAX_PATH] = { 0 }; + GetWindowTextA(pCwp->hwnd, title, MAX_PATH); + char msg[512] = { 0 }; + if (title[0] != '\0') + sprintf(msg, "WM_CREATE[%s]:%s", procName.c_str(), title); + else + sprintf(msg, "WM_CREATE[%s]:%s", procName.c_str(), "NoTitle"); + OutputDebugStringA(msg); + } + } + CloseHandle(hProcess); + hastryHookedProc[pCwp->hwnd] = 1; + } + break; + } + case WM_SHOWWINDOW: + { + if (hastryHookedProc.find(pCwp->hwnd) == hastryHookedProc.end()) + { + if (SetWindowDisplayAffinity(pCwp->hwnd, WDA_EXCLUDEFROMCAPTURE)) + { + SetWindowLong(pCwp->hwnd, GWL_EXSTYLE, GetWindowLong(pCwp->hwnd, GWL_EXSTYLE) + & ~WS_EX_APPWINDOW | WS_EX_TOOLWINDOW); + + char title[MAX_PATH] = { 0 }; + GetWindowTextA(pCwp->hwnd, title, MAX_PATH); + char msg[512] = { 0 }; + if (title[0] != '\0') + sprintf(msg, "WM_SHOWWINDOW[%s]:%s", procName.c_str(), title); + else + sprintf(msg, "WM_SHOWWINDOW[%s]:%s", procName.c_str(), "NoTitle"); + OutputDebugStringA(msg); + } + hastryHookedProc[pCwp->hwnd] = 1; + } + break; + } + /*case WM_CLOSE: + { + char title[MAX_PATH] = { 0 }; + GetWindowTextA(pCwp->hwnd, title, MAX_PATH); + OutputDebugStringA((string(pname) + title + " close").c_str()); + break; + }*/ + + default: + break; + } + return CallNextHookEx(hHook, nCode, wParam, lParam); } EXPORT BOOL WINAPI SetHook(BOOL isInstall) { - if (isInstall) - { - hHook = SetWindowsHookEx(WH_CALLWNDPROC, HookProc, hInstance, 0); - if (hHook) OutputDebugStringA("SetWindowsHookEx Success"); - return hHook != NULL; - } - else - { - if (UnhookWindowsHookEx(hHook)) - { - OutputDebugStringA("UnhookWindowsHookEx Success"); - hHook = NULL; - hInstance = NULL; - return TRUE; - } - } - return FALSE; + if (isInstall) + { + hHook = SetWindowsHookEx(WH_CALLWNDPROC, HookProc, hInstance, 0); + if (hHook) OutputDebugStringA("SetWindowsHookEx Success"); + return hHook != NULL; + } + else + { + if (UnhookWindowsHookEx(hHook)) + { + OutputDebugStringA("UnhookWindowsHookEx Success"); + hHook = NULL; + hInstance = NULL; + return TRUE; + } + } + return FALSE; } BOOL APIENTRY DllMain(HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved + DWORD ul_reason_for_call, + LPVOID lpReserved ) { - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - //OutputDebugStringA(("进入:" + procName).c_str()); - hInstance = (HINSTANCE)hModule; - break; - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - //OutputDebugStringA(("离开:" + procName).c_str()); - break; - } - return TRUE; + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + //OutputDebugStringA(("进入:" + procName).c_str()); + hInstance = (HINSTANCE)hModule; + break; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + //OutputDebugStringA(("离开:" + procName).c_str()); + break; + } + return TRUE; } diff --git a/UnHide/UnHide.vcxproj b/UnHide/UnHide.vcxproj index 0b58806..51efe8e 100644 --- a/UnHide/UnHide.vcxproj +++ b/UnHide/UnHide.vcxproj @@ -29,26 +29,26 @@ DynamicLibrary true - v142 + v143 Unicode DynamicLibrary false - v142 + v143 true Unicode DynamicLibrary true - v142 + v143 Unicode DynamicLibrary false - v142 + v143 true Unicode diff --git a/UnHide/dllmain.cpp b/UnHide/dllmain.cpp index 38a9adf..c457a5f 100644 --- a/UnHide/dllmain.cpp +++ b/UnHide/dllmain.cpp @@ -42,6 +42,12 @@ BOOL CALLBACK lpEnumFunc(HWND hwnd, LPARAM lParam) char title[MAX_PATH] = { 0 }; GetWindowTextA(hwnd, title, MAX_PATH); + + LONG exStyle = GetWindowLong(hwnd, GWL_EXSTYLE); + exStyle |= WS_EX_APPWINDOW; + exStyle &= ~WS_EX_TOOLWINDOW; + SetWindowLong(hwnd, GWL_EXSTYLE, exStyle); + //判断最小化 RECT rect; bool haveRect = false, isMinimized = false; @@ -72,6 +78,12 @@ void setDAForWindows() { char title[MAX_PATH] = { 0 }; GetWindowTextA(windowHandle, title, MAX_PATH); + LONG exStyle = GetWindowLong(windowHandle, GWL_EXSTYLE); + exStyle |= WS_EX_APPWINDOW; + exStyle &= ~WS_EX_TOOLWINDOW; + SetWindowLong(windowHandle, GWL_EXSTYLE, exStyle); + + //判断最小化 RECT rect; bool haveRect = false, isMinimized = false;