📄 scanner.c
字号:
__in DEVICE_TYPE VolumeDeviceType,
__in FLT_FILESYSTEM_TYPE VolumeFilesystemType
)
/*++
Routine Description:
This routine is called by the filter manager when a new instance is created.
We specified in the registry that we only want for manual attachments,
so that is all we should receive here.
Arguments:
FltObjects - Describes the instance and volume which we are being asked to
setup.
Flags - Flags describing the type of attachment this is.
VolumeDeviceType - The DEVICE_TYPE for the volume to which this instance
will attach.
VolumeFileSystemType - The file system formatted on this volume.
Return Value:
FLT_NOTIFY_STATUS_ATTACH - we wish to attach to the volume
FLT_NOTIFY_STATUS_DO_NOT_ATTACH - no, thank you
--*/
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
UNREFERENCED_PARAMETER( VolumeFilesystemType );
PAGED_CODE();
ASSERT( FltObjects->Filter == ScannerData.Filter );
//
// Don't attach to network volumes.
//
if (VolumeDeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) {
return STATUS_FLT_DO_NOT_ATTACH;
}
return STATUS_SUCCESS;
}
NTSTATUS
ScannerQueryTeardown (
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
)
/*++
Routine Description:
This is the instance detach routine for the filter. This
routine is called by filter manager when a user initiates a manual instance
detach. This is a 'query' routine: if the filter does not want to support
manual detach, it can return a failure status
Arguments:
FltObjects - Describes the instance and volume for which we are receiving
this query teardown request.
Flags - Unused
Return Value:
STATUS_SUCCESS - we allow instance detach to happen
--*/
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
return STATUS_SUCCESS;
}
FLT_PREOP_CALLBACK_STATUS
ScannerPreCreate (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID *CompletionContext
)
/*++
Routine Description:
Pre create callback. We need to remember whether this file has been
opened for write access. If it has, we'll want to rescan it in cleanup.
This scheme results in extra scans in at least two cases:
-- if the create fails (perhaps for access denied)
-- the file is opened for write access but never actually written to
The assumption is that writes are more common than creates, and checking
or setting the context in the write path would be less efficient than
taking a good guess before the create.
Arguments:
Data - The structure which describes the operation parameters.
FltObject - The structure which describes the objects affected by this
operation.
CompletionContext - Output parameter which can be used to pass a context
from this pre-create callback to the post-create callback.
Return Value:
FLT_PREOP_SUCCESS_WITH_CALLBACK - If this is not our user-mode process.
FLT_PREOP_SUCCESS_NO_CALLBACK - All other threads.
--*/
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( CompletionContext );
PAGED_CODE();
//
// See if this create is being done by our user process.
//
if (IoThreadToProcess( Data->Thread ) == ScannerData.UserProcess) {
DbgPrint( "!!! scanner.sys -- allowing create for trusted process \n" );
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
BOOLEAN
ScannerpCheckExtension (
__in PUNICODE_STRING Extension
)
/*++
Routine Description:
Checks if this file name extension is something we are interested in
Arguments
Extension - Pointer to the file name extension
Return Value
TRUE - Yes we are interested
FALSE - No
--*/
{
const UNICODE_STRING *ext;
if (Extension->Length == 0) {
return FALSE;
}
//
// Check if it matches any one of our static extension list
//
ext = ScannerExtensionsToScan;
while (ext->Buffer != NULL) {
if (RtlCompareUnicodeString( Extension, ext, TRUE ) == 0) {
//
// A match. We are interested in this file
//
return TRUE;
}
ext++;
}
return FALSE;
}
FLT_POSTOP_CALLBACK_STATUS
ScannerPostCreate (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__in_opt PVOID CompletionContext,
__in FLT_POST_OPERATION_FLAGS Flags
)
/*++
Routine Description:
Post create callback. We can't scan the file until after the create has
gone to the filesystem, since otherwise the filesystem wouldn't be ready
to read the file for us.
Arguments:
Data - The structure which describes the operation parameters.
FltObject - The structure which describes the objects affected by this
operation.
CompletionContext - The operation context passed fron the pre-create
callback.
Flags - Flags to say why we are getting this post-operation callback.
Return Value:
FLT_POSTOP_FINISHED_PROCESSING - ok to open the file or we wish to deny
access to this file, hence undo the open
--*/
{
PSCANNER_STREAM_HANDLE_CONTEXT scannerContext;
FLT_POSTOP_CALLBACK_STATUS returnStatus = FLT_POSTOP_FINISHED_PROCESSING;
PFLT_FILE_NAME_INFORMATION nameInfo;
NTSTATUS status;
BOOLEAN safeToOpen, scanFile;
UNREFERENCED_PARAMETER( CompletionContext );
UNREFERENCED_PARAMETER( Flags );
//
// If this create was failing anyway, don't bother scanning now.
//
if (!NT_SUCCESS( Data->IoStatus.Status ) ||
(STATUS_REPARSE == Data->IoStatus.Status)) {
return FLT_POSTOP_FINISHED_PROCESSING;
}
//
// Check if we are interested in this file.
//
status = FltGetFileNameInformation( Data,
FLT_FILE_NAME_NORMALIZED |
FLT_FILE_NAME_QUERY_DEFAULT,
&nameInfo );
if (!NT_SUCCESS( status )) {
return FLT_POSTOP_FINISHED_PROCESSING;
}
FltParseFileNameInformation( nameInfo );
//
// Check if the extension matches the list of extensions we are interested in
//
scanFile = ScannerpCheckExtension( &nameInfo->Extension );
//
// Release file name info, we're done with it
//
FltReleaseFileNameInformation( nameInfo );
if (!scanFile) {
//
// Not an extension we are interested in
//
return FLT_POSTOP_FINISHED_PROCESSING;
}
status = ScannerpScanFileInUserMode( FltObjects->Instance,
FltObjects->FileObject,
&safeToOpen );
if (!safeToOpen) {
//
// Ask the filter manager to undo the create.
//
DbgPrint( "!!! scanner.sys -- foul language detected in postcreate !!!\n" );
DbgPrint( "!!! scanner.sys -- undoing create \n" );
FltCancelFileOpen( FltObjects->Instance, FltObjects->FileObject );
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
Data->IoStatus.Information = 0;
returnStatus = FLT_POSTOP_FINISHED_PROCESSING;
} else if (FltObjects->FileObject->WriteAccess) {
//
//
// The create has requested write access, mark to rescan the file.
// Allocate the context.
//
status = FltAllocateContext( ScannerData.Filter,
FLT_STREAMHANDLE_CONTEXT,
sizeof(SCANNER_STREAM_HANDLE_CONTEXT),
PagedPool,
&scannerContext );
if (NT_SUCCESS(status)) {
//
// Set the handle context.
//
scannerContext->RescanRequired = TRUE;
status = FltSetStreamHandleContext( FltObjects->Instance,
FltObjects->FileObject,
FLT_SET_CONTEXT_REPLACE_IF_EXISTS,
scannerContext,
NULL );
//
// The only error status that could be returned would tell us that
// contexts are not supported. Even if we got this error,
// we just want to release the context now and that will free
// this memory if it was not successfully set.
//
//
// Release our reference on the context (the set adds a reference)
//
FltReleaseContext( scannerContext );
}
}
return returnStatus;
}
FLT_PREOP_CALLBACK_STATUS
ScannerPreCleanup (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID *CompletionContext
)
/*++
Routine Description:
Pre cleanup callback. If this file was opened for write access, we want
to rescan it now.
Arguments:
Data - The structure which describes the operation parameters.
FltObject - The structure which describes the objects affected by this
operation.
CompletionContext - Output parameter which can be used to pass a context
from this pre-cleanup callback to the post-cleanup callback.
Return Value:
Always FLT_PREOP_SUCCESS_NO_CALLBACK.
--*/
{
NTSTATUS status;
PSCANNER_STREAM_HANDLE_CONTEXT context;
BOOLEAN safe;
UNREFERENCED_PARAMETER( Data );
UNREFERENCED_PARAMETER( CompletionContext );
status = FltGetStreamHandleContext( FltObjects->Instance,
FltObjects->FileObject,
&context );
if (NT_SUCCESS( status )) {
if (context->RescanRequired) {
ScannerpScanFileInUserMode( FltObjects->Instance,
FltObjects->FileObject,
&safe );
if (!safe) {
DbgPrint( "!!! scanner.sys -- foul language detected in precleanup !!!\n" );
}
}
FltReleaseContext( context );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -