3340 lines
92 KiB
C
3340 lines
92 KiB
C
|
|
|||
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
sepaudit.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This Module implements the audit and alarm procedures that are
|
|||
|
private to the security component.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Robert Reichel (robertre) September 10, 1991
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel Mode
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "pch.h"
|
|||
|
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
#include <msaudite.h>
|
|||
|
#include <string.h>
|
|||
|
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE,SepAdtPrivilegeObjectAuditAlarm)
|
|||
|
#pragma alloc_text(PAGE,SepAdtPrivilegedServiceAuditAlarm)
|
|||
|
#pragma alloc_text(PAGE,SepAdtOpenObjectAuditAlarm)
|
|||
|
#pragma alloc_text(PAGE,SepAdtOpenObjectForDeleteAuditAlarm)
|
|||
|
#pragma alloc_text(PAGE,SepAdtCloseObjectAuditAlarm)
|
|||
|
#pragma alloc_text(PAGE,SepAdtDeleteObjectAuditAlarm)
|
|||
|
#pragma alloc_text(PAGE,SepAdtObjectReferenceAuditAlarm)
|
|||
|
#pragma alloc_text(PAGE,SepQueryNameString)
|
|||
|
#pragma alloc_text(PAGE,SepQueryTypeString)
|
|||
|
#pragma alloc_text(PAGE,SeAuditProcessCreation)
|
|||
|
#pragma alloc_text(PAGE,SeAuditHandleDuplication)
|
|||
|
#pragma alloc_text(PAGE,SeAuditProcessExit)
|
|||
|
#pragma alloc_text(PAGE,SeAuditSystemTimeChange)
|
|||
|
#pragma alloc_text(PAGE,SepAdtGenerateDiscardAudit)
|
|||
|
#pragma alloc_text(PAGE,SeLocateProcessImageName)
|
|||
|
#pragma alloc_text(PAGE,SeInitializeProcessAuditName)
|
|||
|
#pragma alloc_text(PAGE,SepAuditAssignPrimaryToken)
|
|||
|
#pragma alloc_text(PAGE,SeAuditLPCInvalidUse)
|
|||
|
#pragma alloc_text(PAGE,SeAuditHardLinkCreation)
|
|||
|
#pragma alloc_text(PAGE,SeOperationAuditAlarm)
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
#define SepSetParmTypeSid( AuditParameters, Index, Sid ) \
|
|||
|
{ \
|
|||
|
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeSid; \
|
|||
|
(AuditParameters).Parameters[(Index)].Length = SeLengthSid( (Sid) ); \
|
|||
|
(AuditParameters).Parameters[(Index)].Address = (Sid); \
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#define SepSetParmTypeString( AuditParameters, Index, String ) \
|
|||
|
{ \
|
|||
|
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeString; \
|
|||
|
(AuditParameters).Parameters[(Index)].Length = \
|
|||
|
sizeof(UNICODE_STRING)+(String)->Length; \
|
|||
|
(AuditParameters).Parameters[(Index)].Address = (String); \
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#define SepSetParmTypeFileSpec( AuditParameters, Index, String ) \
|
|||
|
{ \
|
|||
|
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeFileSpec; \
|
|||
|
(AuditParameters).Parameters[(Index)].Length = \
|
|||
|
sizeof(UNICODE_STRING)+(String)->Length; \
|
|||
|
(AuditParameters).Parameters[(Index)].Address = (String); \
|
|||
|
}
|
|||
|
|
|||
|
#define SepSetParmTypeUlong( AuditParameters, Index, Ulong ) \
|
|||
|
{ \
|
|||
|
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeUlong; \
|
|||
|
(AuditParameters).Parameters[(Index)].Length = sizeof( (Ulong) ); \
|
|||
|
(AuditParameters).Parameters[(Index)].Data[0] = (ULONG)(Ulong); \
|
|||
|
}
|
|||
|
|
|||
|
#define SepSetParmTypePtr( AuditParameters, Index, Ptr ) \
|
|||
|
{ \
|
|||
|
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypePtr; \
|
|||
|
(AuditParameters).Parameters[(Index)].Length = sizeof( ULONG_PTR ); \
|
|||
|
(AuditParameters).Parameters[(Index)].Data[0] = (ULONG_PTR)(Ptr); \
|
|||
|
}
|
|||
|
|
|||
|
#define SepSetParmTypeNoLogon( AuditParameters, Index ) \
|
|||
|
{ \
|
|||
|
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeNoLogonId; \
|
|||
|
}
|
|||
|
|
|||
|
#define SepSetParmTypeLogonId( AuditParameters, Index, LogonId ) \
|
|||
|
{ \
|
|||
|
LUID * TmpLuid; \
|
|||
|
\
|
|||
|
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeLogonId; \
|
|||
|
(AuditParameters).Parameters[(Index)].Length = sizeof( (LogonId) ); \
|
|||
|
TmpLuid = (LUID *)(&(AuditParameters).Parameters[(Index)].Data[0]); \
|
|||
|
*TmpLuid = (LogonId); \
|
|||
|
}
|
|||
|
|
|||
|
#define SepSetParmTypeAccessMask( AuditParameters, Index, AccessMask, ObjectTypeIndex ) \
|
|||
|
{ \
|
|||
|
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeAccessMask; \
|
|||
|
(AuditParameters).Parameters[(Index)].Length = sizeof( ACCESS_MASK ); \
|
|||
|
(AuditParameters).Parameters[(Index)].Data[0] = (AccessMask); \
|
|||
|
(AuditParameters).Parameters[(Index)].Data[1] = (ObjectTypeIndex); \
|
|||
|
}
|
|||
|
|
|||
|
#define SepSetParmTypePrivileges( AuditParameters, Index, Privileges ) \
|
|||
|
{ \
|
|||
|
ASSERT( Privileges->PrivilegeCount <= SEP_MAX_PRIVILEGE_COUNT ); \
|
|||
|
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypePrivs; \
|
|||
|
(AuditParameters).Parameters[(Index)].Length = SepPrivilegeSetSize( (Privileges) ); \
|
|||
|
(AuditParameters).Parameters[(Index)].Address = (Privileges); \
|
|||
|
}
|
|||
|
|
|||
|
#define SepSetParmTypeObjectTypes( AuditParameters, Index, ObjectTypes, ObjectTypeCount, ObjectTypeIndex ) \
|
|||
|
{ \
|
|||
|
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeObjectTypes; \
|
|||
|
(AuditParameters).Parameters[(Index)].Length = sizeof( SE_ADT_OBJECT_TYPE ) * (ObjectTypeCount);\
|
|||
|
(AuditParameters).Parameters[(Index)].Address = (ObjectTypes); \
|
|||
|
(AuditParameters).Parameters[(Index)].Data[1] = (ObjectTypeIndex); \
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#define SepSetParmTypeTime( AuditParameters, Index, Time ) \
|
|||
|
{ \
|
|||
|
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeTime; \
|
|||
|
(AuditParameters).Parameters[(Index)].Length = sizeof( (Time) ); \
|
|||
|
*((PLARGE_INTEGER)(&(AuditParameters).Parameters[(Index)].Data[0])) = Time; \
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
SepAdtPrivilegeObjectAuditAlarm (
|
|||
|
IN PUNICODE_STRING CapturedSubsystemName OPTIONAL,
|
|||
|
IN PVOID HandleId,
|
|||
|
IN PTOKEN ClientToken OPTIONAL,
|
|||
|
IN PTOKEN PrimaryToken,
|
|||
|
IN PVOID ProcessId,
|
|||
|
IN ACCESS_MASK DesiredAccess,
|
|||
|
IN PPRIVILEGE_SET CapturedPrivileges,
|
|||
|
IN BOOLEAN AccessGranted
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Implements NtPrivilegeObjectAuditAlarm after parameters have been
|
|||
|
captured.
|
|||
|
|
|||
|
This routine is used to generate audit and alarm messages when an
|
|||
|
attempt is made to perform privileged operations on a protected
|
|||
|
subsystem object after the object is already opened. This routine may
|
|||
|
result in several messages being generated and sent to Port objects.
|
|||
|
This may result in a significant latency before returning. Design of
|
|||
|
routines that must call this routine must take this potential latency
|
|||
|
into account. This may have an impact on the approach taken for data
|
|||
|
structure mutex locking, for example.
|
|||
|
|
|||
|
This API requires the caller have SeTcbPrivilege privilege. The test
|
|||
|
for this privilege is always against the primary token of the calling
|
|||
|
process, allowing the caller to be impersonating a client during the
|
|||
|
call with no ill effects.
|
|||
|
|
|||
|
This routine will create an SE_ADT_PARAMETERS array organized as follows:
|
|||
|
|
|||
|
Parameter[0] - User Sid
|
|||
|
|
|||
|
Parameter[1] - Subsystem name (if available)
|
|||
|
|
|||
|
Parameter[2] - Subsystem name (if available)
|
|||
|
|
|||
|
Parameter[3] - New handle ID
|
|||
|
|
|||
|
Parameter[4] - Subject's process id
|
|||
|
|
|||
|
Parameter[5] - Subject's primary authentication ID
|
|||
|
|
|||
|
Parameter[6] - Subject's client authentication ID
|
|||
|
|
|||
|
Parameter[7] - Privileges used for open
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CapturedSubsystemName - Supplies a name string identifying the
|
|||
|
subsystem calling the routine.
|
|||
|
|
|||
|
HandleId - A unique value representing the client's handle to the
|
|||
|
object.
|
|||
|
|
|||
|
ClientToken - Optionally provides a pointer to the client token
|
|||
|
(only if the caller is currently impersonating)
|
|||
|
|
|||
|
PrimaryToken - Provides a pointer to the caller's primary token.
|
|||
|
|
|||
|
DesiredAccess - The desired access mask. This mask must have been
|
|||
|
previously mapped to contain no generic accesses.
|
|||
|
|
|||
|
CapturedPrivileges - The set of privileges required for the requested
|
|||
|
operation. Those privileges that were held by the subject are
|
|||
|
marked using the UsedForAccess flag of the attributes
|
|||
|
associated with each privilege.
|
|||
|
|
|||
|
AccessGranted - Indicates whether the requested access was granted or
|
|||
|
not. A value of TRUE indicates the access was granted. A value of
|
|||
|
FALSE indicates the access was not granted.
|
|||
|
|
|||
|
Return value:
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|||
|
PSID CapturedUserSid;
|
|||
|
LUID ClientAuthenticationId;
|
|||
|
LUID PrimaryAuthenticationId;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER( DesiredAccess );
|
|||
|
|
|||
|
//
|
|||
|
// Determine if we are auditing the use of privileges
|
|||
|
//
|
|||
|
|
|||
|
if ( SepAdtAuditThisEvent( AuditCategoryPrivilegeUse, &AccessGranted ) &&
|
|||
|
SepFilterPrivilegeAudits( CapturedPrivileges )) {
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( ClientToken )) {
|
|||
|
|
|||
|
CapturedUserSid = SepTokenUserSid( ClientToken );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
CapturedUserSid = SepTokenUserSid( PrimaryToken );
|
|||
|
}
|
|||
|
|
|||
|
if ( RtlEqualSid( SeLocalSystemSid, CapturedUserSid )) {
|
|||
|
|
|||
|
return (FALSE);
|
|||
|
}
|
|||
|
|
|||
|
PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken );
|
|||
|
|
|||
|
//
|
|||
|
// A completely zero'd entry will be interpreted
|
|||
|
// as a "null string" or not supplied parameter.
|
|||
|
//
|
|||
|
// Initializing the entire array up front will allow
|
|||
|
// us to avoid filling in each not supplied entry.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory (
|
|||
|
(PVOID) &AuditParameters,
|
|||
|
sizeof( AuditParameters )
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_PRIVILEGE_USE;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_PRIVILEGED_OBJECT;
|
|||
|
AuditParameters.ParameterCount = 0;
|
|||
|
|
|||
|
if ( AccessGranted ) {
|
|||
|
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[0] - User Sid
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, CapturedUserSid );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[1] - Subsystem name (if available)
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[2] - Subsystem name (if available)
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[3] - New handle ID
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, HandleId );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[4] - Subject's process id
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[5] - Subject's primary authentication ID
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, PrimaryAuthenticationId );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[6] - Subject's client authentication ID
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( ClientToken )) {
|
|||
|
|
|||
|
ClientAuthenticationId = SepTokenAuthenticationId( ClientToken );
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, ClientAuthenticationId );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[7] - Privileges used for open
|
|||
|
//
|
|||
|
|
|||
|
if ( (CapturedPrivileges != NULL) && (CapturedPrivileges->PrivilegeCount > 0) ) {
|
|||
|
|
|||
|
SepSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, CapturedPrivileges );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
|
|||
|
return ( TRUE );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return ( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SepAdtPrivilegedServiceAuditAlarm (
|
|||
|
IN PUNICODE_STRING CapturedSubsystemName,
|
|||
|
IN PUNICODE_STRING CapturedServiceName,
|
|||
|
IN PTOKEN ClientToken OPTIONAL,
|
|||
|
IN PTOKEN PrimaryToken,
|
|||
|
IN PPRIVILEGE_SET CapturedPrivileges,
|
|||
|
IN BOOLEAN AccessGranted
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is the active part of NtPrivilegedServiceAuditAlarm.
|
|||
|
|
|||
|
This routine is used to generate audit and alarm messages when an
|
|||
|
attempt is made to perform privileged system service operations. This
|
|||
|
routine may result in several messages being generated and sent to Port
|
|||
|
objects. This may result in a significant latency before returning.
|
|||
|
Design of routines that must call this routine must take this potential
|
|||
|
latency into account. This may have an impact on the approach taken
|
|||
|
for data structure mutex locking, for example.
|
|||
|
|
|||
|
This API requires the caller have SeTcbPrivilege privilege. The test
|
|||
|
for this privilege is always against the primary token of the calling
|
|||
|
process, allowing the caller to be impersonating a client during the
|
|||
|
call with no ill effects. The test for this privilege is assumed to
|
|||
|
have occurred at a higher level.
|
|||
|
|
|||
|
This routine will create an SE_ADT_PARAMETERS array organized as follows:
|
|||
|
|
|||
|
Parameter[0] - User Sid
|
|||
|
|
|||
|
Parameter[1] - Subsystem name (if available)
|
|||
|
|
|||
|
Parameter[2] - Subject's primary authentication ID
|
|||
|
|
|||
|
Parameter[3] - Subject's client authentication ID
|
|||
|
|
|||
|
Parameter[4] - Privileges used for open
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SubsystemName - Supplies a name string identifying the subsystem
|
|||
|
calling the routine.
|
|||
|
|
|||
|
ServiceName - Supplies a name of the privileged subsystem service. For
|
|||
|
example, "RESET RUNTIME LOCAL SECURITY" might be specified
|
|||
|
by a Local Security Authority service used to update the local
|
|||
|
security policy database.
|
|||
|
|
|||
|
ClientToken - Optionally provides a pointer to the client token
|
|||
|
(only if the caller is currently impersonating)
|
|||
|
|
|||
|
PrimaryToken - Provides a pointer to the caller's primary token.
|
|||
|
|
|||
|
Privileges - Points to a set of privileges required to perform the
|
|||
|
privileged operation. Those privileges that were held by the
|
|||
|
subject are marked using the UsedForAccess flag of the
|
|||
|
attributes associated with each privilege.
|
|||
|
|
|||
|
AccessGranted - Indicates whether the requested access was granted or
|
|||
|
not. A value of TRUE indicates the access was granted. A value of
|
|||
|
FALSE indicates the access was not granted.
|
|||
|
|
|||
|
|
|||
|
Return value:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|||
|
PSID CapturedUserSid;
|
|||
|
LUID ClientAuthenticationId;
|
|||
|
LUID PrimaryAuthenticationId;
|
|||
|
PUNICODE_STRING SubsystemName;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Determine if we are auditing privileged services
|
|||
|
//
|
|||
|
|
|||
|
if ( SepAdtAuditThisEvent( AuditCategoryPrivilegeUse, &AccessGranted )) {
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( ClientToken )) {
|
|||
|
|
|||
|
CapturedUserSid = SepTokenUserSid( ClientToken );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
CapturedUserSid = SepTokenUserSid( PrimaryToken );
|
|||
|
}
|
|||
|
|
|||
|
PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken );
|
|||
|
|
|||
|
if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
|||
|
|
|||
|
SubsystemName = (PUNICODE_STRING)&SeSubsystemName;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SubsystemName = CapturedSubsystemName;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// A completely zero'd entry will be interpreted
|
|||
|
// as a "null string" or not supplied parameter.
|
|||
|
//
|
|||
|
// Initializing the entire array up front will allow
|
|||
|
// us to avoid filling in each not supplied entry.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory (
|
|||
|
(PVOID) &AuditParameters,
|
|||
|
sizeof( AuditParameters )
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_PRIVILEGE_USE;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_PRIVILEGED_SERVICE;
|
|||
|
AuditParameters.ParameterCount = 0;
|
|||
|
|
|||
|
if ( AccessGranted ) {
|
|||
|
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[0] - User Sid
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, CapturedUserSid );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[1] - Subsystem name (if available)
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[2] - Server
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[3] - Service name (if available)
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( CapturedServiceName )) {
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedServiceName );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[3] - Subject's primary authentication ID
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, PrimaryAuthenticationId );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[4] - Subject's client authentication ID
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( ClientToken )) {
|
|||
|
|
|||
|
ClientAuthenticationId = SepTokenAuthenticationId( ClientToken );
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, ClientAuthenticationId );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[5] - Privileges used for open
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
if ( (CapturedPrivileges != NULL) && (CapturedPrivileges->PrivilegeCount > 0) ) {
|
|||
|
|
|||
|
SepSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, CapturedPrivileges );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
SepAdtOpenObjectAuditAlarm (
|
|||
|
IN PUNICODE_STRING CapturedSubsystemName,
|
|||
|
IN PVOID *HandleId OPTIONAL,
|
|||
|
IN PUNICODE_STRING CapturedObjectTypeName,
|
|||
|
IN PUNICODE_STRING CapturedObjectName OPTIONAL,
|
|||
|
IN PTOKEN ClientToken OPTIONAL,
|
|||
|
IN PTOKEN PrimaryToken,
|
|||
|
IN ACCESS_MASK DesiredAccess,
|
|||
|
IN ACCESS_MASK GrantedAccess,
|
|||
|
IN PLUID OperationId,
|
|||
|
IN PPRIVILEGE_SET CapturedPrivileges OPTIONAL,
|
|||
|
IN BOOLEAN AccessGranted,
|
|||
|
IN HANDLE ProcessID,
|
|||
|
IN POLICY_AUDIT_EVENT_TYPE AuditType,
|
|||
|
IN PIOBJECT_TYPE_LIST ObjectTypeList OPTIONAL,
|
|||
|
IN ULONG ObjectTypeListLength,
|
|||
|
IN PACCESS_MASK GrantedAccessArray OPTIONAL
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Implements NtOpenObjectAuditAlarm after parameters have been captured.
|
|||
|
|
|||
|
This routine is used to generate audit and alarm messages when an
|
|||
|
attempt is made to access an existing protected subsystem object or
|
|||
|
create a new one. This routine may result in several messages being
|
|||
|
generated and sent to Port objects. This may result in a significant
|
|||
|
latency before returning. Design of routines that must call this
|
|||
|
routine must take this potential latency into account. This may have
|
|||
|
an impact on the approach taken for data structure mutex locking, for
|
|||
|
example. This API requires the caller have SeTcbPrivilege privilege.
|
|||
|
The test for this privilege is always against the primary token of the
|
|||
|
calling process, not the impersonation token of the thread.
|
|||
|
|
|||
|
|
|||
|
This routine will create an SE_ADT_PARAMETERS array organized as follows:
|
|||
|
|
|||
|
Parameter[0] - User Sid
|
|||
|
|
|||
|
Parameter[1] - Subsystem name (if available)
|
|||
|
|
|||
|
Parameter[2] - Server name (if available)
|
|||
|
|
|||
|
Parameter[3] - Object Type Name
|
|||
|
|
|||
|
Parameter[4] - Object Name
|
|||
|
|
|||
|
Parameter[5] - New handle ID
|
|||
|
|
|||
|
Parameter[6] - Subject's process id
|
|||
|
|
|||
|
Parameter[7] - Subject's image file name
|
|||
|
|
|||
|
Parameter[8] - Subject's primary authentication ID
|
|||
|
|
|||
|
Parameter[9] - Subject's client authentication ID
|
|||
|
|
|||
|
Parameter[10] - DesiredAccess mask
|
|||
|
|
|||
|
Parameter[11] - Privileges used for open
|
|||
|
|
|||
|
Parameter[12] - Guid/Level/AccessMask of objects/property sets/properties accesses.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CapturedSubsystemName - Supplies a name string identifying the
|
|||
|
subsystem calling the routine.
|
|||
|
|
|||
|
HandleId - A unique value representing the client's handle to the
|
|||
|
object. If the access attempt was not successful (AccessGranted is
|
|||
|
FALSE), then this parameter is ignored.
|
|||
|
|
|||
|
CapturedObjectTypeName - Supplies the name of the type of object being
|
|||
|
accessed.
|
|||
|
|
|||
|
CapturedObjectName - Supplies the name of the object the client
|
|||
|
accessed or attempted to access.
|
|||
|
|
|||
|
CapturedSecurityDescriptor - A pointer to the security descriptor of
|
|||
|
the object being accessed.
|
|||
|
|
|||
|
ClientToken - Optionally provides a pointer to the client token
|
|||
|
(only if the caller is currently impersonating)
|
|||
|
|
|||
|
PrimaryToken - Provides a pointer to the caller's primary token.
|
|||
|
|
|||
|
DesiredAccess - The desired access mask. This mask must have been
|
|||
|
previously mapped to contain no generic accesses.
|
|||
|
|
|||
|
GrantedAccess - The mask of accesses that were actually granted.
|
|||
|
|
|||
|
CapturedPrivileges - Optionally points to a set of privileges that were
|
|||
|
required for the access attempt. Those privileges that were held
|
|||
|
by the subject are marked using the UsedForAccess flag of the
|
|||
|
attributes associated with each privilege.
|
|||
|
|
|||
|
ObjectCreation - A boolean flag indicating whether the access will
|
|||
|
result in a new object being created if granted. A value of TRUE
|
|||
|
indicates an object will be created, FALSE indicates an existing
|
|||
|
object will be opened.
|
|||
|
|
|||
|
AccessGranted - Indicates whether the requested access was granted or
|
|||
|
not. A value of TRUE indicates the access was granted. A value of
|
|||
|
FALSE indicates the access was not granted.
|
|||
|
|
|||
|
GenerateOnClose - Points to a boolean that is set by the audit
|
|||
|
generation routine and must be passed to NtCloseObjectAuditAlarm()
|
|||
|
when the object handle is closed.
|
|||
|
|
|||
|
GenerateAudit - Indicates if we should generate an audit for this operation.
|
|||
|
|
|||
|
GenerateAlarm - Indicates if we should generate an alarm for this operation.
|
|||
|
|
|||
|
AuditType - Specifies the type of audit to be generated. Valid values
|
|||
|
are: AuditCategoryObjectAccess and AuditCategoryDirectoryServiceAccess.
|
|||
|
|
|||
|
ObjectTypeList - Supplies a list of GUIDs representing the object (and
|
|||
|
sub-objects) being accessed.
|
|||
|
|
|||
|
ObjectTypeListLength - Specifies the number of elements in the ObjectTypeList.
|
|||
|
|
|||
|
GrantedAccessArray - If non NULL, specifies an array of access mask granted
|
|||
|
to each object in ObjectTypeList.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns TRUE if audit is generated, FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|||
|
ULONG ObjectTypeIndex;
|
|||
|
PSID CapturedUserSid;
|
|||
|
LUID PrimaryAuthenticationId = { 0 };
|
|||
|
LUID ClientAuthenticationId = { 0 };
|
|||
|
PSE_ADT_OBJECT_TYPE AdtObjectTypeBuffer = NULL;
|
|||
|
PEPROCESS Process = NULL;
|
|||
|
PUNICODE_STRING ImageFileName;
|
|||
|
UNICODE_STRING NullString = {0};
|
|||
|
NTSTATUS Status;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
Process = PsGetCurrentProcess();
|
|||
|
|
|||
|
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
|||
|
|
|||
|
if ( !NT_SUCCESS(Status) ) {
|
|||
|
ImageFileName = &NullString;
|
|||
|
}
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( ClientToken )) {
|
|||
|
|
|||
|
CapturedUserSid = SepTokenUserSid( ClientToken );
|
|||
|
ClientAuthenticationId = SepTokenAuthenticationId( ClientToken );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
CapturedUserSid = SepTokenUserSid( PrimaryToken );
|
|||
|
}
|
|||
|
|
|||
|
PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken );
|
|||
|
|
|||
|
//
|
|||
|
// A completely zero'd entry will be interpreted
|
|||
|
// as a "null string" or not supplied parameter.
|
|||
|
//
|
|||
|
// Initializing the entire array up front will allow
|
|||
|
// us to avoid filling in each not supplied entry.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory (
|
|||
|
(PVOID) &AuditParameters,
|
|||
|
sizeof( AuditParameters )
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
ASSERT( ( AuditType == AuditCategoryObjectAccess ) ||
|
|||
|
( AuditType == AuditCategoryDirectoryServiceAccess ) );
|
|||
|
|
|||
|
if (AuditType == AuditCategoryObjectAccess) {
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS;
|
|||
|
} else {
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_DS_ACCESS;
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.AuditId = SE_AUDITID_OPEN_HANDLE;
|
|||
|
AuditParameters.ParameterCount = 0;
|
|||
|
|
|||
|
if ( AccessGranted ) {
|
|||
|
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[0] - User Sid
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, CapturedUserSid );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[1] - Subsystem name (if available)
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[2] - Object Server (if available)
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[3] - Object Type Name
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( CapturedObjectTypeName )) {
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedObjectTypeName );
|
|||
|
}
|
|||
|
|
|||
|
ObjectTypeIndex = AuditParameters.ParameterCount;
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[4] - Object Name
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( CapturedObjectName )) {
|
|||
|
|
|||
|
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, CapturedObjectName );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[5] - New handle ID
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( HandleId )) {
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, *HandleId );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( OperationId )) {
|
|||
|
|
|||
|
SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, (*OperationId).HighPart );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, (*OperationId).LowPart );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
AuditParameters.ParameterCount += 2;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[6] - Subject's process id
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessID );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[7] - Subject's Image Name
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
|||
|
AuditParameters.ParameterCount ++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[8] - Subject's primary authentication ID
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, PrimaryAuthenticationId );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[9] - Subject's client authentication ID
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( ClientToken )) {
|
|||
|
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, ClientAuthenticationId );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[10] - DesiredAccess mask
|
|||
|
//
|
|||
|
|
|||
|
if ( AccessGranted ) {
|
|||
|
|
|||
|
SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, GrantedAccess, ObjectTypeIndex );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, DesiredAccess, ObjectTypeIndex );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[11] - Privileges used for open
|
|||
|
//
|
|||
|
|
|||
|
if ( (CapturedPrivileges != NULL) && (CapturedPrivileges->PrivilegeCount > 0) ) {
|
|||
|
|
|||
|
SepSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, CapturedPrivileges );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[12] - ObjectTypes of Audited objects/parameter sets/parameters
|
|||
|
//
|
|||
|
|
|||
|
if ( ObjectTypeListLength != 0 ) {
|
|||
|
ULONG GuidCount;
|
|||
|
ULONG i;
|
|||
|
USHORT FlagMask = AccessGranted ? OBJECT_SUCCESS_AUDIT : OBJECT_FAILURE_AUDIT;
|
|||
|
|
|||
|
//
|
|||
|
// Count the number of GUIDs to audit.
|
|||
|
//
|
|||
|
|
|||
|
GuidCount = 0;
|
|||
|
for ( i=0; i<ObjectTypeListLength; i++ ) {
|
|||
|
|
|||
|
if ( i == 0 ) {
|
|||
|
GuidCount++;
|
|||
|
} else if ( ObjectTypeList[i].Flags & FlagMask ) {
|
|||
|
GuidCount ++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If there are any Guids to audit,
|
|||
|
// copy them into a locally allocated buffer.
|
|||
|
//
|
|||
|
|
|||
|
if ( GuidCount > 0 ) {
|
|||
|
|
|||
|
AdtObjectTypeBuffer = ExAllocatePoolWithTag( PagedPool, GuidCount * sizeof(SE_ADT_OBJECT_TYPE), 'pAeS' );
|
|||
|
|
|||
|
//
|
|||
|
// If the buffer can be allocated,
|
|||
|
// fill it in.
|
|||
|
// If not,
|
|||
|
// generate a truncated audit.
|
|||
|
//
|
|||
|
|
|||
|
if ( AdtObjectTypeBuffer != NULL ) {
|
|||
|
|
|||
|
//
|
|||
|
// Copy the GUIDs and optional access masks to the buffer.
|
|||
|
//
|
|||
|
|
|||
|
GuidCount = 0;
|
|||
|
for ( i=0; i<ObjectTypeListLength; i++ ) {
|
|||
|
|
|||
|
if ( ( i > 0 ) && !( ObjectTypeList[i].Flags & FlagMask ) ) {
|
|||
|
|
|||
|
continue;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
AdtObjectTypeBuffer[GuidCount].ObjectType = ObjectTypeList[i].ObjectType;
|
|||
|
AdtObjectTypeBuffer[GuidCount].Level = ObjectTypeList[i].Level;
|
|||
|
|
|||
|
if ( i == 0 ) {
|
|||
|
//
|
|||
|
// Always copy the GUID representing the object itself.
|
|||
|
// Mark it as a such to avoid including it in the audit.
|
|||
|
//
|
|||
|
AdtObjectTypeBuffer[GuidCount].Flags = SE_ADT_OBJECT_ONLY;
|
|||
|
AdtObjectTypeBuffer[GuidCount].AccessMask = 0;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
AdtObjectTypeBuffer[GuidCount].Flags = 0;
|
|||
|
if ( ARGUMENT_PRESENT(GrantedAccessArray) && AccessGranted ) {
|
|||
|
|
|||
|
AdtObjectTypeBuffer[GuidCount].AccessMask = GrantedAccessArray[i];
|
|||
|
}
|
|||
|
}
|
|||
|
GuidCount ++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Store the Object Types.
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeObjectTypes( AuditParameters, AuditParameters.ParameterCount, AdtObjectTypeBuffer, GuidCount, ObjectTypeIndex );
|
|||
|
AuditParameters.ParameterCount ++;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_OPEN_HANDLE_OBJECT_TYPE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[13] - Restricted Sids in token
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, PrimaryToken->RestrictedSidCount );
|
|||
|
AuditParameters.ParameterCount ++;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Audit it.
|
|||
|
//
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
|
|||
|
if ( AdtObjectTypeBuffer != NULL ) {
|
|||
|
ExFreePool( AdtObjectTypeBuffer );
|
|||
|
}
|
|||
|
|
|||
|
if ( ImageFileName != &NullString ) {
|
|||
|
ExFreePool( ImageFileName );
|
|||
|
}
|
|||
|
|
|||
|
return( TRUE );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
SepAdtOpenObjectForDeleteAuditAlarm (
|
|||
|
IN PUNICODE_STRING CapturedSubsystemName,
|
|||
|
IN PVOID *HandleId OPTIONAL,
|
|||
|
IN PUNICODE_STRING CapturedObjectTypeName,
|
|||
|
IN PUNICODE_STRING CapturedObjectName OPTIONAL,
|
|||
|
IN PTOKEN ClientToken OPTIONAL,
|
|||
|
IN PTOKEN PrimaryToken,
|
|||
|
IN ACCESS_MASK DesiredAccess,
|
|||
|
IN ACCESS_MASK GrantedAccess,
|
|||
|
IN PLUID OperationId,
|
|||
|
IN PPRIVILEGE_SET CapturedPrivileges OPTIONAL,
|
|||
|
IN BOOLEAN AccessGranted,
|
|||
|
IN HANDLE ProcessID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Implements SeOpenObjectForDeleteAuditAlarm after parameters have been
|
|||
|
captured.
|
|||
|
|
|||
|
This routine is used to generate audit and alarm messages when an
|
|||
|
attempt is made to access an existing protected subsystem object or
|
|||
|
create a new one. This routine may result in several messages being
|
|||
|
generated and sent to Port objects. This may result in a significant
|
|||
|
latency before returning. Design of routines that must call this
|
|||
|
routine must take this potential latency into account. This may have
|
|||
|
an impact on the approach taken for data structure mutex locking, for
|
|||
|
example. This API requires the caller have SeTcbPrivilege privilege.
|
|||
|
The test for this privilege is always against the primary token of the
|
|||
|
calling process, not the impersonation token of the thread.
|
|||
|
|
|||
|
|
|||
|
This routine will create an SE_ADT_PARAMETERS array organized as follows:
|
|||
|
|
|||
|
Parameter[0] - User Sid
|
|||
|
|
|||
|
Parameter[1] - Subsystem name (if available)
|
|||
|
|
|||
|
Parameter[2] - Server name (if available)
|
|||
|
|
|||
|
Parameter[3] - Object Type Name
|
|||
|
|
|||
|
Parameter[4] - Object Name
|
|||
|
|
|||
|
Parameter[5] - New handle ID
|
|||
|
|
|||
|
Parameter[6] - Subject's process id
|
|||
|
|
|||
|
Parameter[7] - Subject's primary authentication ID
|
|||
|
|
|||
|
Parameter[8] - Subject's client authentication ID
|
|||
|
|
|||
|
Parameter[9] - DesiredAccess mask
|
|||
|
|
|||
|
Parameter[10] - Privileges used for open
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CapturedSubsystemName - Supplies a name string identifying the
|
|||
|
subsystem calling the routine.
|
|||
|
|
|||
|
HandleId - A unique value representing the client's handle to the
|
|||
|
object. If the access attempt was not successful (AccessGranted is
|
|||
|
FALSE), then this parameter is ignored.
|
|||
|
|
|||
|
CapturedObjectTypeName - Supplies the name of the type of object being
|
|||
|
accessed.
|
|||
|
|
|||
|
CapturedObjectName - Supplies the name of the object the client
|
|||
|
accessed or attempted to access.
|
|||
|
|
|||
|
CapturedSecurityDescriptor - A pointer to the security descriptor of
|
|||
|
the object being accessed.
|
|||
|
|
|||
|
ClientToken - Optionally provides a pointer to the client token
|
|||
|
(only if the caller is currently impersonating)
|
|||
|
|
|||
|
PrimaryToken - Provides a pointer to the caller's primary token.
|
|||
|
|
|||
|
DesiredAccess - The desired access mask. This mask must have been
|
|||
|
previously mapped to contain no generic accesses.
|
|||
|
|
|||
|
GrantedAccess - The mask of accesses that were actually granted.
|
|||
|
|
|||
|
CapturedPrivileges - Optionally points to a set of privileges that were
|
|||
|
required for the access attempt. Those privileges that were held
|
|||
|
by the subject are marked using the UsedForAccess flag of the
|
|||
|
attributes associated with each privilege.
|
|||
|
|
|||
|
ObjectCreation - A boolean flag indicating whether the access will
|
|||
|
result in a new object being created if granted. A value of TRUE
|
|||
|
indicates an object will be created, FALSE indicates an existing
|
|||
|
object will be opened.
|
|||
|
|
|||
|
AccessGranted - Indicates whether the requested access was granted or
|
|||
|
not. A value of TRUE indicates the access was granted. A value of
|
|||
|
FALSE indicates the access was not granted.
|
|||
|
|
|||
|
GenerateOnClose - Points to a boolean that is set by the audit
|
|||
|
generation routine and must be passed to NtCloseObjectAuditAlarm()
|
|||
|
when the object handle is closed.
|
|||
|
|
|||
|
GenerateAudit - Indicates if we should generate an audit for this operation.
|
|||
|
|
|||
|
GenerateAlarm - Indicates if we should generate an alarm for this operation.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns TRUE if audit is generated, FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|||
|
ULONG ObjectTypeIndex;
|
|||
|
PSID CapturedUserSid;
|
|||
|
LUID PrimaryAuthenticationId;
|
|||
|
LUID ClientAuthenticationId;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( ClientToken )) {
|
|||
|
|
|||
|
CapturedUserSid = SepTokenUserSid( ClientToken );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
CapturedUserSid = SepTokenUserSid( PrimaryToken );
|
|||
|
}
|
|||
|
|
|||
|
PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken );
|
|||
|
|
|||
|
//
|
|||
|
// A completely zero'd entry will be interpreted
|
|||
|
// as a "null string" or not supplied parameter.
|
|||
|
//
|
|||
|
// Initializing the entire array up front will allow
|
|||
|
// us to avoid filling in each not supplied entry.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory (
|
|||
|
(PVOID) &AuditParameters,
|
|||
|
sizeof( AuditParameters )
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_OPEN_OBJECT_FOR_DELETE;
|
|||
|
AuditParameters.ParameterCount = 0;
|
|||
|
|
|||
|
if ( AccessGranted ) {
|
|||
|
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[0] - User Sid
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, CapturedUserSid );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[1] - Subsystem name (if available)
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[2] - Object Server (if available)
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[3] - Object Type Name
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( CapturedObjectTypeName )) {
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedObjectTypeName );
|
|||
|
}
|
|||
|
|
|||
|
ObjectTypeIndex = AuditParameters.ParameterCount;
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[4] - Object Name
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( CapturedObjectName )) {
|
|||
|
|
|||
|
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, CapturedObjectName );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[5] - New handle ID
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( HandleId )) {
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, *HandleId );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( OperationId )) {
|
|||
|
|
|||
|
SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, (*OperationId).HighPart );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, (*OperationId).LowPart );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
AuditParameters.ParameterCount += 2;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[6] - Subject's process id
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessID );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[7] - Subject's primary authentication ID
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, PrimaryAuthenticationId );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[8] - Subject's client authentication ID
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( ClientToken )) {
|
|||
|
|
|||
|
ClientAuthenticationId = SepTokenAuthenticationId( ClientToken );
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, ClientAuthenticationId );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[9] - DesiredAccess mask
|
|||
|
//
|
|||
|
|
|||
|
if ( AccessGranted ) {
|
|||
|
|
|||
|
SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, GrantedAccess, ObjectTypeIndex );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, DesiredAccess, ObjectTypeIndex );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[10] - Privileges used for open
|
|||
|
//
|
|||
|
|
|||
|
if ( (CapturedPrivileges != NULL) && (CapturedPrivileges->PrivilegeCount > 0) ) {
|
|||
|
|
|||
|
SepSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, CapturedPrivileges );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
|
|||
|
return( TRUE );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SepAdtCloseObjectAuditAlarm (
|
|||
|
IN PUNICODE_STRING CapturedSubsystemName,
|
|||
|
IN PVOID HandleId,
|
|||
|
IN PSID UserSid
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements NtCloseObjectAuditAlarm after parameters have
|
|||
|
been captured.
|
|||
|
|
|||
|
This routine is used to generate audit and alarm messages when a handle
|
|||
|
to a protected subsystem object is deleted. This routine may result in
|
|||
|
several messages being generated and sent to Port objects. This may
|
|||
|
result in a significant latency before returning. Design of routines
|
|||
|
that must call this routine must take this potential latency into
|
|||
|
account. This may have an impact on the approach taken for data
|
|||
|
structure mutex locking, for example.
|
|||
|
|
|||
|
This API requires the caller have SeTcbPrivilege privilege. The test
|
|||
|
for this privilege is always against the primary token of the calling
|
|||
|
process, allowing the caller to be impersonating a client during the
|
|||
|
call with no ill effects. It is assumed that this privilege has been
|
|||
|
tested at a higher level.
|
|||
|
|
|||
|
This routine will create an SE_ADT_PARAMETERS array organized as follows:
|
|||
|
|
|||
|
Parameter[0] - User Sid
|
|||
|
|
|||
|
Parameter[1] - Subsystem name (if available)
|
|||
|
|
|||
|
Parameter[2] - New handle ID
|
|||
|
|
|||
|
Parameter[3] - Subject's process id
|
|||
|
|
|||
|
Parameter[4] - Image file name
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CapturedSubsystemName - Supplies a name string identifying the
|
|||
|
subsystem calling the routine.
|
|||
|
|
|||
|
HandleId - A unique value representing the client's handle to the
|
|||
|
object.
|
|||
|
|
|||
|
Object - The address of the object being closed
|
|||
|
|
|||
|
UserSid - The Sid identifying the current caller.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Return value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|||
|
BOOLEAN AccessGranted = TRUE;
|
|||
|
HANDLE ProcessId;
|
|||
|
PEPROCESS Process = NULL;
|
|||
|
PUNICODE_STRING ImageFileName;
|
|||
|
UNICODE_STRING NullString = {0};
|
|||
|
NTSTATUS Status;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if ( SepAuditOptions.DoNotAuditCloseObjectEvents ) {
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ( SepAdtAuditThisEvent( AuditCategoryObjectAccess, &AccessGranted ) ) {
|
|||
|
|
|||
|
Process = PsGetCurrentProcess();
|
|||
|
ProcessId = PsProcessAuditId( Process );
|
|||
|
|
|||
|
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
|||
|
|
|||
|
if ( !NT_SUCCESS(Status) ) {
|
|||
|
ImageFileName = &NullString;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// A completely zero'd entry will be interpreted
|
|||
|
// as a "null string" or not supplied parameter.
|
|||
|
//
|
|||
|
// Initializing the entire array up front will allow
|
|||
|
// us to avoid filling in each not supplied entry.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory (
|
|||
|
(PVOID) &AuditParameters,
|
|||
|
sizeof( AuditParameters )
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_CLOSE_HANDLE;
|
|||
|
AuditParameters.ParameterCount = 0;
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[0] - User Sid
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[1] - Subsystem name (if available)
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[2] - Subsystem name (if available)
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[3] - New handle ID
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, HandleId );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[4] - Subject's process id
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[5] - Subject's Image Name
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
|||
|
AuditParameters.ParameterCount ++;
|
|||
|
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
|
|||
|
if ( ImageFileName != &NullString ) {
|
|||
|
ExFreePool( ImageFileName );
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SepAdtDeleteObjectAuditAlarm (
|
|||
|
IN PUNICODE_STRING CapturedSubsystemName,
|
|||
|
IN PVOID HandleId,
|
|||
|
IN PSID UserSid
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements NtDeleteObjectAuditAlarm after parameters have
|
|||
|
been captured.
|
|||
|
|
|||
|
This routine is used to generate audit and alarm messages when an object
|
|||
|
in a protected subsystem object is deleted. This routine may result in
|
|||
|
several messages being generated and sent to Port objects. This may
|
|||
|
result in a significant latency before returning. Design of routines
|
|||
|
that must call this routine must take this potential latency into
|
|||
|
account. This may have an impact on the approach taken for data
|
|||
|
structure mutex locking, for example.
|
|||
|
|
|||
|
This API requires the caller have SeTcbPrivilege privilege. The test
|
|||
|
for this privilege is always against the primary token of the calling
|
|||
|
process, allowing the caller to be impersonating a client during the
|
|||
|
call with no ill effects. It is assumed that this privilege has been
|
|||
|
tested at a higher level.
|
|||
|
|
|||
|
This routine will create an SE_ADT_PARAMETERS array organized as follows:
|
|||
|
|
|||
|
Parameter[0] - User Sid
|
|||
|
|
|||
|
Parameter[1] - Subsystem name (if available)
|
|||
|
|
|||
|
Parameter[2] - Handle ID
|
|||
|
|
|||
|
Parameter[3] - Subject's process id
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CapturedSubsystemName - Supplies a name string identifying the
|
|||
|
subsystem calling the routine.
|
|||
|
|
|||
|
HandleId - A unique value representing the client's handle to the
|
|||
|
object.
|
|||
|
|
|||
|
Object - The address of the object being closed
|
|||
|
|
|||
|
UserSid - The Sid identifying the current caller.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Return value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|||
|
BOOLEAN AccessGranted = TRUE;
|
|||
|
HANDLE ProcessId;
|
|||
|
PUNICODE_STRING ImageFileName = NULL;
|
|||
|
UNICODE_STRING NullString = {0};
|
|||
|
PEPROCESS Process = NULL;
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if ( SepAdtAuditThisEvent( AuditCategoryObjectAccess, &AccessGranted ) ) {
|
|||
|
|
|||
|
Process = PsGetCurrentProcess();
|
|||
|
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
|||
|
|
|||
|
if ( !NT_SUCCESS(Status) ) {
|
|||
|
ImageFileName = &NullString;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// A completely zero'd entry will be interpreted
|
|||
|
// as a "null string" or not supplied parameter.
|
|||
|
//
|
|||
|
// Initializing the entire array up front will allow
|
|||
|
// us to avoid filling in each not supplied entry.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory (
|
|||
|
(PVOID) &AuditParameters,
|
|||
|
sizeof( AuditParameters )
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_DELETE_OBJECT;
|
|||
|
AuditParameters.ParameterCount = 0;
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[0] - User Sid
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[1] - Subsystem name (if available)
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[2] - Subsystem name (if available)
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[3] - New handle ID
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, HandleId );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[4] - Subject's process id
|
|||
|
//
|
|||
|
|
|||
|
ProcessId = PsProcessAuditId( PsGetCurrentProcess() );
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[5] - Subject's Image Name
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
|||
|
AuditParameters.ParameterCount ++;
|
|||
|
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
|
|||
|
if (ImageFileName != &NullString) {
|
|||
|
ExFreePool(ImageFileName);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
SeOperationAuditAlarm (
|
|||
|
IN PUNICODE_STRING CapturedSubsystemName OPTIONAL,
|
|||
|
IN PVOID HandleId,
|
|||
|
IN PUNICODE_STRING ObjectTypeName,
|
|||
|
IN ACCESS_MASK AuditMask,
|
|||
|
IN PSID UserSid OPTIONAL
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine generates an "operation-based" audit.
|
|||
|
|
|||
|
This routine may result in several messages being generated and sent
|
|||
|
to Port objects. This may result in a significant latency before
|
|||
|
returning. Design of routines that must call this routine must take
|
|||
|
this potential latency into account. This may have an impact on the
|
|||
|
approach taken for data structure mutex locking, for example.
|
|||
|
|
|||
|
This API requires the caller have SeTcbPrivilege privilege. The test
|
|||
|
for this privilege is always against the primary token of the calling
|
|||
|
process, allowing the caller to be impersonating a client during the
|
|||
|
call with no ill effects. It is assumed that this privilege has been
|
|||
|
tested at a higher level.
|
|||
|
|
|||
|
This routine will create an SE_ADT_PARAMETERS array organized as follows:
|
|||
|
|
|||
|
Parameter[0] - User Sid
|
|||
|
|
|||
|
Parameter[1] - Subsystem name (if available)
|
|||
|
|
|||
|
Parameter[2] - Handle ID
|
|||
|
|
|||
|
Parameter[3] - Subject's process id
|
|||
|
|
|||
|
Parameter[4] - Audit mask
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CapturedSubsystemName - Supplies a name string identifying the
|
|||
|
subsystem calling the routine.
|
|||
|
|
|||
|
HandleId - A unique value representing the client's handle to the
|
|||
|
object.
|
|||
|
|
|||
|
ObjectTypeName - The type of the object being accessed.
|
|||
|
|
|||
|
AuditMask - Mask of bits being audited.
|
|||
|
|
|||
|
UserSid - Optionally supplies the user sid.
|
|||
|
|
|||
|
Return value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|||
|
BOOLEAN AccessGranted = TRUE;
|
|||
|
HANDLE ProcessId;
|
|||
|
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
|
|||
|
ULONG ObjectTypeIndex;
|
|||
|
PUNICODE_STRING SubsystemName;
|
|||
|
NTSTATUS Status;
|
|||
|
UNICODE_STRING NullString = {0};
|
|||
|
PUNICODE_STRING ImageFileName = NULL;
|
|||
|
PEPROCESS Process = NULL;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
Process = PsGetCurrentProcess();
|
|||
|
ProcessId = PsProcessAuditId( Process );
|
|||
|
|
|||
|
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
|||
|
|
|||
|
if ( !NT_SUCCESS(Status) ) {
|
|||
|
ImageFileName = &NullString;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// A completely zero'd entry will be interpreted
|
|||
|
// as a "null string" or not supplied parameter.
|
|||
|
//
|
|||
|
// Initializing the entire array up front will allow
|
|||
|
// us to avoid filling in each not supplied entry.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory (
|
|||
|
(PVOID) &AuditParameters,
|
|||
|
sizeof( AuditParameters )
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_OBJECT_ACCESS;
|
|||
|
AuditParameters.ParameterCount = 0;
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|||
|
|
|||
|
//
|
|||
|
// If the user's SID was not passed, get it out of the current
|
|||
|
// subject context
|
|||
|
//
|
|||
|
|
|||
|
SeCaptureSubjectContext( &SubjectSecurityContext );
|
|||
|
|
|||
|
UserSid = SepTokenUserSid( EffectiveToken( &SubjectSecurityContext ));
|
|||
|
|
|||
|
if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
|||
|
|
|||
|
SubsystemName = (PUNICODE_STRING)&SeSubsystemName;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SubsystemName = CapturedSubsystemName;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[0] - User Sid
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[1] - Subsystem name (if available)
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[2] - Subsystem name (if available)
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[3] - New handle ID
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, HandleId );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[4] - Object Type Name
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, ObjectTypeName );
|
|||
|
ObjectTypeIndex = AuditParameters.ParameterCount;
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[5] - Subject's process id
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[6] - Subject's process name
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[7] - Audit Mask
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, AuditMask, ObjectTypeIndex );
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
|
|||
|
if ( ImageFileName != &NullString ) {
|
|||
|
ExFreePool( ImageFileName );
|
|||
|
}
|
|||
|
|
|||
|
SeReleaseSubjectContext( &SubjectSecurityContext );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SepAdtObjectReferenceAuditAlarm(
|
|||
|
IN PVOID Object,
|
|||
|
IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
|
|||
|
IN ACCESS_MASK DesiredAccess,
|
|||
|
IN BOOLEAN AccessGranted
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
description-of-function.
|
|||
|
|
|||
|
This routine will create an SE_ADT_PARAMETERS array organized as follows:
|
|||
|
|
|||
|
Parameter[0] - User Sid
|
|||
|
|
|||
|
Parameter[1] - Subsystem name (if available)
|
|||
|
|
|||
|
Parameter[2] - Object Type Name
|
|||
|
|
|||
|
Parameter[3] - Object Name
|
|||
|
|
|||
|
Parameter[4] - Subject's process id
|
|||
|
|
|||
|
Parameter[5] - Subject's primary authentication ID
|
|||
|
|
|||
|
Parameter[6] - Subject's client authentication ID
|
|||
|
|
|||
|
Parameter[7] - DesiredAccess mask
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
return-value - Description of conditions needed to return value. - or -
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|||
|
ULONG ObjectTypeIndex;
|
|||
|
POBJECT_NAME_INFORMATION ObjectNameInformation;
|
|||
|
PUNICODE_STRING ObjectTypeInformation;
|
|||
|
PSID UserSid;
|
|||
|
LUID PrimaryAuthenticationId;
|
|||
|
LUID ClientAuthenticationId;
|
|||
|
|
|||
|
PTOKEN ClientToken = (PTOKEN)SubjectSecurityContext->ClientToken;
|
|||
|
PTOKEN PrimaryToken = (PTOKEN)SubjectSecurityContext->PrimaryToken;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( ClientToken )) {
|
|||
|
|
|||
|
UserSid = SepTokenUserSid( ClientToken );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
UserSid = SepTokenUserSid( PrimaryToken );
|
|||
|
}
|
|||
|
|
|||
|
PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken );
|
|||
|
|
|||
|
//
|
|||
|
// A completely zero'd entry will be interpreted
|
|||
|
// as a "null string" or not supplied parameter.
|
|||
|
//
|
|||
|
// Initializing the entire array up front will allow
|
|||
|
// us to avoid filling in each not supplied entry.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory (
|
|||
|
(PVOID) &AuditParameters,
|
|||
|
sizeof( AuditParameters )
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_INDIRECT_REFERENCE;
|
|||
|
AuditParameters.ParameterCount = 8;
|
|||
|
|
|||
|
if ( AccessGranted ) {
|
|||
|
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Obtain the object name and object type name from the
|
|||
|
// object.
|
|||
|
//
|
|||
|
|
|||
|
ObjectNameInformation = SepQueryNameString( Object );
|
|||
|
|
|||
|
|
|||
|
ObjectTypeInformation = SepQueryTypeString( Object );
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[0] - User Sid
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, 0, UserSid );
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[1] - Subsystem name (if available)
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, 1, (PUNICODE_STRING)&SeSubsystemName );
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[2] - Object Type Name
|
|||
|
//
|
|||
|
|
|||
|
if ( ObjectTypeInformation != NULL ) {
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, 2, ObjectTypeInformation );
|
|||
|
}
|
|||
|
|
|||
|
ObjectTypeIndex = 2;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[3] - Object Name
|
|||
|
//
|
|||
|
|
|||
|
if ( ObjectNameInformation != NULL ) {
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, 3, &ObjectNameInformation->Name );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[4] - Subject's process id
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, 4, SubjectSecurityContext->ProcessAuditId );
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[5] - Subject's primary authentication ID
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
SepSetParmTypeLogonId( AuditParameters, 5, PrimaryAuthenticationId );
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[6] - Subject's client authentication ID
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( ClientToken )) {
|
|||
|
|
|||
|
ClientAuthenticationId = SepTokenAuthenticationId( ClientToken );
|
|||
|
SepSetParmTypeLogonId( AuditParameters, 6, ClientAuthenticationId );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SepSetParmTypeNoLogon( AuditParameters, 6 );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Parameter[7] - DesiredAccess mask
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
SepSetParmTypeAccessMask( AuditParameters, 7, DesiredAccess, ObjectTypeIndex );
|
|||
|
|
|||
|
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
|
|||
|
if ( ObjectNameInformation != NULL ) {
|
|||
|
ExFreePool( ObjectNameInformation );
|
|||
|
}
|
|||
|
|
|||
|
if ( ObjectTypeInformation != NULL ) {
|
|||
|
ExFreePool( ObjectTypeInformation );
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
POBJECT_NAME_INFORMATION
|
|||
|
SepQueryNameString(
|
|||
|
IN PVOID Object
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Takes a pointer to an object and returns the name of the object.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Object - a pointer to an object.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A pointer to a buffer containing a POBJECT_NAME_INFORMATION
|
|||
|
structure containing the name of the object. The string is
|
|||
|
allocated out of paged pool and should be freed by the caller.
|
|||
|
|
|||
|
NULL may also be returned.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
ULONG ReturnLength = 0;
|
|||
|
POBJECT_NAME_INFORMATION ObjectNameInfo = NULL;
|
|||
|
PUNICODE_STRING ObjectName = NULL;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
Status = ObQueryNameString(
|
|||
|
Object,
|
|||
|
ObjectNameInfo,
|
|||
|
0,
|
|||
|
&ReturnLength
|
|||
|
);
|
|||
|
|
|||
|
if ( Status == STATUS_INFO_LENGTH_MISMATCH ) {
|
|||
|
|
|||
|
ObjectNameInfo = ExAllocatePoolWithTag( PagedPool, ReturnLength, 'nOeS' );
|
|||
|
|
|||
|
if ( ObjectNameInfo != NULL ) {
|
|||
|
|
|||
|
Status = ObQueryNameString(
|
|||
|
Object,
|
|||
|
ObjectNameInfo,
|
|||
|
ReturnLength,
|
|||
|
&ReturnLength
|
|||
|
);
|
|||
|
|
|||
|
if ( NT_SUCCESS( Status )) {
|
|||
|
|
|||
|
if (ObjectNameInfo->Name.Length != 0) {
|
|||
|
|
|||
|
return( ObjectNameInfo );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
ExFreePool( ObjectNameInfo );
|
|||
|
return( NULL );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return( NULL );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
PUNICODE_STRING
|
|||
|
SepQueryTypeString(
|
|||
|
IN PVOID Object
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Takes a pointer to an object and returns the type of the object.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Object - a pointer to an object.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A pointer to a UNICODE_STRING that contains the name of the object
|
|||
|
type. The string is allocated out of paged pool and should be freed
|
|||
|
by the caller.
|
|||
|
|
|||
|
NULL may also be returned.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
NTSTATUS Status;
|
|||
|
PUNICODE_STRING TypeName = NULL;
|
|||
|
ULONG ReturnLength;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
Status = ObQueryTypeName(
|
|||
|
Object,
|
|||
|
TypeName,
|
|||
|
0,
|
|||
|
&ReturnLength
|
|||
|
);
|
|||
|
|
|||
|
if ( Status == STATUS_INFO_LENGTH_MISMATCH ) {
|
|||
|
|
|||
|
TypeName = ExAllocatePoolWithTag( PagedPool, ReturnLength, 'nTeS' );
|
|||
|
|
|||
|
if ( TypeName != NULL ) {
|
|||
|
|
|||
|
Status = ObQueryTypeName(
|
|||
|
Object,
|
|||
|
TypeName,
|
|||
|
ReturnLength,
|
|||
|
&ReturnLength
|
|||
|
);
|
|||
|
|
|||
|
if ( NT_SUCCESS( Status )) {
|
|||
|
|
|||
|
return( TypeName );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return( NULL );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SeAuditProcessCreation(
|
|||
|
PEPROCESS Process
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Audits the creation of a process. It is the caller's responsibility
|
|||
|
to determine if process auditing is in progress.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Process - Points to the new process object.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ANSI_STRING Ansi;
|
|||
|
LUID UserAuthenticationId;
|
|||
|
NTSTATUS Status;
|
|||
|
PSID UserSid;
|
|||
|
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|||
|
HANDLE ProcessId;
|
|||
|
HANDLE ParentProcessId;
|
|||
|
PUNICODE_STRING ImageFileName;
|
|||
|
UNICODE_STRING NullString = {0};
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Set up the various data that will be needed for the audit:
|
|||
|
// - process id
|
|||
|
// - parent's process id
|
|||
|
// - image file name (unicode)
|
|||
|
//
|
|||
|
|
|||
|
ProcessId = Process->UniqueProcessId;
|
|||
|
ParentProcessId = Process->InheritedFromUniqueProcessId;
|
|||
|
|
|||
|
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
|||
|
|
|||
|
if ( !NT_SUCCESS(Status) ) {
|
|||
|
ImageFileName = &NullString;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// NtCreateProcess with no section will cause this to be NULL
|
|||
|
// fork() for posix will do this, or someone calling NtCreateProcess
|
|||
|
// directly.
|
|||
|
//
|
|||
|
|
|||
|
SeCaptureSubjectContext( &SubjectSecurityContext );
|
|||
|
|
|||
|
RtlZeroMemory (
|
|||
|
(PVOID) &AuditParameters,
|
|||
|
sizeof( AuditParameters )
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_PROCESS_CREATED;
|
|||
|
AuditParameters.ParameterCount = 0;
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|||
|
|
|||
|
//
|
|||
|
// Use the primary token here, because that's what's going to show up
|
|||
|
// when the created process exits.
|
|||
|
//
|
|||
|
|
|||
|
UserSid = SepTokenUserSid( SubjectSecurityContext.PrimaryToken );
|
|||
|
|
|||
|
UserAuthenticationId = SepTokenAuthenticationId( SubjectSecurityContext.PrimaryToken );
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the AuditParameters structure.
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ParentProcessId );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, UserAuthenticationId );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
|
|||
|
SeReleaseSubjectContext( &SubjectSecurityContext );
|
|||
|
|
|||
|
if ( ImageFileName != &NullString ) {
|
|||
|
ExFreePool( ImageFileName );
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SeAuditHandleDuplication(
|
|||
|
PVOID SourceHandle,
|
|||
|
PVOID NewHandle,
|
|||
|
PEPROCESS SourceProcess,
|
|||
|
PEPROCESS TargetProcess
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine generates a handle duplication audit. It is up to the caller
|
|||
|
to determine if this routine should be called or not.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SourceHandle - Original handle
|
|||
|
|
|||
|
NewHandle - New handle
|
|||
|
|
|||
|
SourceProcess - Process containing SourceHandle
|
|||
|
|
|||
|
TargetProcess - Process containing NewHandle
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|||
|
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
|
|||
|
PSID UserSid;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
SeCaptureSubjectContext( &SubjectSecurityContext );
|
|||
|
|
|||
|
UserSid = SepTokenUserSid( EffectiveToken( &SubjectSecurityContext ));
|
|||
|
|
|||
|
RtlZeroMemory (
|
|||
|
(PVOID) &AuditParameters,
|
|||
|
sizeof( AuditParameters )
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_DUPLICATE_HANDLE;
|
|||
|
AuditParameters.ParameterCount = 0;
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, SourceHandle );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, PsProcessAuditId( SourceProcess ));
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, NewHandle );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, PsProcessAuditId( TargetProcess ));
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
|
|||
|
SeReleaseSubjectContext( &SubjectSecurityContext );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SeAuditProcessExit(
|
|||
|
PEPROCESS Process
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Audits the exit of a process. The caller is responsible for
|
|||
|
determining if this should be called.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Process - Pointer to the process object that is exiting.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PTOKEN Token;
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|||
|
PSID UserSid;
|
|||
|
LUID LogonId;
|
|||
|
HANDLE ProcessId;
|
|||
|
PUNICODE_STRING ImageFileName;
|
|||
|
UNICODE_STRING NullString = {0};
|
|||
|
NTSTATUS Status;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
Token = (PTOKEN) PsReferencePrimaryToken (Process);
|
|||
|
|
|||
|
UserSid = SepTokenUserSid( Token );
|
|||
|
LogonId = SepTokenAuthenticationId( Token );
|
|||
|
|
|||
|
RtlZeroMemory (
|
|||
|
(PVOID) &AuditParameters,
|
|||
|
sizeof( AuditParameters )
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
|||
|
|
|||
|
if ( !NT_SUCCESS(Status) ) {
|
|||
|
ImageFileName = &NullString;
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_PROCESS_EXIT;
|
|||
|
AuditParameters.ParameterCount = 0;
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
ProcessId = PsProcessAuditId( Process );
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, LogonId );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
|
|||
|
PsDereferencePrimaryToken( Token );
|
|||
|
|
|||
|
if ( ImageFileName != &NullString ) {
|
|||
|
ExFreePool( ImageFileName );
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SepAdtGenerateDiscardAudit(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Generates an 'audits discarded' audit.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|||
|
PSID UserSid;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
UserSid = SeLocalSystemSid;
|
|||
|
|
|||
|
RtlZeroMemory (
|
|||
|
(PVOID) &AuditParameters,
|
|||
|
sizeof( AuditParameters )
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_SYSTEM;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_AUDITS_DISCARDED;
|
|||
|
AuditParameters.ParameterCount = 0;
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, SepAdtCountEventsDiscarded );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SeInitializeProcessAuditName (
|
|||
|
IN PVOID FileObject,
|
|||
|
IN BOOLEAN bIgnoreAuditPolicy,
|
|||
|
OUT POBJECT_NAME_INFORMATION *pAuditName
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine initializes the executable name for auditing purposes. It allocates memory for the
|
|||
|
image file name. This memory is pointed to by pAuditName.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileObject - Supplies a pointer to a file object for the image being
|
|||
|
executed.
|
|||
|
|
|||
|
bIgnoreAuditPolicy - boolean that indicates that the call should proceed without
|
|||
|
regard to the system's auditing policy.
|
|||
|
|
|||
|
pAuditName - Supplies a pointer to a pointer for the object name information.
|
|||
|
|
|||
|
Return value:
|
|||
|
|
|||
|
NTSTATUS.
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
KeAttached to the target process so not all system services are available.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
OBJECT_NAME_INFORMATION TempNameInfo;
|
|||
|
ULONG ObjectNameInformationLength;
|
|||
|
POBJECT_NAME_INFORMATION pInternalAuditName;
|
|||
|
PFILE_OBJECT FilePointer;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
ASSERT (pAuditName != NULL);
|
|||
|
*pAuditName = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Check if the caller would like to get the process name, even if auditing does not
|
|||
|
// require it.
|
|||
|
//
|
|||
|
|
|||
|
if (FALSE == bIgnoreAuditPolicy) {
|
|||
|
//
|
|||
|
// At the time of process creation, this routine should only proceed when Object Access or
|
|||
|
// Detailed Tracking auditing is enabled. In all other cases, the process name is acquired
|
|||
|
// when it is requested.
|
|||
|
//
|
|||
|
|
|||
|
if (FALSE == SepAdtAuditingEnabled) {
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
if ((FALSE == (SeAuditingState[AuditCategoryObjectAccess].AuditOnSuccess | SeAuditingState[AuditCategoryObjectAccess].AuditOnFailure)) &&
|
|||
|
(FALSE == (SeAuditingState[AuditCategoryDetailedTracking].AuditOnSuccess | SeAuditingState[AuditCategoryDetailedTracking].AuditOnFailure))) {
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
FilePointer = (PFILE_OBJECT) FileObject;
|
|||
|
|
|||
|
//
|
|||
|
// Compute full path for imagefile.
|
|||
|
// This first call to ObQueryNameString is guaranteed to fail.
|
|||
|
// The ObjectNameInformationLength contains only a
|
|||
|
// UNICODE_STRING, so if this call succeeded it would indicate
|
|||
|
// an imagefile name of length 0. That is bad, so all return
|
|||
|
// values except STATUS_BUFFER_OVERFLOW (from NTFS) and
|
|||
|
// STATUS_BUFFER_TOO_SMALL (from DFS). This call gives
|
|||
|
// me the buffer size that I need to store the image name.
|
|||
|
//
|
|||
|
|
|||
|
pInternalAuditName = &TempNameInfo;
|
|||
|
ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
|
|||
|
|
|||
|
Status = ObQueryNameString (FilePointer,
|
|||
|
pInternalAuditName,
|
|||
|
ObjectNameInformationLength,
|
|||
|
&ObjectNameInformationLength);
|
|||
|
|
|||
|
if ((Status == STATUS_BUFFER_OVERFLOW) ||
|
|||
|
(Status == STATUS_BUFFER_TOO_SMALL)) {
|
|||
|
|
|||
|
//
|
|||
|
// Sanity check ObQueryNameString. Different filesystems
|
|||
|
// may be buggy, so make sure that the return length makes
|
|||
|
// sense (that it has room for a non-NULL Buffer in the
|
|||
|
// UNICODE_STRING).
|
|||
|
//
|
|||
|
|
|||
|
if (ObjectNameInformationLength > sizeof(OBJECT_NAME_INFORMATION)) {
|
|||
|
pInternalAuditName = ExAllocatePoolWithTag (NonPagedPool,
|
|||
|
ObjectNameInformationLength,
|
|||
|
'aPeS');
|
|||
|
|
|||
|
if (pInternalAuditName != NULL) {
|
|||
|
Status = ObQueryNameString (FilePointer,
|
|||
|
pInternalAuditName,
|
|||
|
ObjectNameInformationLength,
|
|||
|
&ObjectNameInformationLength);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
#if DBG
|
|||
|
DbgPrint("\n** ObqueryNameString is busted for a filesystem you are using.\n");
|
|||
|
#endif //DBG
|
|||
|
|
|||
|
//
|
|||
|
// If the second call to ObQueryNameString did not succeed, then
|
|||
|
// something is very wrong. Set the image name to NULL string.
|
|||
|
//
|
|||
|
// Free the memory that the first call to ObQueryNameString requested,
|
|||
|
// and allocate enough space to store an empty UNICODE_STRING.
|
|||
|
//
|
|||
|
|
|||
|
ExFreePool (pInternalAuditName);
|
|||
|
ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
|
|||
|
pInternalAuditName = ExAllocatePoolWithTag (NonPagedPool,
|
|||
|
ObjectNameInformationLength,
|
|||
|
'aPeS');
|
|||
|
|
|||
|
if (pInternalAuditName != NULL) {
|
|||
|
RtlZeroMemory(pInternalAuditName, ObjectNameInformationLength);
|
|||
|
|
|||
|
//
|
|||
|
// Status = STATUS_SUCCESS to allow the process creation to continue.
|
|||
|
//
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
} else {
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
}
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// If this happens, then ObQueryNameString is broken for the FS on which
|
|||
|
// it was called.
|
|||
|
//
|
|||
|
|
|||
|
#if DBG
|
|||
|
DbgPrint("\n\n\n** ObqueryNameString is busted for a filesystem you are using.\n");
|
|||
|
DbgPrint("** Please mail jhamblin about this!!\n\n\n");
|
|||
|
#endif //DBG
|
|||
|
ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
|
|||
|
pInternalAuditName = ExAllocatePoolWithTag (NonPagedPool,
|
|||
|
ObjectNameInformationLength,
|
|||
|
'aPeS');
|
|||
|
|
|||
|
if (pInternalAuditName != NULL) {
|
|||
|
RtlZeroMemory(pInternalAuditName, ObjectNameInformationLength);
|
|||
|
|
|||
|
//
|
|||
|
// Status = STATUS_SUCCESS to allow the process creation to continue.
|
|||
|
//
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
} else {
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// If ObQueryNameString returns some other error code, we cannot
|
|||
|
// be certain of which action to take, or whether it has properly
|
|||
|
// set the ReturnLength. For example, ObQueryNameString has slightly
|
|||
|
// different semantics under DFS than NTFS. Additionally, 3rd
|
|||
|
// party file systems may also behave unpredictably. For these reasons,
|
|||
|
// in the case of an unexpected error code from ObQueryNameString
|
|||
|
// we set AuditName to zero length unicode string and allow process
|
|||
|
// creation to continue.
|
|||
|
//
|
|||
|
|
|||
|
#if DBG
|
|||
|
DbgPrint("\n\n\n** ObqueryNameString is busted for a filesystem you are using.\n");
|
|||
|
DbgPrint("** Please mail jhamblin about this!!\n\n\n");
|
|||
|
#endif //DBG
|
|||
|
ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
|
|||
|
pInternalAuditName = ExAllocatePoolWithTag(NonPagedPool, ObjectNameInformationLength, 'aPeS');
|
|||
|
|
|||
|
if (pInternalAuditName != NULL) {
|
|||
|
RtlZeroMemory(pInternalAuditName, ObjectNameInformationLength);
|
|||
|
|
|||
|
//
|
|||
|
// Status = STATUS_SUCCESS to allow the process creation to continue.
|
|||
|
//
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
} else {
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
*pAuditName = pInternalAuditName;
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SeLocateProcessImageName(
|
|||
|
IN PEPROCESS Process,
|
|||
|
OUT PUNICODE_STRING *pImageFileName
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description
|
|||
|
|
|||
|
This routine returns the ImageFileName information from the process, if available. This is a "lazy evaluation" wrapper
|
|||
|
around SeInitializeProcessAuditName. If the image file name information has already been computed, then this call simply
|
|||
|
allocates and returns a UNICODE_STRING with this information. Otherwise, the function determines the name, stores the name in the
|
|||
|
EPROCESS structure, and then allocates and returns a UNICODE_STRING. Caller must free the memory returned in pImageFileName.
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
Process - process for which to acquire the name
|
|||
|
|
|||
|
pImageFileName - output parameter to return name to caller
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
NTSTATUS.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
PVOID FilePointer = NULL;
|
|||
|
PVOID PreviousValue = NULL;
|
|||
|
POBJECT_NAME_INFORMATION pProcessImageName = NULL;
|
|||
|
PUNICODE_STRING pTempUS = NULL;
|
|||
|
ULONG NameLength = 0;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
*pImageFileName = NULL;
|
|||
|
|
|||
|
if (NULL == Process->SeAuditProcessCreationInfo.ImageFileName) {
|
|||
|
|
|||
|
//
|
|||
|
// The name has not been predetermined. We must determine the process name. First, reference the
|
|||
|
// PFILE_OBJECT and lookup the name. Then again check the process image name pointer against NULL.
|
|||
|
// Finally, set the name.
|
|||
|
//
|
|||
|
|
|||
|
Status = PsReferenceProcessFilePointer( Process, &FilePointer );
|
|||
|
|
|||
|
if (NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
//
|
|||
|
// Get the process name information.
|
|||
|
//
|
|||
|
|
|||
|
Status = SeInitializeProcessAuditName(
|
|||
|
FilePointer,
|
|||
|
TRUE, // skip audit policy
|
|||
|
&pProcessImageName // to be allocated in nonpaged pool
|
|||
|
);
|
|||
|
|
|||
|
if (NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
//
|
|||
|
// Only use the pProcessImageName if the field in the process is currently NULL.
|
|||
|
//
|
|||
|
|
|||
|
PreviousValue = InterlockedCompareExchangePointer(
|
|||
|
(PVOID *) &Process->SeAuditProcessCreationInfo.ImageFileName,
|
|||
|
(PVOID) pProcessImageName,
|
|||
|
(PVOID) NULL
|
|||
|
);
|
|||
|
|
|||
|
if (NULL != PreviousValue) {
|
|||
|
ExFreePool(pProcessImageName); // free what we caused to be allocated.
|
|||
|
}
|
|||
|
}
|
|||
|
ObDereferenceObject( FilePointer );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
//
|
|||
|
// Allocate space for a buffer to contain the name for returning to the caller.
|
|||
|
//
|
|||
|
|
|||
|
NameLength = sizeof(UNICODE_STRING) + Process->SeAuditProcessCreationInfo.ImageFileName->Name.MaximumLength;
|
|||
|
pTempUS = ExAllocatePoolWithTag( NonPagedPool, NameLength, 'aPeS' );
|
|||
|
|
|||
|
if (NULL != pTempUS) {
|
|||
|
|
|||
|
RtlCopyMemory(
|
|||
|
pTempUS,
|
|||
|
&Process->SeAuditProcessCreationInfo.ImageFileName->Name,
|
|||
|
NameLength
|
|||
|
);
|
|||
|
|
|||
|
pTempUS->Buffer = (PWSTR)(((PUCHAR) pTempUS) + sizeof(UNICODE_STRING));
|
|||
|
*pImageFileName = pTempUS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SepAuditAssignPrimaryToken(
|
|||
|
IN PEPROCESS Process,
|
|||
|
IN PACCESS_TOKEN AccessToken
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine generates an assign primary token audit. It is up to the caller
|
|||
|
to determine if this routine should be called or not.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Process - process which gets the new token
|
|||
|
|
|||
|
AccessToken - new primary token for the process
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|||
|
NTSTATUS Status;
|
|||
|
PSID UserSid;
|
|||
|
PTOKEN Token;
|
|||
|
HANDLE ProcessId;
|
|||
|
|
|||
|
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
|
|||
|
PTOKEN CurrentToken;
|
|||
|
PEPROCESS CurrentProcess;
|
|||
|
HANDLE CurrentProcessId;
|
|||
|
PUNICODE_STRING CurrentImageFileName;
|
|||
|
PUNICODE_STRING ImageFileName;
|
|||
|
UNICODE_STRING NullString = {0};
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
RtlZeroMemory (
|
|||
|
(PVOID) &AuditParameters,
|
|||
|
sizeof( AuditParameters )
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Get information about the current process, that is, the process
|
|||
|
// that is assigning a new primary token.
|
|||
|
//
|
|||
|
|
|||
|
CurrentProcess = PsGetCurrentProcess();
|
|||
|
CurrentProcessId = PsProcessAuditId( CurrentProcess );
|
|||
|
SeCaptureSubjectContext( &SubjectSecurityContext );
|
|||
|
CurrentToken = EffectiveToken( &SubjectSecurityContext );
|
|||
|
UserSid = SepTokenUserSid( CurrentToken );
|
|||
|
Status = SeLocateProcessImageName( CurrentProcess, &CurrentImageFileName );
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
CurrentImageFileName = &NullString;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Retrieve information about the process receiving the new token.
|
|||
|
//
|
|||
|
|
|||
|
Token = (PTOKEN) AccessToken;
|
|||
|
ProcessId = PsProcessAuditId( Process );
|
|||
|
|
|||
|
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
|||
|
|
|||
|
if ( !NT_SUCCESS(Status) ) {
|
|||
|
ImageFileName = &NullString;
|
|||
|
}
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_ASSIGN_TOKEN;
|
|||
|
AuditParameters.ParameterCount = 0;
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Information regarding the assigning process
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, CurrentProcessId );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, CurrentImageFileName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, SepTokenAuthenticationId( CurrentToken ) );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
//
|
|||
|
// Information about the process receiving the new primary token.
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, SepTokenAuthenticationId( Token ) );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
|
|||
|
if ( ImageFileName != &NullString ) {
|
|||
|
ExFreePool( ImageFileName );
|
|||
|
}
|
|||
|
|
|||
|
if ( CurrentImageFileName != &NullString ) {
|
|||
|
ExFreePool( CurrentImageFileName );
|
|||
|
}
|
|||
|
|
|||
|
SeReleaseSubjectContext( &SubjectSecurityContext );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
SeAuditLPCInvalidUse(
|
|||
|
IN PUNICODE_STRING LpcCallName,
|
|||
|
IN PUNICODE_STRING LpcServerPort
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Audits the invalid use of an LPC port.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LpcCallName - type of call: impersonation or reply
|
|||
|
|
|||
|
LpcServerPort - name of port
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LUID UserAuthenticationId;
|
|||
|
PSID UserSid;
|
|||
|
LUID ThreadAuthenticationId;
|
|||
|
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|||
|
PEPROCESS Process;
|
|||
|
HANDLE ProcessID;
|
|||
|
PUNICODE_STRING ImageFileName;
|
|||
|
UNICODE_STRING NullString = {0};
|
|||
|
NTSTATUS Status;
|
|||
|
BOOLEAN AccessGranted = TRUE;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
|
|||
|
if ( SepAdtAuditThisEvent( AuditCategorySystem, &AccessGranted )) {
|
|||
|
|
|||
|
RtlZeroMemory (
|
|||
|
(PVOID) &AuditParameters,
|
|||
|
sizeof( AuditParameters )
|
|||
|
);
|
|||
|
|
|||
|
Process = PsGetCurrentProcess();
|
|||
|
ProcessID = PsProcessAuditId( Process );
|
|||
|
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
|||
|
|
|||
|
if ( !NT_SUCCESS(Status) ) {
|
|||
|
ImageFileName = &NullString;
|
|||
|
}
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_SYSTEM;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_LPC_INVALID_USE;
|
|||
|
AuditParameters.ParameterCount = 0;
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|||
|
|
|||
|
SeCaptureSubjectContext( &SubjectSecurityContext );
|
|||
|
|
|||
|
UserSid = SepTokenUserSid( SubjectSecurityContext.PrimaryToken );
|
|||
|
UserAuthenticationId = SepTokenAuthenticationId( SubjectSecurityContext.PrimaryToken );
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the AuditParameters structure.
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessID );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, UserAuthenticationId );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
if ( SubjectSecurityContext.ClientToken ) {
|
|||
|
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, SepTokenAuthenticationId( SubjectSecurityContext.ClientToken ));
|
|||
|
} else {
|
|||
|
|
|||
|
SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, LpcCallName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, LpcServerPort );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
|
|||
|
SeReleaseSubjectContext( &SubjectSecurityContext );
|
|||
|
|
|||
|
if ( ImageFileName != &NullString ) {
|
|||
|
ExFreePool( ImageFileName );
|
|||
|
}
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SeAuditSystemTimeChange(
|
|||
|
IN LARGE_INTEGER OldTime,
|
|||
|
IN LARGE_INTEGER NewTime
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Audits the modification of system time.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
OldTime - Time before modification.
|
|||
|
NewTime - Time after modification.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|||
|
PSID UserSid;
|
|||
|
LUID LogonId;
|
|||
|
HANDLE ProcessId;
|
|||
|
PEPROCESS Process;
|
|||
|
PUNICODE_STRING ImageFileName;
|
|||
|
UNICODE_STRING NullString = {0};
|
|||
|
NTSTATUS Status;
|
|||
|
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Make sure that we care to audit system events.
|
|||
|
//
|
|||
|
|
|||
|
if ((SepAdtAuditingEnabled) && (SeAuditingState[AuditCategorySystem].AuditOnSuccess)) {
|
|||
|
|
|||
|
SeCaptureSubjectContext( &SubjectSecurityContext );
|
|||
|
|
|||
|
UserSid = SepTokenUserSid( SubjectSecurityContext.PrimaryToken );
|
|||
|
LogonId = SepTokenAuthenticationId( SubjectSecurityContext.PrimaryToken );
|
|||
|
|
|||
|
Process = PsGetCurrentProcess();
|
|||
|
|
|||
|
RtlZeroMemory (
|
|||
|
(PVOID) &AuditParameters,
|
|||
|
sizeof( AuditParameters )
|
|||
|
);
|
|||
|
|
|||
|
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
|||
|
|
|||
|
if ( !NT_SUCCESS(Status) ) {
|
|||
|
ImageFileName = &NullString;
|
|||
|
}
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_SYSTEM;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_SYSTEM_TIME_CHANGE;
|
|||
|
AuditParameters.ParameterCount = 0;
|
|||
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
ProcessId = PsProcessAuditId( Process );
|
|||
|
|
|||
|
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, LogonId );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
if ( SubjectSecurityContext.ClientToken ) {
|
|||
|
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, SepTokenAuthenticationId( SubjectSecurityContext.ClientToken ));
|
|||
|
} else {
|
|||
|
|
|||
|
SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
|
|||
|
}
|
|||
|
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
SepSetParmTypeTime( AuditParameters, AuditParameters.ParameterCount, OldTime );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeTime( AuditParameters, AuditParameters.ParameterCount, NewTime );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
|
|||
|
SeReleaseSubjectContext( &SubjectSecurityContext );
|
|||
|
|
|||
|
if ( ImageFileName != &NullString ) {
|
|||
|
ExFreePool( ImageFileName );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SeAuditHardLinkCreation(
|
|||
|
IN PUNICODE_STRING FileName,
|
|||
|
IN PUNICODE_STRING LinkName,
|
|||
|
IN BOOLEAN bSuccess
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Audits the attempted creation of a hard link.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileName - Name of the original file.
|
|||
|
|
|||
|
LinkName - The name of the hard link.
|
|||
|
|
|||
|
bSuccess - Boolean indicating if the hard link creation attempt was successful or not.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LUID UserAuthenticationId;
|
|||
|
PSID UserSid;
|
|||
|
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
|
|||
|
SE_ADT_PARAMETER_ARRAY AuditParameters = { 0 };
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
ASSERT( SeAdtParmTypeNone == 0 );
|
|||
|
|
|||
|
AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS;
|
|||
|
AuditParameters.AuditId = SE_AUDITID_HARDLINK_CREATION;
|
|||
|
AuditParameters.ParameterCount = 0;
|
|||
|
AuditParameters.Type = bSuccess ? EVENTLOG_AUDIT_SUCCESS : EVENTLOG_AUDIT_FAILURE;
|
|||
|
|
|||
|
//
|
|||
|
// Use the effective token.
|
|||
|
//
|
|||
|
|
|||
|
SeCaptureSubjectContext( &SubjectSecurityContext );
|
|||
|
UserSid = SepTokenUserSid( EffectiveToken( &SubjectSecurityContext ));
|
|||
|
UserAuthenticationId = SepTokenAuthenticationId( EffectiveToken( &SubjectSecurityContext ));
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the AuditParameters structure.
|
|||
|
//
|
|||
|
|
|||
|
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, UserAuthenticationId );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, FileName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, LinkName );
|
|||
|
AuditParameters.ParameterCount++;
|
|||
|
|
|||
|
SepAdtLogAuditRecord( &AuditParameters );
|
|||
|
|
|||
|
SeReleaseSubjectContext( &SubjectSecurityContext );
|
|||
|
|
|||
|
return;
|
|||
|
}
|