📄 mspylib.c
字号:
RecordList - Where we want to save the data
Return Value:
None.
--*/
{
PRECORD_DATA recordData = &RecordList->LogRecord.Data;
recordData->Status = Data->IoStatus.Status;
recordData->Information = Data->IoStatus.Information;
KeQuerySystemTime( &recordData->CompletionTime );
}
VOID
SpyLogTransactionNofity (
__in PCFLT_RELATED_OBJECTS FltObjects,
__inout PRECORD_LIST RecordList,
__in ULONG TransactionNotification
)
/*++
Routine Description:
This routine logs the transaction notification.
Arguments:
FltObjects - Pointer to the io objects involved in this operation.
RecordList - Where we want to save the data
TransactionNotification - Notification for this transaction.
Return Value:
None.
--*/
{
PRECORD_DATA recordData = &RecordList->LogRecord.Data;
PDEVICE_OBJECT devObj;
NTSTATUS status;
status = FltGetDeviceObject(FltObjects->Volume,&devObj);
if (NT_SUCCESS(status)) {
ObDereferenceObject(devObj);
} else {
devObj = NULL;
}
recordData->CallbackMajorId = IRP_MJ_TRANSACTION_NOTIFY;
recordData->CallbackMinorId = (UCHAR)TransactionNotification;
recordData->DeviceObject = (FILE_ID)devObj;
recordData->FileObject = (FILE_ID)FltObjects->FileObject;
recordData->Transaction = (FILE_ID)FltObjects->Transaction;
recordData->ProcessId = (FILE_ID)PsGetCurrentProcessId();
recordData->ThreadId = (FILE_ID)PsGetCurrentThreadId();
KeQuerySystemTime( &recordData->OriginatingTime );
}
VOID
SpyLog (
__in PRECORD_LIST RecordList
)
/*++
Routine Description:
This routine inserts the given log record into the list to be sent
to the user mode application.
NOTE: This code must be NON-PAGED because it can be called on the
paging path or at DPC level and uses a spin-lock
Arguments:
RecordList - The record to append to the MiniSpyData.OutputBufferList
Return Value:
The function returns STATUS_SUCCESS.
--*/
{
KIRQL oldIrql;
KeAcquireSpinLock(&MiniSpyData.OutputBufferLock, &oldIrql);
InsertTailList(&MiniSpyData.OutputBufferList, &RecordList->List);
KeReleaseSpinLock(&MiniSpyData.OutputBufferLock, oldIrql);
}
NTSTATUS
SpyGetLog (
__out_bcount_part(OutputBufferLength,*ReturnOutputBufferLength) PUCHAR OutputBuffer,
__in ULONG OutputBufferLength,
__out PULONG ReturnOutputBufferLength
)
/*++
Routine Description:
This function fills OutputBuffer with as many LOG_RECORDs as possible.
The LOG_RECORDs are variable sizes and are tightly packed in the
OutputBuffer.
NOTE: This code must be NON-PAGED because it uses a spin-lock.
Arguments:
OutputBuffer - The user's buffer to fill with the log data we have
collected
OutputBufferLength - The size in bytes of OutputBuffer
ReturnOutputBufferLength - The amount of data actually written into the
OutputBuffer.
Return Value:
STATUS_SUCCESS if some records were able to be written to the OutputBuffer.
STATUS_NO_MORE_ENTRIES if we have no data to return.
STATUS_BUFFER_TOO_SMALL if the OutputBuffer is too small to
hold even one record and we have data to return.
--*/
{
PLIST_ENTRY pList;
ULONG bytesWritten = 0;
PLOG_RECORD pLogRecord;
NTSTATUS status = STATUS_NO_MORE_ENTRIES;
PRECORD_LIST pRecordList;
KIRQL oldIrql;
BOOLEAN recordsAvailable = FALSE;
KeAcquireSpinLock( &MiniSpyData.OutputBufferLock, &oldIrql );
while (!IsListEmpty( &MiniSpyData.OutputBufferList ) && (OutputBufferLength > 0)) {
//
// Mark we have records
//
recordsAvailable = TRUE;
//
// Get the next available record
//
pList = RemoveHeadList( &MiniSpyData.OutputBufferList );
pRecordList = CONTAINING_RECORD( pList, RECORD_LIST, List );
pLogRecord = &pRecordList->LogRecord;
//
// If no filename was set then make it into a NULL file name.
//
if (REMAINING_NAME_SPACE( pLogRecord ) == MAX_NAME_SPACE) {
//
// We don't have a name, so return an empty string.
// We have to always start a new log record on a PVOID aligned boundary.
//
pLogRecord->Length += ROUND_TO_SIZE( sizeof( UNICODE_NULL ), sizeof( PVOID ) );
pLogRecord->Name[0] = UNICODE_NULL;
}
//
// Put it back if we've run out of room.
//
if (OutputBufferLength < pLogRecord->Length) {
InsertHeadList( &MiniSpyData.OutputBufferList, pList );
break;
}
KeReleaseSpinLock( &MiniSpyData.OutputBufferLock, oldIrql );
//
// The lock is released, return the data, adjust pointers.
// Protect access to raw user-mode OutputBuffer with an exception handler
//
try {
RtlCopyMemory( OutputBuffer, pLogRecord, pLogRecord->Length );
} except( EXCEPTION_EXECUTE_HANDLER ) {
//
// Put the record back in
//
KeAcquireSpinLock( &MiniSpyData.OutputBufferLock, &oldIrql );
InsertHeadList( &MiniSpyData.OutputBufferList, pList );
KeReleaseSpinLock( &MiniSpyData.OutputBufferLock, oldIrql );
return GetExceptionCode();
}
bytesWritten += pLogRecord->Length;
OutputBufferLength -= pLogRecord->Length;
OutputBuffer += pLogRecord->Length;
SpyFreeRecord( pRecordList );
//
// Relock the list
//
KeAcquireSpinLock( &MiniSpyData.OutputBufferLock, &oldIrql );
}
KeReleaseSpinLock( &MiniSpyData.OutputBufferLock, oldIrql );
//
// Set proper status
//
if ((bytesWritten == 0) && recordsAvailable) {
//
// There were records to be sent up but
// there was not enough room in the buffer.
//
status = STATUS_BUFFER_TOO_SMALL;
} else if (bytesWritten > 0) {
//
// We were able to write some data to the output buffer,
// so this was a success.
//
status = STATUS_SUCCESS;
}
*ReturnOutputBufferLength = bytesWritten;
return status;
}
VOID
SpyEmptyOutputBufferList (
VOID
)
/*++
Routine Description:
This routine frees all the remaining log records in the OutputBufferList
that are not going to get sent up to the user mode application since
MiniSpy is shutting down.
NOTE: This code must be NON-PAGED because it uses a spin-lock
Arguments:
None.
Return Value:
None.
--*/
{
PLIST_ENTRY pList;
PRECORD_LIST pRecordList;
KIRQL oldIrql;
KeAcquireSpinLock( &MiniSpyData.OutputBufferLock, &oldIrql );
while (!IsListEmpty( &MiniSpyData.OutputBufferList )) {
pList = RemoveHeadList( &MiniSpyData.OutputBufferList );
KeReleaseSpinLock( &MiniSpyData.OutputBufferLock, oldIrql );
pRecordList = CONTAINING_RECORD( pList, RECORD_LIST, List );
SpyFreeRecord( pRecordList );
KeAcquireSpinLock( &MiniSpyData.OutputBufferLock, &oldIrql );
}
KeReleaseSpinLock( &MiniSpyData.OutputBufferLock, oldIrql );
}
//---------------------------------------------------------------------------
// Logging routines
//---------------------------------------------------------------------------
VOID
SpyReadDriverParameters (
__in PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This routine tries to read the MiniSpy-specific parameters from
the registry. These values will be found in the registry location
indicated by the RegistryPath passed in.
Arguments:
RegistryPath - the path key which contains the values that are
the MiniSpy parameters
Return Value:
None.
--*/
{
OBJECT_ATTRIBUTES attributes;
HANDLE driverRegKey;
NTSTATUS status;
ULONG resultLength;
UNICODE_STRING valueName;
PKEY_VALUE_PARTIAL_INFORMATION pValuePartialInfo;
UCHAR buffer[sizeof( KEY_VALUE_PARTIAL_INFORMATION ) + sizeof( LONG )];
//
// Open the registry
//
InitializeObjectAttributes( &attributes,
RegistryPath,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL );
status = ZwOpenKey( &driverRegKey,
KEY_READ,
&attributes );
if (!NT_SUCCESS( status )) {
return;
}
//
// Read the MaxRecordsToAllocate entry from the registry
//
RtlInitUnicodeString( &valueName, MAX_RECORDS_TO_ALLOCATE );
status = ZwQueryValueKey( driverRegKey,
&valueName,
KeyValuePartialInformation,
buffer,
sizeof(buffer),
&resultLength );
if (NT_SUCCESS( status )) {
pValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION) buffer;
ASSERT( pValuePartialInfo->Type == REG_DWORD );
MiniSpyData.MaxRecordsToAllocate = *((PLONG)&(pValuePartialInfo->Data));
}
//
// Read the NameQueryMethod entry from the registry
//
RtlInitUnicodeString( &valueName, NAME_QUERY_METHOD );
status = ZwQueryValueKey( driverRegKey,
&valueName,
KeyValuePartialInformation,
buffer,
sizeof(buffer),
&resultLength );
if (NT_SUCCESS( status )) {
pValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION) buffer;
ASSERT( pValuePartialInfo->Type == REG_DWORD );
MiniSpyData.NameQueryMethod = *((PLONG)&(pValuePartialInfo->Data));
}
ZwClose(driverRegKey);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -