Aktualizacja: 2025-10-23 23:36:36
This commit is contained in:
@@ -115,6 +115,7 @@ public:
|
||||
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;
|
||||
bool ProtectProcess(DWORD pid, const std::wstring& protectionLevel, const std::wstring& signerType) noexcept;
|
||||
|
||||
@@ -1228,3 +1228,143 @@ bool Controller::IsPatternMatch(const std::wstring& processName, const std::wstr
|
||||
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<UCHAR>(PS_PROTECTED_SIGNER::Antimalware)) {
|
||||
std::wcout << L" Suggestion: Antimalware-protected processes require special handling\n";
|
||||
}
|
||||
if (signerType == static_cast<UCHAR>(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;
|
||||
}
|
||||
69
kvc/Kvc.cpp
69
kvc/Kvc.cpp
@@ -438,49 +438,70 @@ 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;
|
||||
}
|
||||
// ====================================================================
|
||||
// PROCESS INFORMATION COMMANDS
|
||||
// ====================================================================
|
||||
|
||||
std::wstring_view target = argv[2];
|
||||
else if (command == L"list") {
|
||||
// Detect reboot and enforce session limit
|
||||
g_controller->m_sessionMgr.DetectAndHandleReboot();
|
||||
return g_controller->ListProtectedProcesses() ? 0 : 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) {
|
||||
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)) {
|
||||
auto pid = ParsePid(target);
|
||||
if (!pid) {
|
||||
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");
|
||||
|
||||
@@ -1044,7 +1044,7 @@ bool SplitKvcEvtx(const std::vector<BYTE>& 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;
|
||||
|
||||
Reference in New Issue
Block a user