diff --git a/kvc/Controller.h b/kvc/Controller.h index 13346a1..8fcc1d4 100644 --- a/kvc/Controller.h +++ b/kvc/Controller.h @@ -103,6 +103,10 @@ public: bool UnprotectProcessByName(const std::wstring& processName) noexcept; bool SetProcessProtectionByName(const std::wstring& processName, const std::wstring& protectionLevel, const std::wstring& signerType) noexcept; + // Signer-based batch operations for mass unprotection scenarios + bool UnprotectBySigner(const std::wstring& signerName) noexcept; + bool ListProcessesBySigner(const std::wstring& signerName) noexcept; + bool UnprotectAllProcesses() noexcept; bool UnprotectMultipleProcesses(const std::vector& targets) noexcept; diff --git a/kvc/ControllerProcessOperations.cpp b/kvc/ControllerProcessOperations.cpp index 32ff162..f1e66da 100644 --- a/kvc/ControllerProcessOperations.cpp +++ b/kvc/ControllerProcessOperations.cpp @@ -167,7 +167,7 @@ bool Controller::KillMultipleProcesses(const std::vector& pids) noexcept } } - EndDriverSession(false); // End session after batch operation + EndDriverSession(true); // End session after batch operation INFO(L"Batch operation completed: %d/%d processes terminated", successCount, pids.size()); return successCount > 0; @@ -194,7 +194,7 @@ bool Controller::KillMultipleTargets(const std::vector& targets) n if (allPids.empty()) { ERROR(L"No processes found matching the specified targets"); - EndDriverSession(false); + EndDriverSession(true); return false; } @@ -221,7 +221,7 @@ bool Controller::KillMultipleTargets(const std::vector& targets) n EndDriverSession(true); INFO(L"Kill operation completed: %d/%d processes terminated", successCount, allPids.size()); return successCount > 0; - } +} bool Controller::KillProcessInternal(DWORD pid, bool batchOperation) noexcept { // Only start session if not batch operation (batch already started session) @@ -234,6 +234,7 @@ bool Controller::KillProcessInternal(DWORD pid, bool batchOperation) noexcept { auto kernelAddr = GetCachedKernelAddress(pid); if (!kernelAddr) { ERROR(L"Failed to get kernel address for PID %d", pid); + if (!batchOperation) EndDriverSession(true); return false; } @@ -474,6 +475,7 @@ bool Controller::SetProcessProtection(ULONG_PTR addr, UCHAR protection) noexcept std::optional Controller::ResolveProcessName(const std::wstring& processName) noexcept { if (!BeginDriverSession()) { + EndDriverSession(true); return std::nullopt; } @@ -618,6 +620,7 @@ bool Controller::IsPatternMatch(const std::wstring& processName, const std::wstr bool Controller::GetProcessProtection(DWORD pid) noexcept { if (!BeginDriverSession()) { + EndDriverSession(true); return false; } @@ -668,6 +671,7 @@ bool Controller::GetProcessProtectionByName(const std::wstring& processName) noe bool Controller::ListProtectedProcesses() noexcept { if (!BeginDriverSession()) { + EndDriverSession(true); return false; } @@ -748,6 +752,7 @@ bool Controller::ListProtectedProcesses() noexcept { bool Controller::UnprotectProcess(DWORD pid) noexcept { if (!BeginDriverSession()) { + EndDriverSession(true); return false; } @@ -782,6 +787,7 @@ bool Controller::UnprotectProcess(DWORD pid) noexcept { bool Controller::ProtectProcess(DWORD pid, const std::wstring& protectionLevel, const std::wstring& signerType) noexcept { if (!BeginDriverSession()) { + EndDriverSession(true); return false; } @@ -826,6 +832,7 @@ bool Controller::ProtectProcess(DWORD pid, const std::wstring& protectionLevel, bool Controller::SetProcessProtection(DWORD pid, const std::wstring& protectionLevel, const std::wstring& signerType) noexcept { if (!BeginDriverSession()) { + EndDriverSession(true); return false; } @@ -863,6 +870,7 @@ bool Controller::SetProcessProtection(DWORD pid, const std::wstring& protectionL bool Controller::UnprotectAllProcesses() noexcept { if (!BeginDriverSession()) { + EndDriverSession(true); return false; } @@ -896,13 +904,14 @@ bool Controller::UnprotectAllProcesses() noexcept { INFO(L"Mass unprotection completed: %d/%d processes successfully unprotected", successCount, totalCount); } - EndDriverSession(false); + EndDriverSession(true); return successCount == totalCount; } bool Controller::UnprotectMultipleProcesses(const std::vector& targets) noexcept { if (targets.empty()) { ERROR(L"No targets specified for batch unprotection"); + EndDriverSession(true); return false; } @@ -967,11 +976,123 @@ bool Controller::UnprotectMultipleProcesses(const std::vector& tar INFO(L"Batch unprotection completed: %d/%d targets successfully processed", successCount, totalCount); - EndDriverSession(false); + EndDriverSession(true); return successCount == totalCount; } +bool Controller::UnprotectBySigner(const std::wstring& signerName) noexcept { + auto signerType = Utils::GetSignerTypeFromString(signerName); + if (!signerType) { + ERROR(L"Invalid signer type: %s", signerName.c_str()); + return false; + } + + if (!BeginDriverSession()) { + EndDriverSession(true); + return false; + } + + auto processes = GetProcessList(); + DWORD totalCount = 0; + DWORD successCount = 0; + + INFO(L"Starting batch unprotection of processes signed by: %s", signerName.c_str()); + + for (const auto& entry : processes) { + if (entry.ProtectionLevel > 0 && entry.SignerType == signerType.value()) { + totalCount++; + + if (SetProcessProtection(entry.KernelAddress, 0)) { + successCount++; + SUCCESS(L"Removed protection from PID %d (%s)", entry.Pid, entry.ProcessName.c_str()); + } else { + ERROR(L"Failed to remove protection from PID %d (%s)", entry.Pid, entry.ProcessName.c_str()); + } + + if (g_interrupted) { + INFO(L"Batch operation interrupted by user"); + break; + } + } + } + + if (totalCount == 0) { + INFO(L"No protected processes found with signer: %s", signerName.c_str()); + } else { + INFO(L"Batch unprotection completed: %d/%d processes successfully unprotected", successCount, totalCount); + } + + // ZMIANA: Użyj force cleanup tak jak w ListProcessesBySigner + EndDriverSession(true); + return successCount > 0; +} + +bool Controller::ListProcessesBySigner(const std::wstring& signerName) noexcept { + auto signerType = Utils::GetSignerTypeFromString(signerName); + if (!signerType) { + ERROR(L"Invalid signer type: %s", signerName.c_str()); + return false; + } + + // Pobierz dane PRZED operacjami konsoli + std::vector processes; + + if (!BeginDriverSession()) { + return false; + } + + processes = GetProcessList(); // Pobierz dane gdy sterownik aktywny + EndDriverSession(true); // Natychmiast zamknij sterownik + + // Reszta operacji BEZ sterownika + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO consoleInfo; + GetConsoleScreenBufferInfo(hConsole, &consoleInfo); + WORD originalColor = consoleInfo.wAttributes; + + bool foundAny = false; + + INFO(L"Processes with signer: %s", signerName.c_str()); + std::wcout << L" -------+------------------------------+---------+-----------------+-----------------------+-----------------------+--------------------\n"; + std::wcout << L" PID | Process Name | Level | Signer | EXE sig. level | DLL sig. level | Kernel addr.\n"; + std::wcout << L" -------+------------------------------+---------+-----------------+-----------------------+-----------------------+--------------------\n"; + + for (const auto& entry : processes) { + if (entry.SignerType == signerType.value()) { + foundAny = true; + + if (entry.ProtectionLevel > 0) { + SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); + } + + wchar_t buffer[512]; + swprintf_s(buffer, L" %6d | %-28s | %s (%d) | %s (%d) | %s (0x%02x) | %s (0x%02x) | 0x%016llx\n", + entry.Pid, + entry.ProcessName.length() > 28 ? (entry.ProcessName.substr(0, 25) + L"...").c_str() : entry.ProcessName.c_str(), + Utils::GetProtectionLevelAsString(entry.ProtectionLevel), entry.ProtectionLevel, + Utils::GetSignerTypeAsString(entry.SignerType), entry.SignerType, + Utils::GetSignatureLevelAsString(entry.SignatureLevel), entry.SignatureLevel, + Utils::GetSignatureLevelAsString(entry.SectionSignatureLevel), entry.SectionSignatureLevel, + entry.KernelAddress + ); + std::wcout << buffer; + + SetConsoleTextAttribute(hConsole, originalColor); + } + } + + std::wcout << L" -------+------------------------------+---------+-----------------+-----------------------+-----------------------+--------------------\n"; + + if (!foundAny) { + INFO(L"No processes found with signer: %s", signerName.c_str()); + } + + SetConsoleTextAttribute(hConsole, originalColor); + std::wcout << std::flush; + + return foundAny; +} // ============================================================================ // PROCESS NAME-BASED OPERATIONS // ============================================================================ diff --git a/kvc/HelpSystem.cpp b/kvc/HelpSystem.cpp index 536d1b8..e43c45e 100644 --- a/kvc/HelpSystem.cpp +++ b/kvc/HelpSystem.cpp @@ -135,6 +135,9 @@ void HelpSystem::PrintProtectionCommands() noexcept PrintSectionHeader(L"Process Protection Commands"); PrintCommandLine(L"set ", L"Set protection (force, ignoring current state)"); PrintCommandLine(L"protect ", L"Protect unprotected process"); + PrintCommandLine(L"unprotect Antimalware", L"Remove protection from all Antimalware-signed processes"); + PrintCommandLine(L"unprotect WinTcb", L"Remove protection from all WinTcb-signed processes"); + PrintCommandLine(L"list-signer Antimalware", L"List all processes signed by Antimalware"); PrintCommandLine(L"unprotect ", L"Remove protection from specific process"); PrintCommandLine(L"unprotect all", L"Remove protection from ALL processes"); PrintCommandLine(L"unprotect ", L"Remove protection from multiple processes"); diff --git a/kvc/Kvc.cpp b/kvc/Kvc.cpp index 740d47e..1b3ebb1 100644 --- a/kvc/Kvc.cpp +++ b/kvc/Kvc.cpp @@ -542,70 +542,86 @@ int wmain(int argc, wchar_t* argv[]) return result ? 0 : 2; } - else if (command == L"unprotect") - { - if (argc < 3) - { - ERROR(L"Missing PID/process name argument for unprotection"); - return 1; - } - - std::wstring_view target = argv[2]; - - // Handle special 'all' keyword for mass unprotection scenarios - if (target == L"all") - { - return g_controller->UnprotectAllProcesses() ? 0 : 2; - } - - // Handle comma-separated list of targets for efficient batch operations - std::wstring targetStr(target); - if (targetStr.find(L',') != std::wstring::npos) - { - std::vector targets; - std::wstring current; - - // Parse comma-separated targets with whitespace handling - for (wchar_t ch : targetStr) - { - if (ch == L',') - { - if (!current.empty()) - { - targets.push_back(current); - current.clear(); - } - } - else if (ch != L' ' && ch != L'\t') - { - current += ch; - } - } - - if (!current.empty()) - targets.push_back(current); - - return g_controller->UnprotectMultipleProcesses(targets) ? 0 : 2; - } - - // Handle single target (PID or process name with pattern matching) - if (IsNumeric(target)) - { - auto pid = ParsePid(target); - if (!pid) - { - ERROR(L"Invalid PID format: %s", target.data()); - return 1; - } - return g_controller->UnprotectProcess(pid.value()) ? 0 : 2; - } - else - { - std::wstring processName(target); - return g_controller->UnprotectProcessByName(processName) ? 0 : 2; - } - } + else if (command == L"unprotect") + { + if (argc < 3) + { + ERROR(L"Missing PID/process name argument for unprotection"); + return 1; + } + std::wstring_view target = argv[2]; + + // Handle special 'all' keyword for mass unprotection scenarios + if (target == L"all") + { + return g_controller->UnprotectAllProcesses() ? 0 : 2; + } + + // Handle comma-separated list of targets for efficient batch operations + std::wstring targetStr(target); + if (targetStr.find(L',') != std::wstring::npos) + { + std::vector targets; + std::wstring current; + + // Parse comma-separated targets with whitespace handling + for (wchar_t ch : targetStr) + { + if (ch == L',') + { + if (!current.empty()) + { + targets.push_back(current); + current.clear(); + } + } + else if (ch != L' ' && ch != L'\t') + { + current += ch; + } + } + + if (!current.empty()) + targets.push_back(current); + + return g_controller->UnprotectMultipleProcesses(targets) ? 0 : 2; + } + + // NEW: Check if single target is a signer type for batch unprotection + auto signerType = Utils::GetSignerTypeFromString(targetStr); + if (signerType) { + return g_controller->UnprotectBySigner(targetStr) ? 0 : 2; + } + + // Handle single target (PID or process name with pattern matching) + if (IsNumeric(target)) + { + auto pid = ParsePid(target); + if (!pid) + { + ERROR(L"Invalid PID format: %s", target.data()); + return 1; + } + return g_controller->UnprotectProcess(pid.value()) ? 0 : 2; + } + else + { + std::wstring processName(target); + return g_controller->UnprotectProcessByName(processName) ? 0 : 2; + } + } + else if (command == L"list-signer") { + if (argc < 3) { + ERROR(L"Missing signer type argument"); + return 1; + } + + std::wstring signerName = argv[2]; + return g_controller->ListProcessesBySigner(signerName) ? 0 : 1; + } + + // System integration commands with TrustedInstaller privileges for maximum access else if (command == L"trusted") {