Exemplo n.º 1
0
VOID
PtOperationStatusCallback (
						   __in PCFLT_RELATED_OBJECTS FltObjects,
						   __in PFLT_IO_PARAMETER_BLOCK ParameterSnapshot,
						   __in NTSTATUS OperationStatus,
						   __in PVOID RequesterContext
						   )
						   /*++

						   Routine Description:

						   This routine is called when the given operation returns from the call
						   to IoCallDriver.  This is useful for operations where STATUS_PENDING
						   means the operation was successfully queued.  This is useful for OpLocks
						   and directory change notification operations.

						   This callback is called in the context of the originating thread and will
						   never be called at DPC level.  The file object has been correctly
						   referenced so that you can access it.  It will be automatically
						   dereferenced upon return.

						   This is non-pageable because it could be called on the paging path

						   Arguments:

						   FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
						   opaque handles to this filter, instance, its associated volume and
						   file object.

						   RequesterContext - The context for the completion routine for this
						   operation.

						   OperationStatus -

						   Return Value:

						   The return value is the status of the operation.

						   --*/
{
	UNREFERENCED_PARAMETER( FltObjects );

	PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,
		("PassThrough!PtOperationStatusCallback: Entered\n") );

	PT_DBG_PRINT( PTDBG_TRACE_OPERATION_STATUS,
		("PassThrough!PtOperationStatusCallback: Status=%08x ctx=%p IrpMj=%02x.%02x \"%s\"\n",
		OperationStatus,
		RequesterContext,
		ParameterSnapshot->MajorFunction,
		ParameterSnapshot->MinorFunction,
		FltGetIrpName(ParameterSnapshot->MajorFunction)) );
}
Exemplo n.º 2
0
VOID PtOperationStatusCallback(
	_In_ PCFLT_RELATED_OBJECTS FltObjects,
	_In_ PFLT_IO_PARAMETER_BLOCK ParameterSnapshot,
	_In_ NTSTATUS OperationStatus,
	_In_ PVOID RequesterContext)
{
	UNREFERENCED_PARAMETER(FltObjects);


	KdPrint(("PassThrough!PtOperationStatusCallback: Entered\n"));
	KdPrint(("PassThrough!PtOperationStatusCallback: Status=%08x ctx=%p IrpMj=%02x.%02x \"%s\"\n",
		OperationStatus,
		RequesterContext,
		ParameterSnapshot->MajorFunction,
		ParameterSnapshot->MinorFunction,
		FltGetIrpName(ParameterSnapshot->MajorFunction)));
}
Exemplo n.º 3
0
EXTERN_C static NTSTATUS ScvnpScavenge(_Inout_ PFLT_CALLBACK_DATA Data,
                                       _In_ PCFLT_RELATED_OBJECTS FltObjects) {
  PAGED_CODE();

  // Ignore system threads. Thus, this program does not support activities of
  // kernel mode code.
  if (PsIsSystemThread(PsGetCurrentThread())) {
    return STATUS_SUCCESS;
  }

  const auto operationType = FltGetIrpName(Data->Iopb->MajorFunction);

  PFLT_FILE_NAME_INFORMATION fileNameInformation = nullptr;
  auto status = FltGetFileNameInformationUnsafe(
      FltObjects->FileObject, FltObjects->Instance, FLT_FILE_NAME_NORMALIZED,
      &fileNameInformation);
  if (!NT_SUCCESS(status)) {
    // This error is expected to happen and okay to ignore it.
    if (status != STATUS_FILE_DELETED) {
      LOG_ERROR_SAFE("%-25s : FltGetFileNameInformationUnsafe failed (%08x)",
                     operationType, status);
    }
    return status;
  }

  status = FltParseFileNameInformation(fileNameInformation);
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("%-25s : FltParseFileNameInformation failed (%08x) for %wZ",
                   operationType, status, &fileNameInformation->Name);
    FltParseFileNameInformation(fileNameInformation);
    return status;
  }

  // Ignore directories
  BOOLEAN isDirectory = FALSE;
  status = FltIsDirectory(FltObjects->FileObject, FltObjects->Instance,
                          &isDirectory);
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("%-25s : FltIsDirectory failed (%08x) for %wZ",
                   operationType, status, &fileNameInformation->Name);
    FltParseFileNameInformation(fileNameInformation);
    return status;
  }
  if (isDirectory) {
    FltParseFileNameInformation(fileNameInformation);
    return status;
  }

  // Go through a white list
  if (ScvnpIsWhiteListedFile(&fileNameInformation->Name)) {
    FltParseFileNameInformation(fileNameInformation);
    return status;
  }

  // Get a file size (etc).
  FILE_STANDARD_INFORMATION fileInfo = {};
  status = FltQueryInformationFile(FltObjects->Instance, FltObjects->FileObject,
                                   &fileInfo, sizeof(fileInfo),
                                   FileStandardInformation, nullptr);
  if (!NT_SUCCESS(status)) {
    // This error is expected to happen and okay to ignore it.
    if (status != STATUS_FILE_DELETED) {
      LOG_ERROR_SAFE("%-25s : FltQueryInformationFile failed (%08x) for %wZ",
                     operationType, status, &fileNameInformation->Name);
    }
    FltParseFileNameInformation(fileNameInformation);
    return status;
  }

  // Ignore if the file is empty
  if (fileInfo.EndOfFile.QuadPart == 0) {
    FltParseFileNameInformation(fileNameInformation);
    return status;
  }

  // Ignore if the file size is greater than 4GB
  if (fileInfo.EndOfFile.HighPart != 0) {
    FltParseFileNameInformation(fileNameInformation);
    return STATUS_FILE_TOO_LARGE;
  }

  const auto targetFileSize = fileInfo.EndOfFile.LowPart;

  // Read entire contents of the file onto non paged memory. Thus, it may fail
  // to handle a file larger than the amount of available memory.
  const auto buffer = FltAllocatePoolAlignedWithTag(
      FltObjects->Instance, NonPagedPoolNx, targetFileSize, SCVN_POOL_TAG_NAME);
  if (!buffer) {
    LOG_ERROR_SAFE(
        "%-25s : FltAllocatePoolAlignedWithTag failed (%lu bytes) for %wZ",
        operationType, targetFileSize, &fileNameInformation->Name);
    goto End;
  }
  status = ScvnpReadFile(Data, FltObjects, buffer, targetFileSize);
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("%-25s : ScvnpReadFile failed (%08x) for %wZ", operationType,
                   status, &fileNameInformation->Name);
    goto End;
  }

  // Calculate SHA1 of the written data.
  UCHAR sha1Hash[20] = {};
  status = ScvnpGetSha1(sha1Hash, buffer, targetFileSize);
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("%-25s : ScvnpGetSha1 failed (%08x) for %wZ", operationType,
                   status, &fileNameInformation->Name);
    goto End;
  }
  wchar_t sha1HashW[41] = {};
  for (auto i = 0; i < RTL_NUMBER_OF(sha1Hash); ++i) {
    const auto outW = sha1HashW + i * 2;
    RtlStringCchPrintfW(outW, 3, L"%02x", sha1Hash[i]);
  }

  // Copy the read file contents to the out put folder as <SHA1>.bin.
  wchar_t outPathW[260];
  status = RtlStringCchPrintfW(outPathW, RTL_NUMBER_OF(outPathW), L"%s\\%s.bin",
                               SCVNP_OUT_DIRECTORY_PATH, sha1HashW);
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("%-25s : RtlStringCchPrintfW failed (%08x) for %wZ",
                   operationType, status, &fileNameInformation->Name);
    goto End;
  }
  status =
      ScvnpWriteFile(FltObjects, outPathW, buffer, targetFileSize, FILE_CREATE);
  if (status == STATUS_DELETE_PENDING) {
    status = STATUS_SUCCESS;
    goto End;
  }

  if (status == STATUS_OBJECT_NAME_COLLISION) {
    // The same SHA1 is already there
    LOG_INFO_SAFE("%-25s for %wZ (dup with %S, %lu bytes, %wZ)", operationType,
                  &fileNameInformation->FinalComponent, sha1HashW,
                  targetFileSize, &fileNameInformation->Name);
    status = STATUS_SUCCESS;
    goto End;
  }

  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("%-25s : ScvnpWriteFile failed (%08x) for %wZ",
                   operationType, status, &fileNameInformation->Name);
    goto End;
  }

  // Done
  LOG_INFO_SAFE("%-25s for %wZ (saved as %S, %lu bytes, %wZ)", operationType,
                &fileNameInformation->FinalComponent, sha1HashW, targetFileSize,
                &fileNameInformation->Name);

End:
  if (buffer) {
    FltFreePoolAlignedWithTag(FltObjects->Instance, buffer, SCVN_POOL_TAG_NAME);
  }
  if (fileNameInformation) {
    FltParseFileNameInformation(fileNameInformation);
  }
  return status;
}