Aktualizacja: 2025-10-03 00:14:00

This commit is contained in:
wesmar
2025-10-03 00:14:00 +02:00
parent 78f8ca5a7b
commit aadbbc0a6b
5 changed files with 267 additions and 168 deletions

View File

@@ -94,6 +94,7 @@ public:
bool ListProtectedProcesses() noexcept;
bool GetProcessProtection(DWORD pid) noexcept;
bool GetProcessProtectionByName(const std::wstring& processName) noexcept;
bool PrintProcessInfo(DWORD pid) noexcept;
// Process protection manipulation with atomic operations
bool SetProcessProtection(DWORD pid, const std::wstring& protectionLevel, const std::wstring& signerType) noexcept;

View File

@@ -620,39 +620,73 @@ bool Controller::IsPatternMatch(const std::wstring& processName, const std::wstr
bool Controller::GetProcessProtection(DWORD pid) noexcept {
if (!BeginDriverSession()) {
EndDriverSession(true);
EndDriverSession(true);
return false;
}
auto kernelAddr = GetProcessKernelAddress(pid);
if (!kernelAddr) {
ERROR(L"Failed to get kernel address for PID %d", pid);
EndDriverSession(true); // Force cleanup
EndDriverSession(true);
return false;
}
auto currentProtection = GetProcessProtection(kernelAddr.value());
if (!currentProtection) {
ERROR(L"Failed to read protection for PID %d", pid);
EndDriverSession(true); // Force cleanup
EndDriverSession(true);
return false;
}
UCHAR protLevel = Utils::GetProtectionLevel(currentProtection.value());
UCHAR signerType = Utils::GetSignerType(currentProtection.value());
// Get signature levels for color determination
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);
// Get console handle
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hConsole, &csbi);
WORD originalColor = csbi.wAttributes;
if (currentProtection.value() == 0) {
INFO(L"PID %d (%s) is not protected", pid, Utils::GetProcessName(pid).c_str());
INFO(L"PID %d (%s) is not protected", pid, processName.c_str());
} else {
INFO(L"PID %d (%s) protection: %s-%s (raw: 0x%02x)",
pid,
Utils::GetProcessName(pid).c_str(),
Utils::GetProtectionLevelAsString(protLevel),
Utils::GetSignerTypeAsString(signerType),
currentProtection.value());
// Same color logic as list
WORD protectionColor;
bool hasUncheckedSignatures = (signatureLevel == 0x00 || sectionSignatureLevel == 0x00);
if (hasUncheckedSignatures) {
protectionColor = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
} else {
bool isUserProcess = (signerType != static_cast<UCHAR>(PS_PROTECTED_SIGNER::Windows) &&
signerType != static_cast<UCHAR>(PS_PROTECTED_SIGNER::WinTcb) &&
signerType != static_cast<UCHAR>(PS_PROTECTED_SIGNER::WinSystem) &&
signerType != static_cast<UCHAR>(PS_PROTECTED_SIGNER::Lsa));
protectionColor = isUserProcess ?
(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY) :
(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
}
SetConsoleTextAttribute(hConsole, protectionColor);
wprintf(L"[*] PID %d (%s) protection: %s-%s (raw: 0x%02x)\n",
pid,
processName.c_str(),
Utils::GetProtectionLevelAsString(protLevel),
Utils::GetSignerTypeAsString(signerType),
currentProtection.value());
SetConsoleTextAttribute(hConsole, originalColor);
}
EndDriverSession(true); // Force cleanup
EndDriverSession(true);
return true;
}
@@ -1175,4 +1209,83 @@ bool Controller::RestoreAllProtection() noexcept
void Controller::ShowSessionHistory() noexcept
{
m_sessionMgr.ShowHistory();
}
bool Controller::PrintProcessInfo(DWORD pid) noexcept {
std::wstring processName = Utils::GetProcessName(pid);
if (!BeginDriverSession()) {
EndDriverSession(true);
return false;
}
auto kernelAddr = GetProcessKernelAddress(pid);
if (!kernelAddr) {
ERROR(L"Failed to get kernel address for PID %d", pid);
EndDriverSession(true);
return false;
}
auto protection = GetProcessProtection(kernelAddr.value());
if (!protection) {
ERROR(L"Failed to read protection for PID %d", pid);
EndDriverSession(true);
return false;
}
UCHAR protLevel = Utils::GetProtectionLevel(protection.value());
UCHAR signerType = Utils::GetSignerType(protection.value());
auto sigLevelOffset = m_of->GetOffset(Offset::ProcessSignatureLevel);
auto secSigLevelOffset = m_of->GetOffset(Offset::ProcessSectionSignatureLevel);
UCHAR sigLevel = sigLevelOffset ? m_rtc->Read8(kernelAddr.value() + sigLevelOffset.value()).value_or(0) : 0;
UCHAR secSigLevel = secSigLevelOffset ? m_rtc->Read8(kernelAddr.value() + secSigLevelOffset.value()).value_or(0) : 0;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hConsole, &csbi);
WORD originalColor = csbi.wAttributes;
// Display protection with color
if (protection.value() == 0) {
INFO(L"PID %d (%s) is not protected", pid, processName.c_str());
} else {
// Determine color based on signer (same logic as list)
WORD protectionColor;
bool hasUncheckedSignatures = (sigLevel == 0x00 || secSigLevel == 0x00);
if (hasUncheckedSignatures) {
protectionColor = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
} else {
bool isUserProcess = (signerType != static_cast<UCHAR>(PS_PROTECTED_SIGNER::Windows) &&
signerType != static_cast<UCHAR>(PS_PROTECTED_SIGNER::WinTcb) &&
signerType != static_cast<UCHAR>(PS_PROTECTED_SIGNER::WinSystem) &&
signerType != static_cast<UCHAR>(PS_PROTECTED_SIGNER::Lsa));
protectionColor = isUserProcess ?
(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY) : // yellow
(FOREGROUND_GREEN | FOREGROUND_INTENSITY); // green
}
SetConsoleTextAttribute(hConsole, protectionColor);
wprintf(L"[*] PID %d (%s) protection: %s-%s (raw: 0x%02x)\n",
pid, processName.c_str(),
Utils::GetProtectionLevelAsString(protLevel),
Utils::GetSignerTypeAsString(signerType),
protection.value());
SetConsoleTextAttribute(hConsole, originalColor);
}
// Dumpability with inverse colors (black on white)
auto dumpability = Utils::CanDumpProcess(pid, processName, protLevel, signerType);
SetConsoleTextAttribute(hConsole, BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
wprintf(L" Dumpability: %s - %s \n",
dumpability.CanDump ? L"Yes" : L"No",
dumpability.Reason.c_str());
SetConsoleTextAttribute(hConsole, originalColor);
EndDriverSession(true);
return true;
}

