From bb6e4cae4f56140433b501980c31c532fe5e5385 Mon Sep 17 00:00:00 2001 From: wesmar Date: Thu, 23 Oct 2025 23:36:36 +0200 Subject: [PATCH] Aktualizacja: 2025-10-23 23:36:36 --- kvc/Controller.h | 1 + kvc/ControllerProcessOperations.cpp | 140 ++++++++++++++++++++++++++++ kvc/Kvc.cpp | 77 +++++++++------ kvc/Utils.cpp | 4 +- 4 files changed, 192 insertions(+), 30 deletions(-) diff --git a/kvc/Controller.h b/kvc/Controller.h index 6c415b4..d673ca6 100644 --- a/kvc/Controller.h +++ b/kvc/Controller.h @@ -114,6 +114,7 @@ public: bool GetProcessProtection(DWORD pid) noexcept; bool GetProcessProtectionByName(const std::wstring& processName) noexcept; bool PrintProcessInfo(DWORD pid) noexcept; + // Process protection manipulation bool SetProcessProtection(DWORD pid, const std::wstring& protectionLevel, const std::wstring& signerType) noexcept; diff --git a/kvc/ControllerProcessOperations.cpp b/kvc/ControllerProcessOperations.cpp index 2f7beb5..7bf3654 100644 --- a/kvc/ControllerProcessOperations.cpp +++ b/kvc/ControllerProcessOperations.cpp @@ -1227,4 +1227,144 @@ bool Controller::IsPatternMatch(const std::wstring& processName, const std::wstr } catch (const std::regex_error&) { return false; } +} +// Shows detailed information about the process along with an analysis of droppability. +bool Controller::PrintProcessInfo(DWORD pid) noexcept +{ + if (!BeginDriverSession()) { + EndDriverSession(true); + return false; + } + + // Podstawowe informacje o ochronie + auto kernelAddr = GetProcessKernelAddress(pid); + if (!kernelAddr) { + ERROR(L"Failed to get kernel address for PID %d", pid); + EndDriverSession(true); + return false; + } + + auto currentProtection = GetProcessProtection(kernelAddr.value()); + if (!currentProtection) { + ERROR(L"Failed to read protection for PID %d", pid); + EndDriverSession(true); + return false; + } + + UCHAR protLevel = Utils::GetProtectionLevel(currentProtection.value()); + UCHAR signerType = Utils::GetSignerType(currentProtection.value()); + + auto sigLevelOffset = m_of->GetOffset(Offset::ProcessSignatureLevel); + auto secSigLevelOffset = m_of->GetOffset(Offset::ProcessSectionSignatureLevel); + + UCHAR signatureLevel = sigLevelOffset ? + m_rtc->Read8(kernelAddr.value() + sigLevelOffset.value()).value_or(0) : 0; + UCHAR sectionSignatureLevel = secSigLevelOffset ? + m_rtc->Read8(kernelAddr.value() + secSigLevelOffset.value()).value_or(0) : 0; + + std::wstring processName = Utils::GetProcessName(pid); + + if (!Utils::EnableConsoleVirtualTerminal()) { + ERROR(L"Failed to enable console colors"); + } + + // Wyświetl podstawowe informacje + std::wcout << L"\n[*] Detailed Process Information:\n"; + std::wcout << L" PID: " << pid << L" (" << processName << L")\n"; + + if (protLevel == 0) { + std::wcout << L" Protection: NOT PROTECTED\n"; + } else { + const wchar_t* color = Utils::GetProcessDisplayColor( + signerType, signatureLevel, sectionSignatureLevel); + + std::wcout << color + << L" Protection: " + << Utils::GetProtectionLevelAsString(protLevel) << L"-" + << Utils::GetSignerTypeAsString(signerType) + << L" (raw: 0x" << std::hex << std::uppercase << (int)currentProtection.value() + << std::dec << L")" + << Utils::ProcessColors::RESET << L"\n"; + } + + std::wcout << L" Signature Level: " << Utils::GetSignatureLevelAsString(signatureLevel) + << L" (0x" << std::hex << (int)signatureLevel << std::dec << L")\n"; + std::wcout << L" Section Signature Level: " << Utils::GetSignatureLevelAsString(sectionSignatureLevel) + << L" (0x" << std::hex << (int)sectionSignatureLevel << std::dec << L")\n"; + std::wcout << L" Kernel Address: 0x" << std::hex << kernelAddr.value() << std::dec << L"\n"; + + std::wcout << L"\n[*] Dumpability Analysis:\n"; + auto dumpability = Utils::CanDumpProcess(pid, processName, protLevel, signerType); + std::wcout << L"DEBUG: CanDump=" << dumpability.CanDump << L", Reason=" << dumpability.Reason << L"\n"; + +// Zapisz oryginalny kolor konsoli + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(hConsole, &csbi); + WORD originalColor = csbi.wAttributes; + + if (dumpability.CanDump) { + std::wcout << Utils::ProcessColors::GREEN << L" ✓ DUMPABLE: " + << dumpability.Reason; + SetConsoleTextAttribute(hConsole, originalColor); + std::wcout << L"\n"; + + // Dodatkowe wskazówki + if (protLevel > 0) { + std::wcout << L" Note: Process is protected but can be dumped with elevation\n"; + } + } else { + std::wcout << Utils::ProcessColors::RED << L" ✗ NOT DUMPABLE: " + << dumpability.Reason; + SetConsoleTextAttribute(hConsole, originalColor); + std::wcout << L"\n"; + + // Sugestie obejścia + if (protLevel > 0) { + std::wcout << L" Suggestion: Try elevating current process protection first\n"; + } + if (signerType == static_cast(PS_PROTECTED_SIGNER::Antimalware)) { + std::wcout << L" Suggestion: Antimalware-protected processes require special handling\n"; + } + if (signerType == static_cast(PS_PROTECTED_SIGNER::Lsa)) { + std::wcout << L" Suggestion: LSA-protected process requires PPL-Lsa or higher\n"; + } + } + + // Information about permissions + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); + if (hProcess) { + HANDLE hToken; + if (OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) { + DWORD elevationType; + DWORD returnLength; + + if (GetTokenInformation(hToken, TokenElevationType, &elevationType, + sizeof(elevationType), &returnLength)) { + std::wcout << L"\n[*] Process Context:\n"; + std::wcout << L" Elevation Type: "; + + switch (elevationType) { + case TokenElevationTypeDefault: + std::wcout << L"Default\n"; + break; + case TokenElevationTypeFull: + std::wcout << L"Full (Admin)\n"; + break; + case TokenElevationTypeLimited: + std::wcout << L"Limited\n"; + break; + default: + std::wcout << L"Unknown\n"; + } + } + CloseHandle(hToken); + } + CloseHandle(hProcess); + } + + SetConsoleTextAttribute(hConsole, originalColor); + std::wcout << std::endl; + EndDriverSession(true); + return true; } \ No newline at end of file diff --git a/kvc/Kvc.cpp b/kvc/Kvc.cpp index 159fa8d..43ba4e7 100644 --- a/kvc/Kvc.cpp +++ b/kvc/Kvc.cpp @@ -438,33 +438,50 @@ int wmain(int argc, wchar_t* argv[]) return g_controller->ListProtectedProcesses() ? 0 : 2; } - else if (command == L"info") { - if (argc < 3) { - ERROR(L"Missing PID/process name argument"); - return 1; - } - - std::wstring_view target = argv[2]; - - if (IsNumeric(target)) { - auto pid = ParsePid(target); - if (!pid) { - ERROR(L"Invalid PID format: %s", target.data()); - return 1; - } - return g_controller->GetProcessProtection(pid.value()) ? 0 : 2; - } else { - std::wstring processName(target); - return g_controller->GetProcessProtectionByName(processName) ? 0 : 2; - } - } - - else if (command == L"get") { - if (argc < 3) { + // ==================================================================== + // PROCESS INFORMATION COMMANDS + // ==================================================================== + + else if (command == L"list") { + // Detect reboot and enforce session limit + g_controller->m_sessionMgr.DetectAndHandleReboot(); + return g_controller->ListProtectedProcesses() ? 0 : 2; + } + + else if (command == L"get") + { + if (argc < 3) + { ERROR(L"Missing PID/process name argument"); return 1; } + + std::wstring_view target = argv[2]; + // Simple protection info display + if (IsNumeric(target)) + { + auto pid = ParsePid(target); + if (!pid) + { + ERROR(L"Invalid PID format: %s", target.data()); + return 1; + } + return g_controller->GetProcessProtection(pid.value()) ? 0 : 2; + } + else + { + std::wstring processName(target); + return g_controller->GetProcessProtectionByName(processName) ? 0 : 2; + } + } + + else if (command == L"info") { + if (argc < 3) { + ERROR(L"Missing PID/process name argument for detailed information"); + return 1; + } + std::wstring_view target = argv[2]; if (IsNumeric(target)) { @@ -473,14 +490,18 @@ int wmain(int argc, wchar_t* argv[]) ERROR(L"Invalid PID format: %s", target.data()); return 1; } - return g_controller->GetProcessProtection(pid.value()) ? 0 : 2; + return g_controller->PrintProcessInfo(pid.value()) ? 0 : 2; } else { std::wstring processName(target); - return g_controller->GetProcessProtectionByName(processName) ? 0 : 2; + auto match = g_controller->ResolveNameWithoutDriver(processName); + if (match) { + return g_controller->PrintProcessInfo(match->Pid) ? 0 : 2; + } else { + return 2; + } } - } - - + } + else if (command == L"list-signer") { if (argc < 3) { ERROR(L"Missing signer type argument"); diff --git a/kvc/Utils.cpp b/kvc/Utils.cpp index f4eceae..9a136ca 100644 --- a/kvc/Utils.cpp +++ b/kvc/Utils.cpp @@ -1044,7 +1044,7 @@ bool SplitKvcEvtx(const std::vector& kvcData, return false; } - DEBUG(L"Split kvc.evtx: kvc.sys=%zu bytes, ExplorerFrame\u200B.dll=%zu bytes", + DEBUG(L"Split kvc.evtx: kvc.sys=%zu bytes, ExplorerFrame.dll=%zu bytes", outKvcSys.size(), outDll.size()); return true; @@ -1094,7 +1094,7 @@ bool ExtractResourceComponents(int resourceId, return false; } - DEBUG(L"[EXTRACT] Success - kvc.sys: %zu bytes, ExplorerFrame\u200B.dll: %zu bytes", + DEBUG(L"[EXTRACT] Success - kvc.sys: %zu bytes, ExplorerFrame.dll: %zu bytes", outKvcSys.size(), outDll.size()); return true;