Esempio n. 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;
}
Esempio n. 2
0
NTSTATUS
PtInstanceSetup (
				 __in PCFLT_RELATED_OBJECTS FltObjects,
				 __in FLT_INSTANCE_SETUP_FLAGS Flags,
				 __in DEVICE_TYPE VolumeDeviceType,
				 __in FLT_FILESYSTEM_TYPE VolumeFilesystemType
				 )
{
	PDEVICE_OBJECT devObj = NULL;
	PVOLUME_CONTEXT ctx = NULL;
	PFILE_FS_SIZE_INFORMATION VolumeBuffer = NULL;
	NTSTATUS status = STATUS_SUCCESS;
	ULONG retLen;
	PUNICODE_STRING workingName;
	USHORT size;
	IO_STATUS_BLOCK IoStatus;

	UCHAR volPropBuffer[sizeof(FLT_VOLUME_PROPERTIES)+512];
	PFLT_VOLUME_PROPERTIES volProp = (PFLT_VOLUME_PROPERTIES)volPropBuffer;

	PAGED_CODE();

	UNREFERENCED_PARAMETER( Flags );
	UNREFERENCED_PARAMETER( VolumeDeviceType );
	UNREFERENCED_PARAMETER( VolumeFilesystemType );

	try {

		//我们在卷上下文中保存扇区大小跟一个资源,用卷上下文完成vcb的工作
		status = FltAllocateContext( FltObjects->Filter,
			FLT_VOLUME_CONTEXT,
			sizeof(VOLUME_CONTEXT),
			NonPagedPool,
			&ctx );

		if (!NT_SUCCESS(status)) 
		{
			leave;
		}

		status = FltGetVolumeProperties( FltObjects->Volume,
			volProp,
			sizeof(volPropBuffer),
			&retLen );

		if (!NT_SUCCESS(status)) 
		{

			leave;
		}

		ASSERT((volProp->SectorSize  == 0) || (volProp->SectorSize  >= MIN_SECTOR_SIZE));

		if(volProp->SectorSize  > MAX_SECTOR_SIZE)
		{
			DbgPrint("不支持这么大的扇区的磁盘 %d \n",volProp->SectorSize );
			status = STATUS_UNSUCCESSFUL;
			leave;
		}

		ctx->SectorSize = max(volProp->SectorSize ,MIN_SECTOR_SIZE);

		ctx->VolResource = X70FsdAllocateResource();

		ctx->DeviceType = volProp->DeviceType;

		VolumeBuffer = FltAllocatePoolAlignedWithTag(FltObjects->Instance,NonPagedPool,sizeof(FILE_FS_SIZE_INFORMATION),'clu');

		if(VolumeBuffer == NULL)
		{
			status = STATUS_INSUFFICIENT_RESOURCES;
			leave;
		}

		status = FltQueryVolumeInformation(
			FltObjects->Instance,
			&IoStatus,
			VolumeBuffer,
			sizeof(FILE_FS_SIZE_INFORMATION),
			FileFsSizeInformation
			); 

		if (NT_SUCCESS(status)) 
		{

			ctx->SectorsPerAllocationUnit = VolumeBuffer->SectorsPerAllocationUnit;
		}
		else
		{
			ctx->SectorsPerAllocationUnit = 1; //网络设备会返回失败。
		}

		FltIsVolumeWritable(FltObjects->Volume,&ctx->IsWritable );

		status = FltSetVolumeContext( FltObjects->Volume,
			FLT_SET_CONTEXT_KEEP_IF_EXISTS,
			ctx,
			NULL );

		if (status == STATUS_FLT_CONTEXT_ALREADY_DEFINED) 
		{
			status = STATUS_SUCCESS;
		}

	} 
	finally 
	{

		if (ctx != NULL)
		{

			FltReleaseContext( ctx );
		}
		if(VolumeBuffer != NULL)
		{
			FltFreePoolAlignedWithTag(FltObjects->Instance,VolumeBuffer,'clu');
		}
	}

	return status;
}
Esempio n. 3
0
NTSTATUS
File_UpdateEntireFileByFileObject(
	__in PFLT_CALLBACK_DATA Data,
	__in PFLT_RELATED_OBJECTS FltObjects,
	__in PFILE_OBJECT FileObject, 
	__in PSTREAM_CONTEXT pStreamCtx,
	__in PVOLUME_CONTEXT pVolCtx
	)
{
	NTSTATUS status = STATUS_SUCCESS ;
	PUCHAR Buffer = NULL ;
	LARGE_INTEGER ReadWriteOffset = {0} ;
	BOOLEAN EndOfFile = FALSE;
	ULONG uReadBytes = 0 ;
	ULONG uWriteBytes = 0 ;
	ULONG uAllocateBufferSize = 1024*64 ; 
	ULONG uReadWriteLength = 0 ;
	ULONG uOffset = 0 ;
	LARGE_INTEGER FileSize = {0} ;
	PFILE_FLAG psFileFlag = NULL ;
	KIRQL OldIrql ;

	try{

		//判断分配空间长度是否SectorSize对齐
		if ((uAllocateBufferSize % pVolCtx->SectorSize) != 0)
		{//由于SectorSize目前为512bytes,故暂时先返回失败,以后可以对AllocateBufferSize进行调整
			status = ERR_CORE_LENGTH_NOT_ALIGNED ;
			__leave ;
		}

		Buffer = FltAllocatePoolAlignedWithTag(FltObjects->Instance,PagedPool, uAllocateBufferSize, FILEFLAG_POOL_TAG);
		if (!Buffer)
		{
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave ;
		}

             //allocate local file flag buffer
		psFileFlag = (PFILE_FLAG)ExAllocatePoolWithTag(NonPagedPool, FILE_FLAG_LENGTH, FILEFLAG_POOL_TAG) ;
		if (NULL == psFileFlag)
		{
			status = STATUS_INSUFFICIENT_RESOURCES ;
			__leave ;
		}
		RtlCopyMemory(psFileFlag, g_psFileFlag, FILE_FLAG_LENGTH) ; //实际上这里应该是当前文件自身的flag

        //set current file size into file flag buffer
        File_GetFileSize(Data, FltObjects, &FileSize) ;
		psFileFlag->FileValidLength= FileSize.QuadPart ;

		//calculate padded file size
		if (FileSize.QuadPart % SECTOR_SIZE)
		{//file size is not multiply of sector size
			FileSize.QuadPart = FileSize.QuadPart + (SECTOR_SIZE - FileSize.QuadPart % SECTOR_SIZE) + FILE_FLAG_LENGTH ;
		}
		else
		{//file size is multiply of sector size
			FileSize.QuadPart += FILE_FLAG_LENGTH ;
		}
		RtlCopyMemory(psFileFlag->FileKeyHash, pStreamCtx->szKeyHash, HASH_SIZE) ;
		

		while (TRUE)
		{
			status = File_ReadWriteFile(IRP_MJ_READ, 
										FltObjects->Instance, 
										FileObject, 
										&ReadWriteOffset,
										uAllocateBufferSize, 
										Buffer, 
										&uReadBytes,
										FLTFL_IO_OPERATION_NON_CACHED|FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET) ;
			if (!NT_SUCCESS(status))
				break;

			if (0 == uReadBytes)
				break;

			if (KeGetCurrentIrql() > PASSIVE_LEVEL)
				ExAcquireSpinLock(&pVolCtx->FsCryptSpinLock, &OldIrql);
			else
				ExAcquireFastMutex(&pVolCtx->FsCtxTableMutex) ;
			///if (data_crypt(pVolCtx->aes_ctr_ctx, Buffer, uOffset, uReadBytes))
			///{
			///	if (KeGetCurrentIrql() > PASSIVE_LEVEL)
			///		ExReleaseSpinLock(&pVolCtx->FsCryptSpinLock, OldIrql) ;
			///	else
			///		ExReleaseFastMutex(&pVolCtx->FsCtxTableMutex) ;
			///	break ;
			///}
			if (KeGetCurrentIrql() > PASSIVE_LEVEL)
				ExReleaseSpinLock(&pVolCtx->FsCryptSpinLock, OldIrql) ;
			else
				ExReleaseFastMutex(&pVolCtx->FsCtxTableMutex) ;

			if (uReadBytes < uAllocateBufferSize)
				EndOfFile = TRUE;

			status = File_ReadWriteFile(IRP_MJ_WRITE, 
										FltObjects->Instance, 
										FileObject, 
										&ReadWriteOffset,
										uReadBytes, 
										Buffer, 
										&uWriteBytes,
										FLTFL_IO_OPERATION_NON_CACHED|FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET) ;
			if (!NT_SUCCESS(status))
				break;

			if (EndOfFile)
				break;
			
			uOffset += uAllocateBufferSize ;
			ReadWriteOffset.QuadPart += uAllocateBufferSize ;
			RtlZeroMemory(Buffer, uAllocateBufferSize) ;
		}

		// write file flag
		ReadWriteOffset.QuadPart = FileSize.QuadPart - FILE_FLAG_LENGTH ;
		File_ReadWriteFile(IRP_MJ_WRITE, 
						   FltObjects->Instance, 
						   FileObject, 
						   &ReadWriteOffset, 
						   FILE_FLAG_LENGTH, 
						   psFileFlag, 
						   &uWriteBytes,
						   FLTFL_IO_OPERATION_NON_CACHED|FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET) ;
		
	}
	finally{

		if (Buffer)
		{
			FltFreePoolAlignedWithTag(FltObjects->Instance, Buffer, FILEFLAG_POOL_TAG);
			Buffer = NULL ;
		}

		if (psFileFlag)
		{
			ExFreePoolWithTag(psFileFlag, FILEFLAG_POOL_TAG) ;
			psFileFlag = NULL ;
		}
	}

	return status;
}