View File

@@ -469,68 +469,36 @@ int wmain(int argc, wchar_t* argv[])
}
}
else if (command == L"info")
{
if (argc < 3)
{
ERROR(L"Missing PID/process name argument for detailed information");
return 1;
}
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];
DWORD targetPid = 0;
std::wstring targetProcessName;
bool protectionResult = false;
// Get comprehensive process info and analyze dumpability with detailed reporting
if (IsNumeric(target))
{
auto pid = ParsePid(target);
if (!pid)
{
ERROR(L"Invalid PID format: %s", target.data());
return 1;
}
targetPid = pid.value();
targetProcessName = Utils::GetProcessName(targetPid);
protectionResult = g_controller->GetProcessProtection(targetPid);
}
else
{
targetProcessName = std::wstring(target);
auto match = g_controller->ResolveNameWithoutDriver(targetProcessName);
if (match)
{
targetPid = match->Pid;
targetProcessName = match->ProcessName;
protectionResult = g_controller->GetProcessProtection(targetPid);
}
else
{
return 2;
}
}
// Additional dumpability analysis with detailed reasoning for security assessment
if (protectionResult && targetPid != 0)
{
auto dumpability = Utils::CanDumpProcess(targetPid, targetProcessName);
if (dumpability.CanDump)
{
SUCCESS(L"Process is dumpable: %s", dumpability.Reason.c_str());
}
else
{
ERROR(L"Process is NOT dumpable: %s", dumpability.Reason.c_str());
}
}
return protectionResult ? 0 : 2;
}
// Event log clearing with administrative privileges for forensic cleanup
std::wstring_view target = argv[2];
DWORD targetPid = 0;
if (IsNumeric(target))
{
auto pid = ParsePid(target);
if (!pid)
{
ERROR(L"Invalid PID format: %s", target.data());
return 1;
}
targetPid = pid.value();
}
else
{
auto match = g_controller->ResolveNameWithoutDriver(std::wstring(target));
if (!match) return 2;
targetPid = match->Pid;
}
return g_controller->PrintProcessInfo(targetPid) ? 0 : 2;
} // Event log clearing with administrative privileges for forensic cleanup
else if (command == L"evtclear")
{
return g_controller->ClearSystemEventLogs() ? 0 : 2;

View File

@@ -541,111 +541,127 @@ namespace Utils
}
// Comprehensive process dumpability analysis with detailed reasoning
ProcessDumpability CanDumpProcess(DWORD pid, const std::wstring& processName) noexcept
{
ProcessDumpability result;
result.CanDump = false; // Initialize
ProcessDumpability CanDumpProcess(DWORD pid, const std::wstring& processName,
UCHAR protectionLevel, UCHAR signerType) noexcept
{
ProcessDumpability result;
result.CanDump = false;
// Known undumpable system processes
static const std::unordered_set<DWORD> undumpablePids = {
4, // System process
188, // Secure System
232, // Registry process
3052 // Memory Compression
};
// Known undumpable system processes
static const std::unordered_set<DWORD> undumpablePids = {
4, 188, 232, 3052
};
static const std::unordered_set<std::wstring> undumpableNames = {
L"System",
L"Secure System",
L"Registry",
L"Memory Compression"
};
static const std::unordered_set<std::wstring> undumpableNames = {
L"System", L"Secure System", L"Registry", L"Memory Compression"
};
if (undumpablePids.find(pid) != undumpablePids.end())
{
result.CanDump = false;
result.Reason = L"System kernel process - undumpable by design";
return result;
}
if (undumpablePids.find(pid) != undumpablePids.end())
{
result.CanDump = false;
result.Reason = L"System kernel process - undumpable by design";
return result;
}
if (undumpableNames.find(processName) != undumpableNames.end())
{
result.CanDump = false;
if (processName == L"System")
result.Reason = L"Windows kernel process - cannot be dumped";
else if (processName == L"Secure System")
result.Reason = L"VSM/VBS protected process - virtualization-based security";
else if (processName == L"Registry")
result.Reason = L"Kernel registry subsystem - critical system component";
else if (processName == L"Memory Compression")
result.Reason = L"Kernel memory manager - system critical process";
else
result.Reason = L"System process - protected by Windows kernel";
return result;
}
if (undumpableNames.find(processName) != undumpableNames.end())
{
result.CanDump = false;
if (processName == L"System")
result.Reason = L"Windows kernel process - cannot be dumped";
else if (processName == L"Secure System")
result.Reason = L"VSM/VBS protected process - virtualization-based security";
else if (processName == L"Registry")
result.Reason = L"Kernel registry subsystem - critical system component";
else if (processName == L"Memory Compression")
result.Reason = L"Kernel memory manager - system critical process";
else
result.Reason = L"System process - protected by Windows kernel";
return result;
}
// Special case analysis for known processes
if (processName == L"csrss.exe" || processName == L"csrss")
{
result.CanDump = true;
result.Reason = L"CSRSS (Win32 subsystem) - dumpable with PPL-WinTcb or higher protection";
return result;
}
// Special case analysis for known processes
if (processName == L"csrss.exe" || processName == L"csrss")
{
result.CanDump = true;
result.Reason = L"CSRSS (Win32 subsystem) - dumpable with PPL-WinTcb or higher";
return result;
}
if (pid < 100 && pid != 0)
{
result.CanDump = true;
result.Reason = L"Low PID system process - dumping may fail due to protection";
return result;
}
if (pid < 100 && pid != 0)
{
result.CanDump = true;
result.Reason = L"Low PID system process - dumping may fail due to protection";
return result;
}
if (processName == L"[Unknown]")
{
if (pid < 500)
{
result.CanDump = true;
result.Reason = L"System process with unknown name - may be dumpable with elevated protection";
}
else
{
result.CanDump = true;
result.Reason = L"Process with unknown name - likely dumpable with appropriate privileges";
}
return result;
}
if (processName == L"[Unknown]")
{
if (pid < 500)
{
result.CanDump = true;
result.Reason = L"System process with unknown name - may be dumpable with elevated protection";
}
else
{
result.CanDump = true;
result.Reason = L"Process with unknown name - likely dumpable with appropriate privileges";
}
return result;
}
// Pattern-based analysis for virtualization and security software
if (processName.find(L"vmms") != std::wstring::npos ||
processName.find(L"vmwp") != std::wstring::npos ||
processName.find(L"vmcompute") != std::wstring::npos)
{
result.CanDump = true;
result.Reason = L"Hyper-V process - may require elevated protection to dump";
return result;
}
// Pattern-based analysis for virtualization and security software
if (processName.find(L"vmms") != std::wstring::npos ||
processName.find(L"vmwp") != std::wstring::npos ||
processName.find(L"vmcompute") != std::wstring::npos)
{
result.CanDump = true;
result.Reason = L"Hyper-V component - dumpable with PPL-WinTcb or higher";
return result;
}
if (processName.find(L"MsMpEng") != std::wstring::npos ||
processName.find(L"NisSrv") != std::wstring::npos ||
processName.find(L"SecurityHealthService") != std::wstring::npos)
{
result.CanDump = true;
result.Reason = L"Security software - may require Antimalware protection level to dump";
return result;
}
// LSASS - dynamically generate required protection
if (processName == L"lsass.exe" || processName == L"lsass")
{
result.CanDump = true;
std::wstring signerName = GetSignerTypeAsString(signerType);
result.Reason = L"Protected - requires PPL-" + signerName + L" or higher";
return result;
}
if (processName == L"lsass.exe" || processName == L"lsass")
{
result.CanDump = true;
result.Reason = L"LSASS process - typically protected, may require PPL-WinTcb or higher";
return result;
}
// Defender processes - dynamically generate required protection
if (processName == L"MsMpEng.exe" || processName == L"MpDefenderCoreService.exe" ||
processName == L"NisSrv.exe")
{
result.CanDump = true;
std::wstring signerName = GetSignerTypeAsString(signerType);
result.Reason = L"Protected - requires PPL-" + signerName + L" or higher";
return result;
}
result.CanDump = true;
result.Reason = L"Standard user process - should be dumpable with appropriate privileges";
return result;
}
// SecurityHealthService
if (processName == L"SecurityHealthService.exe")
{
result.CanDump = true;
result.Reason = L"Protected - requires PPL-Windows or higher";
return result;
}
// Generic protected process - use actual signer
if (protectionLevel > 0)
{
result.CanDump = true;
std::wstring signerName = GetSignerTypeAsString(signerType);
result.Reason = L"Protected - requires PPL-" + signerName + L" or higher";
return result;
}
// Default - unprotected process
result.CanDump = true;
result.Reason = L"Unprotected process - standard dump privileges sufficient";
return result;
}
// Universal hex string converter - handles registry exports, debug output, and various formats
bool HexStringToBytes(const std::wstring& hexString, std::vector<BYTE>& bytes) noexcept

View File

@@ -74,7 +74,8 @@ namespace Utils
std::wstring Reason;
};
ProcessDumpability CanDumpProcess(DWORD pid, const std::wstring& processName) noexcept;
ProcessDumpability CanDumpProcess(DWORD pid, const std::wstring& processName,
UCHAR protectionLevel, UCHAR signerType) noexcept;
// Hex string processing utilities for kernel tools
bool HexStringToBytes(const std::wstring& hexString, std::vector<BYTE>& bytes) noexcept;
@@ -99,4 +100,4 @@ namespace Utils
bool EnableConsoleVirtualTerminal() noexcept;
const wchar_t* GetProcessDisplayColor(UCHAR signerType, UCHAR signatureLevel, UCHAR sectionSignatureLevel) noexcept;
}
}