📄 minispy.c
字号:
if ((InputBuffer != NULL) &&
(InputBufferSize >= (FIELD_OFFSET(COMMAND_MESSAGE,Command) +
sizeof(MINISPY_COMMAND)))) {
try {
//
// Probe and capture input message: the message is raw user mode
// buffer, so need to protect with exception handler
//
command = ((PCOMMAND_MESSAGE) InputBuffer)->Command;
} except( EXCEPTION_EXECUTE_HANDLER ) {
return GetExceptionCode();
}
switch (command) {
case GetMiniSpyLog:
//
// Return as many log records as can fit into the OutputBuffer
//
if ((OutputBuffer == NULL) || (OutputBufferSize == 0)) {
status = STATUS_INVALID_PARAMETER;
break;
}
//
// We want to validate that the given buffer is POINTER
// aligned. But if this is a 64bit system and we want to
// support 32bit applications we need to be careful with how
// we do the check. Note that the way SpyGetLog is written
// it actually does not care about alignment but we are
// demonstrating how to do this type of check.
//
#if defined(_WIN64)
if (IoIs32bitProcess( NULL )) {
//
// Validate alignment for the 32bit process on a 64bit
// system
//
if (!IS_ALIGNED(OutputBuffer,sizeof(ULONG))) {
status = STATUS_DATATYPE_MISALIGNMENT;
break;
}
} else {
#endif
if (!IS_ALIGNED(OutputBuffer,sizeof(PVOID))) {
status = STATUS_DATATYPE_MISALIGNMENT;
break;
}
#if defined(_WIN64)
}
#endif
//
// Get the log record.
//
status = SpyGetLog( OutputBuffer,
OutputBufferSize,
ReturnOutputBufferLength );
break;
case GetMiniSpyVersion:
//
// Return version of the MiniSpy filter driver. Verify
// we have a valid user buffer including valid
// alignment
//
if ((OutputBufferSize < sizeof( MINISPYVER )) ||
(OutputBuffer == NULL)) {
status = STATUS_INVALID_PARAMETER;
break;
}
//
// Validate Buffer alignment. If a minifilter cares about
// the alignment value of the buffer pointer they must do
// this check themselves. Note that a try/except will not
// capture alignment faults.
//
if (!IS_ALIGNED(OutputBuffer,sizeof(ULONG))) {
status = STATUS_DATATYPE_MISALIGNMENT;
break;
}
//
// Protect access to raw user-mode output buffer with an
// exception handler
//
try {
((PMINISPYVER)OutputBuffer)->Major = MINISPY_MAJ_VERSION;
((PMINISPYVER)OutputBuffer)->Minor = MINISPY_MIN_VERSION;
} except( EXCEPTION_EXECUTE_HANDLER ) {
return GetExceptionCode();
}
*ReturnOutputBufferLength = sizeof( MINISPYVER );
status = STATUS_SUCCESS;
break;
default:
status = STATUS_INVALID_PARAMETER;
break;
}
} else {
status = STATUS_INVALID_PARAMETER;
}
return status;
}
//---------------------------------------------------------------------------
// Operation filtering routines
//---------------------------------------------------------------------------
FLT_PREOP_CALLBACK_STATUS
SpyPreOperationCallback (
IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
OUT PVOID *CompletionContext
)
/*++
Routine Description:
This routine receives ALL pre-operation callbacks for this filter. It then
tries to log information about the given operation. If we are able
to log information then we will call our post-operation callback routine.
NOTE: This routine must be NON-PAGED because it can be called on the
paging path.
Arguments:
Data - Contains information about the given operation.
FltObjects - Contains pointers to the various objects that are pertinent
to this operation.
CompletionContext - This receives the address of our log buffer for this
operation. Our completion routine then receives this buffer address.
Return Value:
Identifies how processing should continue for this operation
--*/
{
FLT_PREOP_CALLBACK_STATUS returnStatus = FLT_PREOP_SUCCESS_NO_CALLBACK; //assume we are NOT going to call our completion routine
PRECORD_LIST recordList;
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
UNICODE_STRING defaultName;
PUNICODE_STRING nameToUse;
NTSTATUS status;
//
// Try and get a log record
//
recordList = SpyNewRecord();
if (recordList) {
//
// We got a log record, if there is a file object, get its name.
//
// NOTE: By default, we use the query method
// FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP
// because MiniSpy would like to get the name as much as possible, but
// can cope if we can't retrieve a name. For a debugging type filter,
// like Minispy, this is reasonable, but for most production filters
// who need names reliably, they should query the name at times when it
// is known to be safe and use the query method
// FLT_FILE_NAME_QUERY_DEFAULT.
//
if (FltObjects->FileObject != NULL) {
status = FltGetFileNameInformation( Data,
FLT_FILE_NAME_NORMALIZED |
MiniSpyData.NameQueryMethod,
&nameInfo );
} else {
//
// Can't get a name when there's no file object
//
status = STATUS_UNSUCCESSFUL;
}
//
// Use the name if we got it else use a default name
//
if (NT_SUCCESS( status )) {
nameToUse = &nameInfo->Name;
//
// Parse the name if requested
//
if (FlagOn( MiniSpyData.DebugFlags, SPY_DEBUG_PARSE_NAMES )) {
status = FltParseFileNameInformation( nameInfo );
ASSERT(NT_SUCCESS(status));
}
} else {
RtlInitUnicodeString( &defaultName, L"<NO NAME>" );
nameToUse = &defaultName;
}
//
// Store the name
//
SpySetRecordName( &(recordList->LogRecord), nameToUse );
//
// Release the name information structure (if defined)
//
if (NULL != nameInfo) {
FltReleaseFileNameInformation( nameInfo );
}
//
// Set all of the operation information into the record
//
SpyLogPreOperationData( Data, FltObjects, recordList );
//
// Pass the record to our completions routine and return that
// we want our completion routine called.
//
if (Data->Iopb->MajorFunction == IRP_MJ_SHUTDOWN) {
//
// Since completion callbacks are not supported for
// this operation, do the completion processing now
//
SpyPostOperationCallback( Data,
FltObjects,
recordList,
0 );
returnStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
} else {
*CompletionContext = recordList;
returnStatus = FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
}
return returnStatus;
}
FLT_POSTOP_CALLBACK_STATUS
SpyPostOperationCallback (
IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
IN PVOID CompletionContext,
IN FLT_POST_OPERATION_FLAGS Flags
)
/*++
Routine Description:
This routine receives ALL post-operation callbacks. This will take
the log record passed in the context parameter and update it with
the completion information. It will then insert it on a list to be
sent to the usermode component.
NOTE: This routine must be NON-PAGED because it can be called at DPC level
Arguments:
Data - Contains information about the given operation.
FltObjects - Contains pointers to the various objects that are pertinent
to this operation.
CompletionContext - Pointer to the RECORD_LIST structure in which we
store the information we are logging. This was passed from the
pre-operation callback
Flags - Contains information as to why this routine was called.
Return Value:
Identifies how processing should continue for this operation
--*/
{
PRECORD_LIST recordList;
PRECORD_LIST reparseRecordList = NULL;
PLOG_RECORD reparseLogRecord;
PFLT_TAG_DATA_BUFFER tagData;
ULONG copyLength;
UNREFERENCED_PARAMETER( FltObjects );
recordList = (PRECORD_LIST)CompletionContext;
//
// If our instance is in the process of being torn down don't bother to
// log this record, free it now.
//
if (FlagOn(Flags,FLTFL_POST_OPERATION_DRAINING)) {
SpyFreeRecord( recordList );
return FLT_POSTOP_FINISHED_PROCESSING;
}
//
// Set completion information into the record
//
SpyLogPostOperationData( Data, recordList );
//
// Log reparse tag information if specified.
//
if (tagData = Data->TagData) {
reparseRecordList = SpyNewRecord();
if (reparseRecordList) {
//
// only copy the DATA portion of the information
//
RtlCopyMemory( &reparseRecordList->LogRecord.Data,
&recordList->LogRecord.Data,
sizeof(RECORD_DATA) );
reparseLogRecord = &reparseRecordList->LogRecord;
copyLength = FLT_TAG_DATA_BUFFER_HEADER_SIZE + tagData->TagDataLength;
if(copyLength > MAX_NAME_SPACE) {
copyLength = MAX_NAME_SPACE;
}
//
// Copy reparse data
//
RtlCopyMemory(
&reparseRecordList->LogRecord.Name[0],
tagData,
copyLength
);
reparseLogRecord->RecordType |= RECORD_TYPE_FILETAG;
reparseLogRecord->Length += (ULONG) ROUND_TO_SIZE( copyLength, sizeof( PVOID ) );
}
}
//
// Send the logged information to the user service.
//
SpyLog( recordList );
if (reparseRecordList) {
SpyLog( reparseRecordList );
}
return FLT_POSTOP_FINISHED_PROCESSING;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -