2016-07-21 23:02:31 +00:00
# include "PsMonitor.h"
# include "ExcludeList.h"
# include "Helper.h"
# include "PsTable.h"
2016-08-27 20:18:54 +00:00
# include "PsRules.h"
2016-12-12 20:40:35 +00:00
# include "Driver.h"
2016-12-18 18:11:10 +00:00
# include "Configs.h"
2016-08-27 20:18:54 +00:00
2017-02-02 22:55:19 +00:00
# define PSMON_ALLOC_TAG 'nMsP'
2016-08-27 20:18:54 +00:00
# define PROCESS_QUERY_LIMITED_INFORMATION 0x1000
# define SYSTEM_PROCESS_ID (HANDLE)4
2016-07-21 23:02:31 +00:00
2016-10-10 21:37:28 +00:00
BOOLEAN g_psMonitorInited = FALSE ;
2016-07-21 23:02:31 +00:00
PVOID g_obRegCallback = NULL ;
OB_OPERATION_REGISTRATION g_regOperation [ 2 ] ;
OB_CALLBACK_REGISTRATION g_regCallback ;
2016-08-27 20:18:54 +00:00
PsRulesContext g_excludeProcessRules ;
PsRulesContext g_protectProcessRules ;
2021-07-25 20:15:08 +00:00
PsRulesContext g_hideProcessRules ;
2016-07-21 23:02:31 +00:00
2021-07-28 18:54:03 +00:00
FAST_MUTEX g_processTableLock ;
KGUARDED_MUTEX g_activeProcListLock ;
2016-10-18 21:28:55 +00:00
2016-10-10 21:37:28 +00:00
typedef struct _ProcessListEntry {
LPCWSTR path ;
ULONG inherit ;
} ProcessListEntry , * PProcessListEntry ;
2016-09-04 19:00:48 +00:00
// Use this variable for hard code full path to applications that can see hidden objects
2016-09-05 19:30:18 +00:00
// For instance: L"\\Device\\HarddiskVolume1\\Windows\\System32\\calc.exe",
2016-09-04 19:00:48 +00:00
// Notice: this array should be NULL terminated
2016-10-10 21:37:28 +00:00
CONST ProcessListEntry g_excludeProcesses [ ] = {
2016-12-18 18:11:10 +00:00
{ NULL , PsRuleTypeWithoutInherit }
2016-07-21 23:02:31 +00:00
} ;
2016-09-04 19:00:48 +00:00
// Use this variable for hard code full path to applications that will be protected
2016-09-05 19:30:18 +00:00
// For instance: L"\\Device\\HarddiskVolume1\\Windows\\System32\\cmd.exe",
2016-09-04 19:00:48 +00:00
// Notice: this array should be NULL terminated
2016-10-10 21:37:28 +00:00
CONST ProcessListEntry g_protectProcesses [ ] = {
2016-12-18 18:11:10 +00:00
{ NULL , PsRuleTypeWithoutInherit }
2016-07-21 23:02:31 +00:00
} ;
2016-10-10 21:37:28 +00:00
# define CSRSS_PAHT_BUFFER_SIZE 256
UNICODE_STRING g_csrssPath ;
WCHAR g_csrssPathBuffer [ CSRSS_PAHT_BUFFER_SIZE ] ;
2021-07-28 18:54:03 +00:00
_Must_inspect_result_
_IRQL_requires_max_ ( APC_LEVEL )
NTKERNELAPI
NTSTATUS
PsLookupProcessByProcessId (
_In_ HANDLE ProcessId ,
_Outptr_ PEPROCESS * Process
) ;
2016-10-10 21:37:28 +00:00
BOOLEAN CheckProtectedOperation ( HANDLE Source , HANDLE Destination )
{
ProcessTableEntry srcInfo , destInfo ;
2016-10-18 21:28:55 +00:00
BOOLEAN result ;
2016-10-10 21:37:28 +00:00
if ( Source = = Destination )
return FALSE ;
2016-10-18 21:28:55 +00:00
srcInfo . processId = Source ;
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
result = GetProcessInProcessTable ( & srcInfo ) ;
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( ! result )
2016-10-10 21:37:28 +00:00
return FALSE ;
2016-10-18 21:28:55 +00:00
destInfo . processId = Destination ;
// Spinlock is locked once for both Get\Update process table functions
// because we want to prevent situations when another thread can change
// any state of process beetwen get and update functions on this place
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( ! GetProcessInProcessTable ( & destInfo ) )
{
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-10 21:37:28 +00:00
return FALSE ;
2016-10-18 21:28:55 +00:00
}
2016-10-10 21:37:28 +00:00
// Not-inited process can open any process (parent, csrss, etc)
if ( ! destInfo . inited )
{
2016-10-18 21:28:55 +00:00
result = TRUE ;
2016-10-10 21:37:28 +00:00
// Update if source is subsystem and destination isn't inited
if ( srcInfo . subsystem )
{
destInfo . inited = TRUE ;
if ( ! UpdateProcessInProcessTable ( & destInfo ) )
2016-10-18 21:28:55 +00:00
result = FALSE ;
2016-10-10 21:37:28 +00:00
}
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( ! result )
2018-12-02 21:56:39 +00:00
LogWarning ( " Warning, can't update initial state for process: %p " , destInfo . processId ) ;
2016-10-18 21:28:55 +00:00
2016-10-10 21:37:28 +00:00
return FALSE ;
}
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
2016-10-10 21:37:28 +00:00
if ( ! destInfo . protected )
return FALSE ;
if ( srcInfo . protected )
return FALSE ;
if ( srcInfo . subsystem )
return FALSE ;
return TRUE ;
}
2016-07-21 23:02:31 +00:00
OB_PREOP_CALLBACK_STATUS ProcessPreCallback ( PVOID RegistrationContext , POB_PRE_OPERATION_INFORMATION OperationInformation )
{
UNREFERENCED_PARAMETER ( RegistrationContext ) ;
2016-12-12 20:40:35 +00:00
if ( ! IsDriverEnabled ( ) )
return OB_PREOP_SUCCESS ;
2016-07-21 23:02:31 +00:00
if ( OperationInformation - > KernelHandle )
return OB_PREOP_SUCCESS ;
2016-09-19 20:20:30 +00:00
2018-12-02 21:56:39 +00:00
LogInfo ( " Process object operation, destPid:%d, srcTid:%d, oper: %s, space: %s " ,
PsGetProcessId ( OperationInformation - > Object ) , PsGetCurrentThreadId ( ) ,
( OperationInformation - > Operation = = OB_OPERATION_HANDLE_CREATE ? " create " : " dup " ) ,
( OperationInformation - > KernelHandle ? " kernel " : " user " )
) ;
2016-07-21 23:02:31 +00:00
2016-10-10 21:37:28 +00:00
if ( ! CheckProtectedOperation ( PsGetCurrentProcessId ( ) , PsGetProcessId ( OperationInformation - > Object ) ) )
2016-07-21 23:02:31 +00:00
{
2021-07-28 22:00:14 +00:00
LogInfo ( " Allow protected process access from %Iu to %Iu " , ( ULONG_PTR ) PsGetCurrentProcessId ( ) , ( ULONG_PTR ) PsGetProcessId ( OperationInformation - > Object ) ) ;
2016-07-21 23:02:31 +00:00
return OB_PREOP_SUCCESS ;
}
2021-07-28 22:00:14 +00:00
LogTrace ( " Disallow protected process access from %Iu to %Iu " , ( ULONG_PTR ) PsGetCurrentProcessId ( ) , ( ULONG_PTR ) PsGetProcessId ( OperationInformation - > Object ) ) ;
2016-07-21 23:02:31 +00:00
if ( OperationInformation - > Operation = = OB_OPERATION_HANDLE_CREATE )
OperationInformation - > Parameters - > CreateHandleInformation . DesiredAccess = ( SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION ) ;
else
OperationInformation - > Parameters - > DuplicateHandleInformation . DesiredAccess = ( SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION ) ;
return OB_PREOP_SUCCESS ;
}
OB_PREOP_CALLBACK_STATUS ThreadPreCallback ( PVOID RegistrationContext , POB_PRE_OPERATION_INFORMATION OperationInformation )
{
UNREFERENCED_PARAMETER ( RegistrationContext ) ;
2016-12-12 20:40:35 +00:00
if ( ! IsDriverEnabled ( ) )
return OB_PREOP_SUCCESS ;
2016-07-21 23:02:31 +00:00
if ( OperationInformation - > KernelHandle )
return OB_PREOP_SUCCESS ;
2021-07-28 22:00:14 +00:00
LogInfo ( " Thread object operation, destPid:%Iu, destTid:%Iu, srcPid:%Iu, oper:%s, space:%s " ,
2021-07-04 22:30:08 +00:00
( ULONG_PTR ) PsGetThreadProcessId ( OperationInformation - > Object ) ,
( ULONG_PTR ) PsGetThreadId ( OperationInformation - > Object ) ,
( ULONG_PTR ) PsGetCurrentProcessId ( ) ,
2018-12-02 21:56:39 +00:00
( OperationInformation - > Operation = = OB_OPERATION_HANDLE_CREATE ? " create " : " dup " ) ,
( OperationInformation - > KernelHandle ? " kernel " : " user " )
) ;
2016-07-21 23:02:31 +00:00
2018-12-19 23:53:28 +00:00
if ( ! CheckProtectedOperation ( PsGetCurrentProcessId ( ) , PsGetThreadProcessId ( OperationInformation - > Object ) ) )
2016-07-21 23:02:31 +00:00
{
2021-07-28 22:00:14 +00:00
LogInfo ( " Allow protected thread access from %Iu to %Iu " , ( ULONG_PTR ) PsGetCurrentProcessId ( ) , ( ULONG_PTR ) PsGetThreadProcessId ( OperationInformation - > Object ) ) ;
2016-07-21 23:02:31 +00:00
return OB_PREOP_SUCCESS ;
}
2021-07-28 22:00:14 +00:00
LogTrace ( " Disallow protected thread access from %Iu to %Iu " , ( ULONG_PTR ) PsGetCurrentProcessId ( ) , ( ULONG_PTR ) PsGetThreadProcessId ( OperationInformation - > Object ) ) ;
2016-07-21 23:02:31 +00:00
if ( OperationInformation - > Operation = = OB_OPERATION_HANDLE_CREATE )
OperationInformation - > Parameters - > CreateHandleInformation . DesiredAccess = ( SYNCHRONIZE | THREAD_QUERY_LIMITED_INFORMATION ) ;
else
OperationInformation - > Parameters - > DuplicateHandleInformation . DesiredAccess = ( SYNCHRONIZE | THREAD_QUERY_LIMITED_INFORMATION ) ;
return OB_PREOP_SUCCESS ;
}
VOID CheckProcessFlags ( PProcessTableEntry Entry , PCUNICODE_STRING ImgPath , HANDLE ParentId )
{
ProcessTableEntry lookup ;
2016-08-27 20:18:54 +00:00
ULONG inheritType ;
2016-10-18 21:28:55 +00:00
BOOLEAN result ;
2016-08-27 20:18:54 +00:00
2016-07-21 23:02:31 +00:00
RtlZeroMemory ( & lookup , sizeof ( lookup ) ) ;
2016-10-10 21:37:28 +00:00
Entry - > inited = ( ! g_psMonitorInited ? TRUE : FALSE ) ;
2021-07-24 12:30:01 +00:00
if ( Entry - > processId = = SYSTEM_PROCESS_ID )
2017-02-18 13:39:08 +00:00
Entry - > subsystem = TRUE ;
else
2016-12-27 21:31:00 +00:00
Entry - > subsystem = RtlEqualUnicodeString ( & g_csrssPath , ImgPath , TRUE ) ;
2016-10-10 21:37:28 +00:00
2016-07-21 23:02:31 +00:00
// Check exclude flag
2016-08-27 20:18:54 +00:00
Entry - > excluded = FALSE ;
Entry - > inheritExclusion = PsRuleTypeWithoutInherit ;
if ( FindInheritanceInPsRuleList ( g_excludeProcessRules , ImgPath , & inheritType ) )
2016-07-21 23:02:31 +00:00
{
Entry - > excluded = TRUE ;
2016-08-27 20:18:54 +00:00
Entry - > inheritExclusion = inheritType ;
2016-07-21 23:02:31 +00:00
}
else if ( ParentId ! = 0 )
{
lookup . processId = ParentId ;
2016-10-18 21:28:55 +00:00
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
result = GetProcessInProcessTable ( & lookup ) ;
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( result )
2016-08-27 20:18:54 +00:00
{
if ( lookup . inheritExclusion = = PsRuleTypeInherit )
{
Entry - > excluded = TRUE ;
Entry - > inheritExclusion = PsRuleTypeInherit ;
}
else if ( lookup . inheritExclusion = = PsRuleTypeInheritOnce )
{
Entry - > excluded = TRUE ;
Entry - > inheritExclusion = PsRuleTypeWithoutInherit ;
}
}
2016-07-21 23:02:31 +00:00
}
// Check protected flag
2016-08-27 20:18:54 +00:00
Entry - > protected = FALSE ;
Entry - > inheritProtection = PsRuleTypeWithoutInherit ;
if ( FindInheritanceInPsRuleList ( g_protectProcessRules , ImgPath , & inheritType ) )
2016-07-21 23:02:31 +00:00
{
Entry - > protected = TRUE ;
2016-08-27 20:18:54 +00:00
Entry - > inheritProtection = inheritType ;
2016-07-21 23:02:31 +00:00
}
else if ( ParentId ! = 0 )
{
2016-08-27 20:18:54 +00:00
lookup . processId = ParentId ;
2016-10-18 21:28:55 +00:00
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
result = GetProcessInProcessTable ( & lookup ) ;
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( result )
2016-07-21 23:02:31 +00:00
{
2016-08-27 20:18:54 +00:00
if ( lookup . inheritProtection = = PsRuleTypeInherit )
{
Entry - > protected = TRUE ;
Entry - > inheritProtection = PsRuleTypeInherit ;
}
else if ( lookup . inheritProtection = = PsRuleTypeInheritOnce )
{
Entry - > protected = TRUE ;
Entry - > inheritProtection = PsRuleTypeWithoutInherit ;
}
2016-07-21 23:02:31 +00:00
}
}
2021-07-25 20:15:08 +00:00
// Check hidden flag
Entry - > hidden = FALSE ;
Entry - > inheritStealth = PsRuleTypeWithoutInherit ;
if ( FindInheritanceInPsRuleList ( g_hideProcessRules , ImgPath , & inheritType ) )
{
Entry - > hidden = TRUE ;
Entry - > inheritStealth = inheritType ;
}
else if ( ParentId ! = 0 )
{
lookup . processId = ParentId ;
ExAcquireFastMutex ( & g_processTableLock ) ;
result = GetProcessInProcessTable ( & lookup ) ;
ExReleaseFastMutex ( & g_processTableLock ) ;
if ( result )
{
if ( lookup . inheritStealth = = PsRuleTypeInherit )
{
Entry - > hidden = TRUE ;
Entry - > inheritStealth = PsRuleTypeInherit ;
}
else if ( lookup . inheritStealth = = PsRuleTypeInheritOnce )
{
Entry - > hidden = TRUE ;
Entry - > inheritStealth = PsRuleTypeWithoutInherit ;
}
}
}
2016-07-21 23:02:31 +00:00
}
2021-07-28 18:54:03 +00:00
//TODO:
// - Find an offset on driver initialization step
BOOLEAN FindActiveProcessLinksOffset ( PEPROCESS Process , ULONG * Offset )
{
# ifdef _M_AMD64
ULONG peak = 0x300 ;
# else
ULONG peak = 0x150 ;
# endif
HANDLE * ptr = ( HANDLE * ) Process ;
HANDLE processId = PsGetProcessId ( Process ) ;
ULONG i ;
// EPROCESS ActiveProcessLinks field is next to UniqueProcessId
// ...
// + 0x0b4 UniqueProcessId : Ptr32 Void
// + 0x0b8 ActiveProcessLinks : _LIST_ENTRY
// + 0x0c0 Flags2 : Uint4B
// ...
for ( i = 10 ; i < peak / sizeof ( HANDLE ) ; i + + )
{
if ( ptr [ i ] = = processId )
{
* Offset = sizeof ( HANDLE ) * ( i + 1 ) ;
2021-07-28 22:00:14 +00:00
LogInfo ( " EPROCESS->ActiveProcessList offset is %x " , * Offset ) ;
2021-07-28 18:54:03 +00:00
return TRUE ;
}
}
return FALSE ;
}
VOID UnlinkProcessFromList ( PLIST_ENTRY Current )
{ // https://github.com/landhb/HideProcess/blob/master/driver/hideprocess.c
PLIST_ENTRY Previous , Next ;
Previous = ( Current - > Blink ) ;
Next = ( Current - > Flink ) ;
// Loop over self (connect previous with next)
Previous - > Flink = Next ;
Next - > Blink = Previous ;
// Re-write the current LIST_ENTRY to point to itself (avoiding BSOD)
Current - > Blink = ( PLIST_ENTRY ) & Current - > Flink ;
Current - > Flink = ( PLIST_ENTRY ) & Current - > Flink ;
}
VOID UnlinkProcessFromActiveProcessLinks ( PEPROCESS Process )
{
ULONG eprocListOffset = 0 ;
PLIST_ENTRY CurrentList = NULL ;
if ( ! FindActiveProcessLinksOffset ( Process , & eprocListOffset ) )
{
LogError ( " Error, can't find active process list offset, eprocess:%p " , Process ) ;
return ;
}
CurrentList = ( PLIST_ENTRY ) ( ( ULONG_PTR ) Process + eprocListOffset ) ;
// We use g_activeProcListLock to sync our modification inside hidden and raise
// IRQL to disable special APC's because we want to minimize a BSOD chance because
// of lack of the ActiveProcessLinks syncronization
KeAcquireGuardedMutex ( & g_activeProcListLock ) ;
UnlinkProcessFromList ( CurrentList ) ;
KeReleaseGuardedMutex ( & g_activeProcListLock ) ;
}
VOID LinkProcessFromList ( PLIST_ENTRY Current , PLIST_ENTRY Target )
{
PLIST_ENTRY Previous , Next ;
if ( Current - > Blink ! = Current - > Flink )
return ;
Previous = Target ;
Next = Target - > Flink ;
Current - > Blink = Previous ;
Current - > Flink = Next ;
Previous - > Flink = ( PLIST_ENTRY ) & Current - > Flink ;
Next - > Blink = ( PLIST_ENTRY ) & Current - > Flink ;
}
VOID LinkProcessToActiveProcessLinks ( PEPROCESS Process )
{
ULONG eprocListOffset = 0 ;
PLIST_ENTRY CurrentList = NULL , TargetList = NULL ;
PEPROCESS Target ;
NTSTATUS status ;
if ( ! FindActiveProcessLinksOffset ( Process , & eprocListOffset ) )
{
LogWarning ( " Warning, can't find active process list offset, eprocess:%p " , Process ) ;
return ;
}
status = PsLookupProcessByProcessId ( SYSTEM_PROCESS_ID , & Target ) ;
if ( ! NT_SUCCESS ( status ) )
{
LogWarning ( " Warning, can't find active system process " ) ;
return ;
}
CurrentList = ( PLIST_ENTRY ) ( ( ULONG_PTR ) Process + eprocListOffset ) ;
TargetList = ( PLIST_ENTRY ) ( ( ULONG_PTR ) Target + eprocListOffset ) ;
KeAcquireGuardedMutex ( & g_activeProcListLock ) ;
LinkProcessFromList ( CurrentList , TargetList ) ;
KeReleaseGuardedMutex ( & g_activeProcListLock ) ;
2021-07-28 22:00:14 +00:00
ObDereferenceObject ( Target ) ;
2021-07-28 18:54:03 +00:00
}
2016-07-21 23:02:31 +00:00
VOID CreateProcessNotifyCallback ( PEPROCESS Process , HANDLE ProcessId , PPS_CREATE_NOTIFY_INFO CreateInfo )
{
ProcessTableEntry entry ;
2016-10-18 21:28:55 +00:00
BOOLEAN result ;
2016-07-21 23:02:31 +00:00
UNREFERENCED_PARAMETER ( Process ) ;
if ( CreateInfo )
2018-12-02 21:56:39 +00:00
LogInfo (
2021-07-28 22:00:14 +00:00
" Created process, pid:%p, srcPid:%p, srcTid:%p, image:%wZ " ,
2018-12-02 21:56:39 +00:00
ProcessId ,
PsGetCurrentProcessId ( ) ,
PsGetCurrentThreadId ( ) ,
CreateInfo - > ImageFileName
) ;
2016-07-21 23:02:31 +00:00
else
2018-12-02 21:56:39 +00:00
LogInfo (
2021-07-28 22:00:14 +00:00
" Destroyed process, pid:%p, srcPid:%p, srcTid:%p " ,
2018-12-02 21:56:39 +00:00
ProcessId ,
PsGetCurrentProcessId ( ) ,
PsGetCurrentThreadId ( )
) ;
2016-07-21 23:02:31 +00:00
RtlZeroMemory ( & entry , sizeof ( entry ) ) ;
entry . processId = ProcessId ;
if ( CreateInfo )
{
const USHORT maxBufSize = CreateInfo - > ImageFileName - > Length + NORMALIZE_INCREAMENT ;
UNICODE_STRING normalized ;
NTSTATUS status ;
2017-02-02 22:55:19 +00:00
normalized . Buffer = ( PWCH ) ExAllocatePoolWithTag ( PagedPool , maxBufSize , PSMON_ALLOC_TAG ) ;
2016-07-21 23:02:31 +00:00
normalized . Length = 0 ;
normalized . MaximumLength = maxBufSize ;
if ( ! normalized . Buffer )
{
2018-12-02 21:56:39 +00:00
LogWarning ( " Error, can't allocate buffer " ) ;
2016-07-21 23:02:31 +00:00
return ;
}
status = NormalizeDevicePath ( CreateInfo - > ImageFileName , & normalized ) ;
if ( ! NT_SUCCESS ( status ) )
{
2018-12-02 21:56:39 +00:00
LogWarning ( " Error, path normalization failed with code:%08x, path:%wZ " , status , CreateInfo - > ImageFileName ) ;
2017-02-02 22:55:19 +00:00
ExFreePoolWithTag ( normalized . Buffer , PSMON_ALLOC_TAG ) ;
2016-07-21 23:02:31 +00:00
return ;
}
2016-12-10 11:22:49 +00:00
CheckProcessFlags ( & entry , & normalized , PsGetCurrentProcessId ( ) /*CreateInfo->ParentProcessId*/ ) ;
2016-07-21 23:02:31 +00:00
if ( entry . excluded )
2018-12-02 21:56:39 +00:00
LogTrace ( " Excluded process:%p " , ProcessId ) ;
2016-07-21 23:02:31 +00:00
if ( entry . protected )
2018-12-02 21:56:39 +00:00
LogTrace ( " Protected process:%p " , ProcessId ) ;
2016-07-21 23:02:31 +00:00
2021-07-28 18:54:03 +00:00
if ( entry . hidden )
{
LogTrace ( " Hidden process:%p " , ProcessId ) ;
if ( AddHiddenProcessToProcessTable ( Process ) )
UnlinkProcessFromActiveProcessLinks ( Process ) ;
else
LogWarning ( " Warning, can't hide a process %p " , ProcessId ) ;
}
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
result = AddProcessToProcessTable ( & entry ) ;
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( ! result )
2018-12-02 21:56:39 +00:00
LogWarning ( " Warning, can't add process(pid:%p) to process table " , ProcessId ) ;
2016-08-27 20:18:54 +00:00
2017-02-02 22:55:19 +00:00
ExFreePoolWithTag ( normalized . Buffer , PSMON_ALLOC_TAG ) ;
2016-07-21 23:02:31 +00:00
}
else
{
2021-07-28 18:54:03 +00:00
// We don't check is an operation successful or not to avoid extra CPU for looking a process
if ( ! RemoveHiddenProcessFromProcessTable ( Process ) )
LogTrace ( " Process %p isn't hidden " , ProcessId ) ;
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
result = RemoveProcessFromProcessTable ( & entry ) ;
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( ! result )
2018-12-02 21:56:39 +00:00
LogWarning ( " Warning, can't remove process(pid:%p) from process table " , ProcessId ) ;
2016-07-21 23:02:31 +00:00
}
}
BOOLEAN IsProcessExcluded ( HANDLE ProcessId )
{
ProcessTableEntry entry ;
2016-10-18 21:28:55 +00:00
BOOLEAN result ;
2016-07-21 23:02:31 +00:00
2017-02-18 13:39:08 +00:00
// Exclude system process because we don't want affect to kernel-mode threads
2021-07-24 12:30:01 +00:00
if ( ProcessId = = SYSTEM_PROCESS_ID )
2017-02-18 13:39:08 +00:00
return TRUE ;
2016-07-21 23:02:31 +00:00
entry . processId = ProcessId ;
2016-10-18 21:28:55 +00:00
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
result = GetProcessInProcessTable ( & entry ) ;
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( ! result )
2016-07-21 23:02:31 +00:00
return FALSE ;
2021-07-24 12:30:01 +00:00
return entry . excluded ;
2016-07-21 23:02:31 +00:00
}
BOOLEAN IsProcessProtected ( HANDLE ProcessId )
{
ProcessTableEntry entry ;
2016-10-18 21:28:55 +00:00
BOOLEAN result ;
2016-07-21 23:02:31 +00:00
entry . processId = ProcessId ;
2016-10-18 21:28:55 +00:00
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
result = GetProcessInProcessTable ( & entry ) ;
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( ! result )
2016-07-21 23:02:31 +00:00
return FALSE ;
return entry . protected ;
}
2016-12-18 18:11:10 +00:00
NTSTATUS ParsePsConfigEntry ( PUNICODE_STRING Entry , PUNICODE_STRING Path , PULONG Inherit )
{
USHORT inx , length = Entry - > Length / sizeof ( WCHAR ) ;
LPWSTR str = Entry - > Buffer ;
UNICODE_STRING command , template ;
RtlZeroMemory ( & command , sizeof ( command ) ) ;
for ( inx = 0 ; inx < length ; inx + + )
{
if ( str [ inx ] = = L ' ; ' )
{
command . Buffer = str + inx + 1 ;
command . Length = ( length - inx - 1 ) * sizeof ( WCHAR ) ;
command . MaximumLength = command . Length ;
break ;
}
}
if ( inx = = 0 )
return STATUS_NO_DATA_DETECTED ;
Path - > Buffer = Entry - > Buffer ;
Path - > Length = inx * sizeof ( WCHAR ) ;
Path - > MaximumLength = Path - > Length ;
RtlInitUnicodeString ( & template , L " none " ) ;
if ( RtlCompareUnicodeString ( & command , & template , TRUE ) = = 0 )
{
* Inherit = PsRuleTypeWithoutInherit ;
return STATUS_SUCCESS ;
}
RtlInitUnicodeString ( & template , L " always " ) ;
if ( RtlCompareUnicodeString ( & command , & template , TRUE ) = = 0 )
{
* Inherit = PsRuleTypeInherit ;
return STATUS_SUCCESS ;
}
RtlInitUnicodeString ( & template , L " once " ) ;
if ( RtlCompareUnicodeString ( & command , & template , TRUE ) = = 0 )
{
* Inherit = PsRuleTypeInheritOnce ;
return STATUS_SUCCESS ;
}
return STATUS_NOT_FOUND ;
}
2016-12-25 20:56:18 +00:00
VOID LoadProtectedRulesCallback ( PUNICODE_STRING Str , PVOID Params )
2016-12-18 18:11:10 +00:00
{
UNICODE_STRING path ;
ULONG inherit ;
PsRuleEntryId ruleId ;
2016-12-25 20:56:18 +00:00
UNREFERENCED_PARAMETER ( Params ) ;
if ( NT_SUCCESS ( ParsePsConfigEntry ( Str , & path , & inherit ) ) )
AddProtectedImage ( & path , inherit , FALSE , & ruleId ) ;
}
VOID LoadIgnoredRulesCallback ( PUNICODE_STRING Str , PVOID Params )
{
UNICODE_STRING path ;
ULONG inherit ;
PsRuleEntryId ruleId ;
UNREFERENCED_PARAMETER ( Params ) ;
2016-12-18 18:11:10 +00:00
if ( NT_SUCCESS ( ParsePsConfigEntry ( Str , & path , & inherit ) ) )
2016-12-25 20:56:18 +00:00
AddExcludedImage ( & path , inherit , FALSE , & ruleId ) ;
2016-12-18 18:11:10 +00:00
}
2016-07-21 23:02:31 +00:00
NTSTATUS InitializePsMonitor ( PDRIVER_OBJECT DriverObject )
{
const USHORT maxBufSize = 512 ;
NTSTATUS status ;
2016-10-10 21:37:28 +00:00
UNICODE_STRING str , normalized , csrss ;
2016-07-21 23:02:31 +00:00
UINT32 i ;
2016-08-27 20:18:54 +00:00
PsRuleEntryId ruleId ;
2016-07-21 23:02:31 +00:00
UNREFERENCED_PARAMETER ( DriverObject ) ;
2016-10-10 21:37:28 +00:00
// Set csrss path
RtlZeroMemory ( g_csrssPathBuffer , sizeof ( g_csrssPathBuffer ) ) ;
g_csrssPath . Buffer = g_csrssPathBuffer ;
g_csrssPath . Length = 0 ;
g_csrssPath . MaximumLength = sizeof ( g_csrssPathBuffer ) ;
RtlInitUnicodeString ( & csrss , L " \\ SystemRoot \\ System32 \\ csrss.exe " ) ;
status = NormalizeDevicePath ( & csrss , & g_csrssPath ) ;
if ( ! NT_SUCCESS ( status ) )
{
2018-12-02 21:56:39 +00:00
LogError ( " Error, subsystem path normalization failed with code:%08x " , status ) ;
2016-10-10 21:37:28 +00:00
return status ;
}
2018-12-02 21:56:39 +00:00
LogTrace ( " Subsystem path: %wZ " , & g_csrssPath ) ;
2016-10-10 21:37:28 +00:00
// Init normalization buffer
2017-02-02 22:55:19 +00:00
normalized . Buffer = ( PWCH ) ExAllocatePoolWithTag ( NonPagedPool , maxBufSize , PSMON_ALLOC_TAG ) ;
2016-07-21 23:02:31 +00:00
normalized . Length = 0 ;
normalized . MaximumLength = maxBufSize ;
if ( ! normalized . Buffer )
{
2018-12-02 21:56:39 +00:00
LogError ( " Error, allocation failed " ) ;
2016-07-21 23:02:31 +00:00
return STATUS_ACCESS_DENIED ;
}
// Initialize and fill exclude file\dir lists
2016-08-27 20:18:54 +00:00
// exclude
2016-10-10 21:37:28 +00:00
2016-08-27 20:18:54 +00:00
status = InitializePsRuleListContext ( & g_excludeProcessRules ) ;
2016-07-21 23:02:31 +00:00
if ( ! NT_SUCCESS ( status ) )
{
2018-12-02 21:56:39 +00:00
LogError ( " Error, excluded process rules initialization failed with code:%08x " , status ) ;
2017-02-02 22:55:19 +00:00
ExFreePoolWithTag ( normalized . Buffer , PSMON_ALLOC_TAG ) ;
2016-07-21 23:02:31 +00:00
return status ;
}
2016-10-10 21:37:28 +00:00
for ( i = 0 ; g_excludeProcesses [ i ] . path ; i + + )
2016-07-21 23:02:31 +00:00
{
2016-10-10 21:37:28 +00:00
RtlInitUnicodeString ( & str , g_excludeProcesses [ i ] . path ) ;
2016-07-21 23:02:31 +00:00
status = NormalizeDevicePath ( & str , & normalized ) ;
2018-12-02 21:56:39 +00:00
LogTrace ( " Normalized excluded: %wZ " , & normalized ) ;
2016-07-21 23:02:31 +00:00
if ( ! NT_SUCCESS ( status ) )
{
2018-12-02 21:56:39 +00:00
LogWarning ( " Path normalization failed with code:%08x, path:%wZ " , status , & str ) ;
2016-07-21 23:02:31 +00:00
continue ;
}
2016-10-10 21:37:28 +00:00
AddRuleToPsRuleList ( g_excludeProcessRules , & normalized , g_excludeProcesses [ i ] . inherit , & ruleId ) ;
2016-07-21 23:02:31 +00:00
}
2016-12-18 18:11:10 +00:00
// Load entries from the config
2016-12-25 20:56:18 +00:00
CfgEnumConfigsTable ( IgnoreImagesTable , & LoadIgnoredRulesCallback , NULL ) ;
2016-12-18 18:11:10 +00:00
2016-08-27 20:18:54 +00:00
// protected
status = InitializePsRuleListContext ( & g_protectProcessRules ) ;
2016-07-21 23:02:31 +00:00
if ( ! NT_SUCCESS ( status ) )
{
2018-12-02 21:56:39 +00:00
LogError ( " Error, protected process rules initialization failed with code:%08x " , status ) ;
2016-08-27 20:18:54 +00:00
DestroyPsRuleListContext ( g_excludeProcessRules ) ;
2017-02-02 22:55:19 +00:00
ExFreePoolWithTag ( normalized . Buffer , PSMON_ALLOC_TAG ) ;
2016-07-21 23:02:31 +00:00
return status ;
}
2016-10-10 21:37:28 +00:00
for ( i = 0 ; g_protectProcesses [ i ] . path ; i + + )
2016-07-21 23:02:31 +00:00
{
2016-10-10 21:37:28 +00:00
RtlInitUnicodeString ( & str , g_protectProcesses [ i ] . path ) ;
2016-07-21 23:02:31 +00:00
status = NormalizeDevicePath ( & str , & normalized ) ;
2018-12-02 21:56:39 +00:00
LogTrace ( " Normalized protected %wZ " , & normalized ) ;
2016-07-21 23:02:31 +00:00
if ( ! NT_SUCCESS ( status ) )
{
2018-12-02 21:56:39 +00:00
LogWarning ( " Path normalization failed with code:%08x, path:%wZ " , status , & str ) ;
2016-07-21 23:02:31 +00:00
continue ;
}
2016-10-10 21:37:28 +00:00
AddRuleToPsRuleList ( g_protectProcessRules , & normalized , g_protectProcesses [ i ] . inherit , & ruleId ) ;
2016-07-21 23:02:31 +00:00
}
2016-12-18 18:11:10 +00:00
// Load entries from the config
2016-12-25 20:56:18 +00:00
CfgEnumConfigsTable ( ProtectImagesTable , & LoadProtectedRulesCallback , NULL ) ;
2016-12-18 18:11:10 +00:00
2021-07-25 20:15:08 +00:00
// hidden
status = InitializePsRuleListContext ( & g_hideProcessRules ) ;
if ( ! NT_SUCCESS ( status ) )
{
LogError ( " Error, hidden process rules initialization failed with code:%08x " , status ) ;
DestroyPsRuleListContext ( g_excludeProcessRules ) ;
DestroyPsRuleListContext ( g_protectProcessRules ) ;
ExFreePoolWithTag ( normalized . Buffer , PSMON_ALLOC_TAG ) ;
return status ;
}
//TODO: load hidden config
2016-10-18 21:28:55 +00:00
// Process table
2016-12-29 19:48:37 +00:00
ExInitializeFastMutex ( & g_processTableLock ) ;
2021-07-28 18:54:03 +00:00
KeInitializeGuardedMutex ( & g_activeProcListLock ) ;
2016-10-18 21:28:55 +00:00
2016-07-21 23:02:31 +00:00
status = InitializeProcessTable ( CheckProcessFlags ) ;
if ( ! NT_SUCCESS ( status ) )
{
2016-08-27 20:18:54 +00:00
DestroyPsRuleListContext ( g_excludeProcessRules ) ;
DestroyPsRuleListContext ( g_protectProcessRules ) ;
2021-07-25 20:15:08 +00:00
DestroyPsRuleListContext ( g_hideProcessRules ) ;
2017-02-02 22:55:19 +00:00
ExFreePoolWithTag ( normalized . Buffer , PSMON_ALLOC_TAG ) ;
2016-07-21 23:02:31 +00:00
return status ;
}
2017-02-02 22:55:19 +00:00
ExFreePoolWithTag ( normalized . Buffer , PSMON_ALLOC_TAG ) ;
2016-07-21 23:02:31 +00:00
2021-07-28 18:54:03 +00:00
InitializeHiddenProcessTable ( ) ;
2016-10-10 21:37:28 +00:00
g_psMonitorInited = TRUE ;
2016-07-21 23:02:31 +00:00
// Register ps\thr pre create\duplicate object callback
g_regOperation [ 0 ] . ObjectType = PsProcessType ;
g_regOperation [ 0 ] . Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE ;
g_regOperation [ 0 ] . PreOperation = ProcessPreCallback ;
g_regOperation [ 0 ] . PostOperation = NULL ;
g_regOperation [ 1 ] . ObjectType = PsThreadType ;
g_regOperation [ 1 ] . Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE ;
g_regOperation [ 1 ] . PreOperation = ThreadPreCallback ;
g_regOperation [ 1 ] . PostOperation = NULL ;
g_regCallback . Version = OB_FLT_REGISTRATION_VERSION ;
g_regCallback . OperationRegistrationCount = 2 ;
g_regCallback . RegistrationContext = NULL ;
g_regCallback . OperationRegistration = g_regOperation ;
RtlInitUnicodeString ( & g_regCallback . Altitude , L " 1000 " ) ;
status = ObRegisterCallbacks ( & g_regCallback , & g_obRegCallback ) ;
if ( ! NT_SUCCESS ( status ) )
{
2018-12-02 21:56:39 +00:00
LogError ( " Error, object filter registration failed with code:%08x " , status ) ;
2016-07-21 23:02:31 +00:00
DestroyPsMonitor ( ) ;
return status ;
}
// Register rocess create\destroy callback
status = PsSetCreateProcessNotifyRoutineEx ( CreateProcessNotifyCallback , FALSE ) ;
if ( ! NT_SUCCESS ( status ) )
{
2018-12-02 21:56:39 +00:00
LogError ( " Error, process notify registartion failed with code:%08x " , status ) ;
2016-07-21 23:02:31 +00:00
DestroyPsMonitor ( ) ;
return status ;
}
2018-12-02 21:56:39 +00:00
LogTrace ( " Initialization is completed " ) ;
2016-07-21 23:02:31 +00:00
return status ;
}
NTSTATUS DestroyPsMonitor ( )
{
2016-10-10 21:37:28 +00:00
if ( ! g_psMonitorInited )
return STATUS_ALREADY_DISCONNECTED ;
2016-07-21 23:02:31 +00:00
if ( g_obRegCallback )
{
ObUnRegisterCallbacks ( g_obRegCallback ) ;
g_obRegCallback = NULL ;
}
PsSetCreateProcessNotifyRoutineEx ( CreateProcessNotifyCallback , TRUE ) ;
2016-08-27 20:18:54 +00:00
DestroyPsRuleListContext ( g_excludeProcessRules ) ;
DestroyPsRuleListContext ( g_protectProcessRules ) ;
2021-07-25 20:15:08 +00:00
DestroyPsRuleListContext ( g_hideProcessRules ) ;
2016-07-21 23:02:31 +00:00
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-07-21 23:02:31 +00:00
DestroyProcessTable ( ) ;
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
2021-07-28 18:54:03 +00:00
DestroyHiddenProcessTable ( ) ;
2016-10-10 21:37:28 +00:00
g_psMonitorInited = FALSE ;
2016-07-21 23:02:31 +00:00
2018-12-02 21:56:39 +00:00
LogTrace ( " Deinitialization is completed " ) ;
2016-07-21 23:02:31 +00:00
return STATUS_SUCCESS ;
}
2016-08-30 19:40:25 +00:00
2021-07-25 20:15:08 +00:00
NTSTATUS SetStateForProcessesByImage ( PCUNICODE_STRING ImagePath , BOOLEAN Excluded , BOOLEAN Protected , BOOLEAN Hidden )
2016-10-18 21:28:55 +00:00
{
PSYSTEM_PROCESS_INFORMATION processInfo = NULL , first ;
SIZE_T size = 0 , offset ;
NTSTATUS status ;
status = QuerySystemInformation ( SystemProcessInformation , & processInfo , & size ) ;
if ( ! NT_SUCCESS ( status ) )
{
2018-12-02 21:56:39 +00:00
LogWarning ( " Query system information(pslist) failed with code:%08x " , status ) ;
2016-10-18 21:28:55 +00:00
return status ;
}
offset = 0 ;
first = processInfo ;
do
{
HANDLE hProcess ;
CLIENT_ID clientId ;
OBJECT_ATTRIBUTES attribs ;
PUNICODE_STRING procName ;
ProcessTableEntry entry ;
processInfo = ( PSYSTEM_PROCESS_INFORMATION ) ( ( SIZE_T ) processInfo + offset ) ;
if ( processInfo - > ProcessId = = 0 )
{
offset = processInfo - > NextEntryOffset ;
continue ;
}
InitializeObjectAttributes ( & attribs , NULL , OBJ_KERNEL_HANDLE , NULL , NULL ) ;
clientId . UniqueProcess = processInfo - > ProcessId ;
clientId . UniqueThread = 0 ;
status = ZwOpenProcess ( & hProcess , 0x1000 /*PROCESS_QUERY_LIMITED_INFORMATION*/ , & attribs , & clientId ) ;
if ( ! NT_SUCCESS ( status ) )
{
2018-12-02 21:56:39 +00:00
LogWarning ( " Can't open process (pid:%p) failed with code:%08x " , processInfo - > ProcessId , status ) ;
2016-10-18 21:28:55 +00:00
offset = processInfo - > NextEntryOffset ;
continue ;
}
status = QueryProcessInformation ( ProcessImageFileName , hProcess , & procName , & size ) ;
ZwClose ( hProcess ) ;
if ( ! NT_SUCCESS ( status ) )
{
2018-12-02 21:56:39 +00:00
LogWarning ( " Query process information(pid:%p) failed with code:%08x " , processInfo - > ProcessId , status ) ;
2016-10-18 21:28:55 +00:00
offset = processInfo - > NextEntryOffset ;
continue ;
}
entry . processId = processInfo - > ProcessId ;
2021-07-28 22:00:14 +00:00
2016-10-18 21:28:55 +00:00
if ( RtlCompareUnicodeString ( procName , ImagePath , TRUE ) = = 0 )
{
BOOLEAN result = TRUE ;
2021-07-28 22:00:14 +00:00
if ( Hidden )
{
PEPROCESS process = NULL ;
status = PsLookupProcessByProcessId ( processInfo - > ProcessId , & process ) ;
if ( NT_SUCCESS ( status ) )
{
if ( ! AddHiddenProcessToProcessTable ( process ) )
LogWarning ( " Warning, can't insert hidden process, pid:%p " , processInfo - > ProcessId ) ;
UnlinkProcessFromActiveProcessLinks ( process ) ;
ObDereferenceObject ( process ) ;
}
else
{
LogWarning ( " Warning, process lookup failed with code:%08x, pid:%p " , status , processInfo - > ProcessId ) ;
}
}
2016-10-18 21:28:55 +00:00
// Spinlock is locked once for both Get\Update process table functions
// because we want to prevent situations when another thread can change
// any state of process beetwen get and update functions on this place
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( GetProcessInProcessTable ( & entry ) )
{
if ( Excluded )
{
entry . excluded = TRUE ;
entry . inheritExclusion = PsRuleTypeWithoutInherit ;
}
if ( Protected )
{
entry . protected = TRUE ;
entry . inheritProtection = PsRuleTypeWithoutInherit ;
}
2021-07-25 20:15:08 +00:00
if ( Hidden )
{
entry . hidden = TRUE ;
entry . inheritStealth = PsRuleTypeWithoutInherit ;
}
2016-10-18 21:28:55 +00:00
if ( ! UpdateProcessInProcessTable ( & entry ) )
result = FALSE ;
}
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( ! result )
2018-12-02 21:56:39 +00:00
LogWarning ( " Can't update process %p " , processInfo - > ProcessId ) ;
2016-10-18 21:28:55 +00:00
}
FreeInformation ( procName ) ;
offset = processInfo - > NextEntryOffset ;
} while ( offset ) ;
FreeInformation ( first ) ;
return STATUS_SUCCESS ;
}
NTSTATUS AddProtectedImage ( PUNICODE_STRING ImagePath , ULONG InheritType , BOOLEAN ApplyForProcesses , PULONGLONG ObjId )
2016-08-30 19:40:25 +00:00
{
2016-09-19 20:20:30 +00:00
const USHORT maxBufSize = ImagePath - > Length + NORMALIZE_INCREAMENT ;
UNICODE_STRING normalized ;
NTSTATUS status ;
2017-02-02 22:55:19 +00:00
normalized . Buffer = ( PWCH ) ExAllocatePoolWithTag ( PagedPool , maxBufSize , PSMON_ALLOC_TAG ) ;
2016-09-19 20:20:30 +00:00
normalized . Length = 0 ;
normalized . MaximumLength = maxBufSize ;
if ( ! normalized . Buffer )
{
2018-12-02 21:56:39 +00:00
LogWarning ( " Error, can't allocate buffer " ) ;
2016-09-19 20:20:30 +00:00
return STATUS_MEMORY_NOT_ALLOCATED ;
}
status = NormalizeDevicePath ( ImagePath , & normalized ) ;
if ( ! NT_SUCCESS ( status ) )
{
2018-12-02 21:56:39 +00:00
LogWarning ( " Error, path normalization failed with code:%08x, path:%wZ " , status , ImagePath ) ;
2017-02-02 22:55:19 +00:00
ExFreePoolWithTag ( normalized . Buffer , PSMON_ALLOC_TAG ) ;
2016-09-19 20:20:30 +00:00
return status ;
}
2018-12-02 21:56:39 +00:00
LogTrace ( " Adding protect image: %wZ " , & normalized ) ;
2016-09-19 20:20:30 +00:00
status = AddRuleToPsRuleList ( g_protectProcessRules , & normalized , InheritType , ObjId ) ;
2016-10-18 21:28:55 +00:00
if ( ApplyForProcesses )
2021-07-25 20:15:08 +00:00
SetStateForProcessesByImage ( & normalized , FALSE , TRUE , FALSE ) ;
2016-10-18 21:28:55 +00:00
2017-02-02 22:55:19 +00:00
ExFreePoolWithTag ( normalized . Buffer , PSMON_ALLOC_TAG ) ;
2016-09-19 20:20:30 +00:00
return status ;
2016-08-30 19:40:25 +00:00
}
NTSTATUS GetProtectedProcessState ( HANDLE ProcessId , PULONG InheritType , PBOOLEAN Enable )
{
ProcessTableEntry entry ;
2016-10-18 21:28:55 +00:00
BOOLEAN result ;
2016-08-30 19:40:25 +00:00
entry . processId = ProcessId ;
2016-10-18 21:28:55 +00:00
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
result = GetProcessInProcessTable ( & entry ) ;
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( ! result )
2016-08-30 19:40:25 +00:00
return STATUS_NOT_FOUND ;
* Enable = entry . protected ;
* InheritType = entry . inheritProtection ;
return STATUS_SUCCESS ;
}
NTSTATUS SetProtectedProcessState ( HANDLE ProcessId , ULONG InheritType , BOOLEAN Enable )
{
NTSTATUS status = STATUS_SUCCESS ;
ProcessTableEntry entry ;
2016-10-18 21:28:55 +00:00
BOOLEAN result ;
2016-08-30 19:40:25 +00:00
entry . processId = ProcessId ;
2016-10-18 21:28:55 +00:00
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
result = GetProcessInProcessTable ( & entry ) ;
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( ! result )
2016-08-30 19:40:25 +00:00
return STATUS_NOT_FOUND ;
if ( Enable )
{
entry . protected = TRUE ;
entry . inheritProtection = InheritType ;
}
else
{
entry . protected = FALSE ;
}
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
result = UpdateProcessInProcessTable ( & entry ) ;
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( ! result )
2016-08-30 19:40:25 +00:00
return STATUS_NOT_FOUND ;
return status ;
}
NTSTATUS RemoveProtectedImage ( ULONGLONG ObjId )
{
return RemoveRuleFromPsRuleList ( g_protectProcessRules , ObjId ) ;
}
NTSTATUS RemoveAllProtectedImages ( )
{
return RemoveAllRulesFromPsRuleList ( g_protectProcessRules ) ;
}
2016-10-18 21:28:55 +00:00
NTSTATUS AddExcludedImage ( PUNICODE_STRING ImagePath , ULONG InheritType , BOOLEAN ApplyForProcesses , PULONGLONG ObjId )
2016-08-30 19:40:25 +00:00
{
2016-09-19 20:20:30 +00:00
const USHORT maxBufSize = ImagePath - > Length + NORMALIZE_INCREAMENT ;
UNICODE_STRING normalized ;
NTSTATUS status ;
2017-02-02 22:55:19 +00:00
normalized . Buffer = ( PWCH ) ExAllocatePoolWithTag ( PagedPool , maxBufSize , PSMON_ALLOC_TAG ) ;
2016-09-19 20:20:30 +00:00
normalized . Length = 0 ;
normalized . MaximumLength = maxBufSize ;
if ( ! normalized . Buffer )
{
2018-12-02 21:56:39 +00:00
LogWarning ( " Error, can't allocate buffer " ) ;
2016-09-19 20:20:30 +00:00
return STATUS_MEMORY_NOT_ALLOCATED ;
}
status = NormalizeDevicePath ( ImagePath , & normalized ) ;
if ( ! NT_SUCCESS ( status ) )
{
2018-12-02 21:56:39 +00:00
LogWarning ( " Error, path normalization failed with code:%08x, path:%wZ " , status , ImagePath ) ;
2017-02-02 22:55:19 +00:00
ExFreePoolWithTag ( normalized . Buffer , PSMON_ALLOC_TAG ) ;
2016-09-19 20:20:30 +00:00
return status ;
}
2018-12-02 21:56:39 +00:00
LogTrace ( " Adding exclude image: %wZ " , & normalized ) ;
2016-09-19 20:20:30 +00:00
status = AddRuleToPsRuleList ( g_excludeProcessRules , & normalized , InheritType , ObjId ) ;
2016-10-18 21:28:55 +00:00
if ( ApplyForProcesses )
2021-07-25 20:15:08 +00:00
SetStateForProcessesByImage ( & normalized , TRUE , FALSE , FALSE ) ;
2016-10-18 21:28:55 +00:00
2017-02-02 22:55:19 +00:00
ExFreePoolWithTag ( normalized . Buffer , PSMON_ALLOC_TAG ) ;
2016-09-19 20:20:30 +00:00
return status ;
2016-08-30 19:40:25 +00:00
}
NTSTATUS GetExcludedProcessState ( HANDLE ProcessId , PULONG InheritType , PBOOLEAN Enable )
{
ProcessTableEntry entry ;
2016-10-18 21:28:55 +00:00
BOOLEAN result ;
2016-08-30 19:40:25 +00:00
entry . processId = ProcessId ;
2016-10-18 21:28:55 +00:00
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
result = GetProcessInProcessTable ( & entry ) ;
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( ! result )
2016-08-30 19:40:25 +00:00
return STATUS_NOT_FOUND ;
* Enable = entry . excluded ;
* InheritType = entry . inheritExclusion ;
return STATUS_SUCCESS ;
}
NTSTATUS SetExcludedProcessState ( HANDLE ProcessId , ULONG InheritType , BOOLEAN Enable )
{
NTSTATUS status = STATUS_SUCCESS ;
ProcessTableEntry entry ;
2016-10-18 21:28:55 +00:00
BOOLEAN result ;
2016-08-30 19:40:25 +00:00
entry . processId = ProcessId ;
2016-10-18 21:28:55 +00:00
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
result = GetProcessInProcessTable ( & entry ) ;
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( ! result )
2016-08-30 19:40:25 +00:00
return STATUS_NOT_FOUND ;
if ( Enable )
{
entry . excluded = TRUE ;
entry . inheritExclusion = InheritType ;
}
else
{
entry . excluded = FALSE ;
}
2016-12-29 19:48:37 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
result = UpdateProcessInProcessTable ( & entry ) ;
2016-12-29 19:48:37 +00:00
ExReleaseFastMutex ( & g_processTableLock ) ;
2016-10-18 21:28:55 +00:00
if ( ! result )
2016-08-30 19:40:25 +00:00
return STATUS_NOT_FOUND ;
return status ;
}
NTSTATUS RemoveExcludedImage ( ULONGLONG ObjId )
{
return RemoveRuleFromPsRuleList ( g_excludeProcessRules , ObjId ) ;
}
NTSTATUS RemoveAllExcludedImages ( )
{
return RemoveAllRulesFromPsRuleList ( g_excludeProcessRules ) ;
}
2021-07-25 20:15:08 +00:00
NTSTATUS AddHiddenImage ( PUNICODE_STRING ImagePath , ULONG InheritType , BOOLEAN ApplyForProcesses , PULONGLONG ObjId )
{
const USHORT maxBufSize = ImagePath - > Length + NORMALIZE_INCREAMENT ;
UNICODE_STRING normalized ;
NTSTATUS status ;
normalized . Buffer = ( PWCH ) ExAllocatePoolWithTag ( PagedPool , maxBufSize , PSMON_ALLOC_TAG ) ;
normalized . Length = 0 ;
normalized . MaximumLength = maxBufSize ;
if ( ! normalized . Buffer )
{
LogWarning ( " Error, can't allocate buffer " ) ;
return STATUS_MEMORY_NOT_ALLOCATED ;
}
status = NormalizeDevicePath ( ImagePath , & normalized ) ;
if ( ! NT_SUCCESS ( status ) )
{
LogWarning ( " Error, path normalization failed with code:%08x, path:%wZ " , status , ImagePath ) ;
ExFreePoolWithTag ( normalized . Buffer , PSMON_ALLOC_TAG ) ;
return status ;
}
LogTrace ( " Adding hidden image: %wZ " , & normalized ) ;
status = AddRuleToPsRuleList ( g_hideProcessRules , & normalized , InheritType , ObjId ) ;
//TODO:
if ( ApplyForProcesses )
SetStateForProcessesByImage ( & normalized , FALSE , FALSE , TRUE ) ;
ExFreePoolWithTag ( normalized . Buffer , PSMON_ALLOC_TAG ) ;
return status ;
}
NTSTATUS GetHiddenProcessState ( HANDLE ProcessId , PULONG InheritType , PBOOLEAN Enable )
{
ProcessTableEntry entry ;
BOOLEAN result ;
entry . processId = ProcessId ;
ExAcquireFastMutex ( & g_processTableLock ) ;
result = GetProcessInProcessTable ( & entry ) ;
ExReleaseFastMutex ( & g_processTableLock ) ;
if ( ! result )
return STATUS_NOT_FOUND ;
* Enable = entry . hidden ;
* InheritType = entry . inheritStealth ;
return STATUS_SUCCESS ;
}
2021-07-28 18:54:03 +00:00
NTSTATUS SetHiddenProcessState ( HANDLE ProcessId , ULONG InheritType , BOOLEAN Enable )
2021-07-25 20:15:08 +00:00
{
ProcessTableEntry entry ;
BOOLEAN result ;
2021-07-28 18:54:03 +00:00
PEPROCESS process = NULL ;
NTSTATUS status ;
if ( ! ProcessId | | ProcessId = = SYSTEM_PROCESS_ID )
return STATUS_NOT_SUPPORTED ;
2021-07-25 20:15:08 +00:00
entry . processId = ProcessId ;
ExAcquireFastMutex ( & g_processTableLock ) ;
result = GetProcessInProcessTable ( & entry ) ;
ExReleaseFastMutex ( & g_processTableLock ) ;
if ( ! result )
return STATUS_NOT_FOUND ;
2021-07-28 18:54:03 +00:00
status = PsLookupProcessByProcessId ( ProcessId , & process ) ;
if ( ! NT_SUCCESS ( status ) )
{
LogWarning ( " Warning, process lookup failed with code:%08x, pid:%p " , status , ProcessId ) ;
return status ;
}
2021-07-25 20:15:08 +00:00
if ( Enable )
{
2021-07-28 18:54:03 +00:00
if ( ! entry . hidden )
{
if ( ! AddHiddenProcessToProcessTable ( process ) )
{
LogWarning ( " Warning, can't insert hidden process, pid:%p " , ProcessId ) ;
ObDereferenceObject ( process ) ;
return STATUS_LINK_FAILED ;
}
UnlinkProcessFromActiveProcessLinks ( process ) ;
}
2021-07-25 20:15:08 +00:00
entry . hidden = TRUE ;
entry . inheritStealth = InheritType ;
}
else
{
2021-07-28 18:54:03 +00:00
if ( ! entry . hidden )
{
ObDereferenceObject ( process ) ;
return STATUS_NOT_CAPABLE ;
}
if ( ! RemoveHiddenProcessFromProcessTable ( process ) )
{
LogWarning ( " Warning, can't remove hidden process, pid:%p " , ProcessId ) ;
ObDereferenceObject ( process ) ;
return STATUS_LINK_FAILED ;
}
LinkProcessToActiveProcessLinks ( process ) ;
2021-07-25 20:15:08 +00:00
entry . hidden = FALSE ;
2021-07-28 18:54:03 +00:00
entry . inheritStealth = 0 ;
2021-07-25 20:15:08 +00:00
}
2021-07-28 18:54:03 +00:00
ObDereferenceObject ( process ) ;
2021-07-25 20:15:08 +00:00
ExAcquireFastMutex ( & g_processTableLock ) ;
result = UpdateProcessInProcessTable ( & entry ) ;
ExReleaseFastMutex ( & g_processTableLock ) ;
if ( ! result )
return STATUS_NOT_FOUND ;
2021-07-28 18:54:03 +00:00
return STATUS_SUCCESS ;
2021-07-25 20:15:08 +00:00
}
NTSTATUS RemoveHiddenImage ( ULONGLONG ObjId )
{
return RemoveRuleFromPsRuleList ( g_hideProcessRules , ObjId ) ;
}
NTSTATUS RemoveAllHiddenImages ( )
{
return RemoveAllRulesFromPsRuleList ( g_hideProcessRules ) ;
}