Exemple #1
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;
}
NTSTATUS
GingkoRead (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
	NTSTATUS status = STATUS_SUCCESS;
	PVOID pBuff = NULL;
	BOOLEAN GingkoFile = FALSE;
	PGINGKO_OBJECT pGingkoObject = NULL;
	PIO_STACK_LOCATION irpsp = NULL;
	PFILE_OBJECT FileObject = NULL;
	SharedNotificationPtr snf = NULL;
	PGINGKO_PROCESS_LIST pProcessList = NULL;
	PGINGKO_DEVICE_EXTENSION DevExt = DeviceObject->DeviceExtension;

	if ( IS_GINGKO_CONTROL_DEVICE_OBJECT(DeviceObject) ) {
		//KdPrint( ("READ: Read Gingko Control Device...") );
		Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest( Irp, IO_NO_INCREMENT );
		return STATUS_INVALID_DEVICE_REQUEST;
	}

	REDFISH_NETWORK_DISPATCH( DeviceObject, Irp );

	if( IsGingkoServerProcess()  || PsIsSystemThread(KeGetCurrentThread()) )
	{
		return GingkoPassThrough( DeviceObject, Irp );
	}

	snf = GingkoReferenceSharedNotification();

	if( gGingkoServerStarted == FALSE || snf == NULL )
	{
		return GingkoPassThrough( DeviceObject, Irp );
	}

	GingkoDereferenceSharedNotification( snf );

	irpsp = IoGetCurrentIrpStackLocation(Irp);

	FileObject = irpsp->FileObject;
	
	if( FsRtlIsPagingFile( FileObject ) )
	{
		KdPrint(("This is a Paging file: %wZ.\n", &(FileObject->FileName)));
	}

	//RtlInitUnicodeString( &TempName, L"\\GingkoDebug\\dbgview.chm" );

	//if( RtlCompareUnicodeString( &TempName, &FileObject->FileName, TRUE ) == 0 )
	//{
	//	LARGE_INTEGER OriginalOffset = irpsp->Parameters.Read.ByteOffset;
	//	long		  OriginalLength = irpsp->Parameters.Read.Length;
	//	KdPrint(("Read DbgView: %I64d (L: %08x, H: %08x) Lenght: %08x\n", OriginalOffset.QuadPart, OriginalOffset.LowPart, 
	//		OriginalOffset.HighPart, OriginalLength));
	//}

	if( FindWriteFileObject( FileObject, IoGetRequestorProcessId(Irp), &pGingkoObject, FALSE ) )
	{
	    NTSTATUS status = 0L;
		if( pGingkoObject != NULL ) //&& pGingkoObject->Queue.CryptoInfo != NULL && ( pGingkoObject->Permission & 0x800F0000 | pGingkoObject->Permission & 0x8000F000 ) )
		{
			if( irpsp->Parameters.Read.Length > 0L )
			{
				if( !Irp->MdlAddress )
				{
					__try{
						ProbeForRead( Irp->UserBuffer, irpsp->Parameters.Read.Length, 1);
						IoAllocateMdl( Irp->UserBuffer, irpsp->Parameters.Read.Length, FALSE, FALSE, Irp );
						if( Irp->MdlAddress )
						{
							MmProbeAndLockPages( Irp->MdlAddress, UserMode, IoReadAccess );
						}
					}__except(EXCEPTION_EXECUTE_HANDLER)
					{
						KdPrint(("Exception Code: %08x. PassThrough. The Write Length is %d, Offset: %I64d.\n", GetExceptionCode(), irpsp->Parameters.Read.Length, irpsp->Parameters.Read.ByteOffset ));
						if( Irp->MdlAddress )
						{
							IoFreeMdl( Irp->MdlAddress );
							Irp->MdlAddress = NULL;
						}
					}
				}
			}

			status = EncryptedIoQueueAddIrp (&pGingkoObject->Queue, Irp);
			
			if( status != STATUS_PENDING )
				TCCompleteDiskIrp ( Irp, status, 0 );

			return status;
		}