The new bits of the WDK have been released, and it seems that finally, we are starting to see a glimpse of some of the new filtering technologies that were promised in Vista SP1 to help with incompatibilities due to PatchGuard. Although Vista added powerful Registry filtering support on top of the existing File filtering architecture, hooking some native calls would still have been necessary in order to filter other kinds of system behaviour. The first which seems to have been addressed are handles, and Vista SP1 now supports Object Manager Filters.
Currently, only create and duplicate can be filtered, but the ability for both pre and post notifications exist. As with the new filter model, Object Manager Filters also support Altitudes, and are fully versionned. Unfortunately, this new set of APIs seems rather disappointing to me. For starters, this functionality was already available, even behind Patchguard’s back, through native Object Manager callbacks present in the OBJECT_TYPE’s ObjectTypeInitializer structure which contains all the callbacks for the object type. This interface seems to do nothing more but expose in a more public and accessible way the same ObCreateMethod interface that has existed since NT4, except that it only works for create and duplicate (while the internal interface allows for open and inherit as well).
Nevertheless, this new filtering mechanism is clearly written to be extensible for other Object Manager actions, so hopefully we’ll see some new improvements before SP1 actually ships. For the curious, here are some of the new toys to play with:
//
// Registration version for Vista SP1 and Windows Server 2007
//
#define OB_FLT_REGISTRATION_VERSION_0100Â 0x0100
//
// This value should be used by filters for registration
//
#define OB_FLT_REGISTRATION_VERSION OB_FLT_REGISTRATION_VERSION_0100
typedef ULONG OB_OPERATION;
#define OB_OPERATION_HANDLE_CREATEÂ Â Â Â Â Â Â Â Â Â Â Â Â 0x00000001
#define OB_OPERATION_HANDLE_DUPLICATEÂ Â Â Â Â Â Â Â Â Â 0x00000002
typedef struct _OB_PRE_CREATE_HANDLE_INFORMATION {
   __inout ACCESS_MASK        DesiredAccess;
   __in ACCESS_MASK           OriginalDesiredAccess;
} OB_PRE_CREATE_HANDLE_INFORMATION, *POB_PRE_CREATE_HANDLE_INFORMATION;
typedef struct _OB_PRE_DUPLICATE_HANDLE_INFORMATION {
   __inout ACCESS_MASK        DesiredAccess;
   __in ACCESS_MASK           OriginalDesiredAccess;
   __in PVOID                 SourceProcess;
   __in PVOID                 TargetProcess;
} OB_PRE_DUPLICATE_HANDLE_INFORMATION, * POB_PRE_DUPLICATE_HANDLE_INFORMATION;
typedef union _OB_PRE_OPERATION_PARAMETERS {
   __inout OB_PRE_CREATE_HANDLE_INFORMATION       CreateHandleInformation;
   __inout OB_PRE_DUPLICATE_HANDLE_INFORMATION    DuplicateHandleInformation;
} OB_PRE_OPERATION_PARAMETERS, *POB_PRE_OPERATION_PARAMETERS;
typedef struct _OB_PRE_OPERATION_INFORMATION {
   __in OB_OPERATION          Operation;
   union {
       __in ULONG Flags;
       struct {
           __in ULONG KernelHandle:1;
           __in ULONG Reserved:31;
       };
   };
   __in PVOID                        Object;
   __in POBJECT_TYPE                 ObjectType;
   __out PVOID                       CallContext;
   __in POB_PRE_OPERATION_PARAMETERS Parameters;
} OB_PRE_OPERATION_INFORMATION, *POB_PRE_OPERATION_INFORMATION;
typedef struct _OB_POST_CREATE_HANDLE_INFORMATION {
   __in ACCESS_MASK           GrantedAccess;
} OB_POST_CREATE_HANDLE_INFORMATION, *POB_POST_CREATE_HANDLE_INFORMATION;
typedef struct _OB_POST_DUPLICATE_HANDLE_INFORMATION {
   __in ACCESS_MASK           GrantedAccess;
} OB_POST_DUPLICATE_HANDLE_INFORMATION, * POB_POST_DUPLICATE_HANDLE_INFORMATION;
typedef union _OB_POST_OPERATION_PARAMETERS {
   __in OB_POST_CREATE_HANDLE_INFORMATION      CreateHandleInformation;
   __in OB_POST_DUPLICATE_HANDLE_INFORMATION   DuplicateHandleInformation;
} OB_POST_OPERATION_PARAMETERS, *POB_POST_OPERATION_PARAMETERS;
typedef struct _OB_POST_OPERATION_INFORMATION {
   __in OB_OPERATION Operation;
   union {
       __in ULONG Flags;
       struct {
           __in ULONG KernelHandle:1;
           __in ULONG Reserved:31;
       };
   };
   __in PVOID                         Object;
   __in POBJECT_TYPE                  ObjectType;
   __in PVOID                         CallContext;
   __in NTSTATUS                      ReturnStatus;
   __in POB_POST_OPERATION_PARAMETERS Parameters;
} OB_POST_OPERATION_INFORMATION,*POB_POST_OPERATION_INFORMATION;
typedef enum _OB_PREOP_CALLBACK_STATUS {
   OB_PREOP_SUCCESS
} OB_PREOP_CALLBACK_STATUS, *POB_PREOP_CALLBACK_STATUS;
typedef OB_PREOP_CALLBACK_STATUS
(*POB_PRE_OPERATION_CALLBACK) (
   __in PVOID RegistrationContext,
   __inout POB_PRE_OPERATION_INFORMATION OperationInformation
   );
typedef VOID
(*POB_POST_OPERATION_CALLBACK) (
   __in PVOID RegistrationContext,
   __in POB_POST_OPERATION_INFORMATION OperationInformation
   );
typedef struct _OB_OPERATION_REGISTRATION {
   __in POBJECT_TYPE               *ObjectType;
   __in OB_OPERATION               Operations;
   __in POB_PRE_OPERATION_CALLBACK PreOperation;
   __in POB_POST_OPERATION_CALLBACK PostOperation;
} OB_OPERATION_REGISTRATION, *POB_OPERATION_REGISTRATION;
typedef struct _OB_CALLBACK_REGISTRATION {
   __in USHORT                    Version;
   __in USHORT                    OperationRegistrationCount;
   __in UNICODE_STRING            Altitude;
   __in PVOID                     RegistrationContext;
   __in OB_OPERATION_REGISTRATION *OperationRegistration;
} OB_CALLBACK_REGISTRATION, *POB_CALLBACK_REGISTRATION;
#if (NTDDI_VERSION >= NTDDI_VISTASP1)
NTKERNELAPI
NTSTATUS
ObRegisterCallbacks (
   __in POB_CALLBACK_REGISTRATION CallbackRegistration,
   __deref_out PVOID *RegistrationHandle
   );
NTKERNELAPI
VOID
ObUnRegisterCallbacks (
   __in PVOID RegistrationHandle
   );
NTKERNELAPI
USHORT
ObGetFilterVersion ();
#endif