Advertisement
Guest User

Untitled

a guest
Nov 27th, 2015
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. FLT_PREOP_CALLBACK_STATUS
  2. RWBPreCreate(
  3.     _Inout_ PFLT_CALLBACK_DATA Data,
  4.     _In_ PCFLT_RELATED_OBJECTS FltObjects,
  5.     _Flt_CompletionContext_Outptr_ PVOID *CompletionContext
  6.     ){
  7.         NTSTATUS status; // Operation status
  8.         PFLT_FILE_NAME_INFORMATION pFileNameInfo = NULL; // File name information for file being opened
  9.         UNICODE_STRING backupPath; // String to hold the backup file
  10.         HANDLE originalHandle = NULL, // Original file handle
  11.                backupHandle = NULL; // Backup file handle
  12.         PFILE_OBJECT pOriginalFileObject = NULL, // Pointer to original file object TODO: check if it must be de-allocated
  13.             pBackupFileObject = NULL; // Pointer to backup file object TODO: check if it must be de-allocated
  14.         OBJECT_ATTRIBUTES oaOriginal,  // Object attributes for original file
  15.                           oaBackup; // Object attributes for backup file
  16.         IO_STATUS_BLOCK iosbOriginal, // IO Status block for original file
  17.                         iosbBackup; // IO Status block for backup file
  18.         FILE_BASIC_INFORMATION fileInfo; // Basic file information
  19.  
  20.  
  21. // CODE EXECUTED IF THE FILE HAS .txt EXTENSION AND IF IT IS OPENED IN WRITE OR DELETE MODE
  22. #pragma region OpenOriginalFile
  23.             // Initialize file attributes for original file
  24.             InitializeObjectAttributes(
  25.                 &oaOriginal,
  26.                 &pFileNameInfo->Name,
  27.                 OBJ_KERNEL_HANDLE,
  28.                 NULL,
  29.                 NULL
  30.                 );
  31.  
  32.             // Open original file
  33.             status = FltCreateFileEx(
  34.                 Globals.Filter,
  35.                 FltObjects->Instance,
  36.                 &originalHandle,
  37.                 &pOriginalFileObject,
  38.                 FILE_READ_DATA | FILE_READ_ATTRIBUTES,
  39.                 &oaOriginal,
  40.                 &iosbOriginal,
  41.                 NULL,
  42.                 FILE_ATTRIBUTE_READONLY,
  43.                 (ULONG)0,
  44.                 FILE_OPEN,
  45.                 FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY | FILE_OPEN_FOR_BACKUP_INTENT,
  46.                 NULL,
  47.                 (ULONG)0,
  48.                 IO_IGNORE_SHARE_ACCESS_CHECK
  49.                 );
  50.  
  51.             // If the original object name was not found, the file does not exists and it's
  52.             // being created. This is not an error
  53.             if (status == STATUS_OBJECT_NAME_NOT_FOUND){
  54.                 [...]
  55.                 goto RWBPreCreateCleanup;
  56.             }
  57.  
  58.  
  59.             if (!NT_SUCCESS(status)){
  60.                 [...]
  61.                 goto RWBPreCreateCleanup;
  62.             }
  63. #pragma endregion Open the original file
  64. // Initialize object attributes for the backup file
  65.             InitializeObjectAttributes(
  66.                 &oaBackup,
  67.                 &backupPath,
  68.                 OBJ_KERNEL_HANDLE,
  69.                 NULL,
  70.                 NULL
  71.                 );
  72.  
  73.             // Try to open backup file (if it already exists)
  74.             status = FltCreateFileEx(
  75.                 Globals.Filter,
  76.                 FltObjects->Instance,
  77.                 &backupHandle,
  78.                 &pBackupFileObject,
  79.                 FILE_READ_DATA,
  80.                 &oaBackup,
  81.                 &iosbBackup,
  82.                 NULL,
  83.                 FILE_ATTRIBUTE_NORMAL,
  84.                 (ULONG)0,
  85.                 FILE_OPEN,
  86.                 FILE_NON_DIRECTORY_FILE,
  87.                 NULL,
  88.                 (ULONG)0,
  89.                 IO_IGNORE_SHARE_ACCESS_CHECK
  90.                 );
  91.  
  92.         // If the file was opened without problems, it means that it already existed and we have to check when it was created          
  93.             if (status == STATUS_SUCCESS){
  94.                 LARGE_INTEGER currentTime;
  95.  
  96.                 PT_DBG_PRINT(PTDBG_TRACE_OPERATION_STATUS,
  97.                     ("[RWB]: RWBPreCreate -> Backup file already exists. Checking attributes"));
  98.  
  99.                 status = FltQueryInformationFile(
  100.                     FltObjects->Instance,
  101.                     pBackupFileObject,
  102.                     &fileInfo,
  103.                     sizeof(fileInfo),
  104.                     FileBasicInformation,
  105.                     NULL
  106.                     );
  107.  
  108.                 if (!NT_SUCCESS(status)){
  109.                     [...]
  110.                     goto RWBPreCreateCleanup;
  111.                 }
  112.                 KeQuerySystemTime(&currentTime);
  113.                
  114.                 LONGLONG deltaBackup = (currentTime.QuadPart - fileInfo.ChangeTime.QuadPart) / 10000000;
  115.  
  116.     // If the last backup was made less than BACKUP_INTERVAL_SECONDS ago, we don't back it up again.
  117.     // Since times are expressed as number of 100-nanoseconds intervals since the start of the year 1601
  118.     // we do the appropriate computation. If we have to create the new file because the backup is too old,
  119.     // we close the old handle and open a new one is write mode
  120.                 if ( deltaBackup < BACKUP_INTERVAL_SECONDS){
  121.                     PT_DBG_PRINT(PTDBG_TRACE_OPERATION_STATUS,
  122.                         ("[RWB]: RWBPreCreate -> Backup file not old enough. Won't backup again (Cbd = %p, FileObject = %p)\n",
  123.                         Data,
  124.                         FltObjects->FileObject));
  125.  
  126.                     goto RWBPreCreateCleanup;
  127.                 }
  128.                 else{
  129.  
  130.                     FltClose(backupHandle);
  131.  
  132.                     status = FltCreateFileEx(
  133.                         Globals.Filter,
  134.                         FltObjects->Instance,
  135.                         &backupHandle,
  136.                         &pBackupFileObject,
  137.                         FILE_WRITE_DATA,
  138.                         &oaBackup,
  139.                         &iosbBackup,
  140.                         NULL,
  141.                         FILE_ATTRIBUTE_NORMAL,
  142.                         (ULONG)0,
  143.                         FILE_OVERWRITE,
  144.                         FILE_NON_DIRECTORY_FILE,
  145.                         NULL,
  146.                         (ULONG)0,
  147.                         IO_IGNORE_SHARE_ACCESS_CHECK
  148.                         );
  149.  
  150.                     if (!NT_SUCCESS(status)){
  151.                         PT_DBG_PRINT(PTDBG_TRACE_OPERATION_STATUS,
  152.                             ("[RWB]: RWBPreCreate -> Failed to overwrite backup file (Cbd = %p, FileObject = %p)\n",
  153.                             Data,
  154.                             FltObjects->FileObject));
  155.  
  156.                         goto RWBPreCreateCleanup;
  157.                     }
  158.                 }
  159.  
  160.             }
  161.             // If the creation fails with error STATUS_OBJECT_PATH_NOT_FOUND this means that the
  162.             // folder does not exists. Create the folder
  163.             else if (status == STATUS_OBJECT_PATH_NOT_FOUND){
  164.                 UNICODE_STRING previousFolder;
  165.                 // Creates a new string to hold the path without the final component
  166.                 previousFolder.MaximumLength = backupPath.Length - pFileNameInfo->FinalComponent.Length - sizeof(WCHAR);
  167.                 RWBAllocateUnicodeString(&previousFolder);
  168.                 RtlCopyMemory(
  169.                     previousFolder.Buffer,
  170.                     backupPath.Buffer,
  171.                     previousFolder.MaximumLength
  172.                     );
  173.                 previousFolder.Length = previousFolder.MaximumLength;
  174.  
  175.                 // Creates the previous folders
  176.                 RWBRollPath(
  177.                     previousFolder,
  178.                     Globals.Filter,
  179.                     FltObjects->Instance
  180.                     );
  181.  
  182.                 RWBFreeUnicodeString(&previousFolder);
  183.  
  184.                 // Create backup file. This time should not fail
  185.                 status = FltCreateFileEx(
  186.                     Globals.Filter,
  187.                     FltObjects->Instance,
  188.                     &backupHandle,
  189.                     &pBackupFileObject,
  190.                     FILE_WRITE_DATA,
  191.                     &oaBackup,
  192.                     &iosbBackup,
  193.                     NULL,
  194.                     FILE_ATTRIBUTE_NORMAL,
  195.                     (ULONG)0,
  196.                     FILE_CREATE,
  197.                     FILE_NON_DIRECTORY_FILE,
  198.                     NULL,
  199.                     (ULONG)0,
  200.                     IO_IGNORE_SHARE_ACCESS_CHECK
  201.                     );
  202.             }
  203.            
  204.            
  205.             if (!NT_SUCCESS(status)){
  206.                 PT_DBG_PRINT(PTDBG_TRACE_OPERATION_STATUS,
  207.                     ("[RWB]: RWBPreCreate -> Failed to create backup file (Cbd = %p, FileObject = %p)\n",
  208.                     Data,
  209.                     FltObjects->FileObject));
  210.  
  211.                 goto RWBPreCreateCleanup;
  212.             }
  213. #pragma endregion Create the backup file
  214. #pragma region CopyContent
  215.             // At this point, both the original handle and the backup handle must be valid
  216.             NT_ASSERT(originalHandle != NULL && backupHandle != NULL);
  217.             NT_ASSERT(pOriginalFileObject != NULL && pBackupFileObject != NULL);
  218.  
  219.             status = RWBCopyContent(
  220.                 FltObjects->Instance,
  221.                 pOriginalFileObject,
  222.                 pBackupFileObject
  223.                 );
  224.  
  225.  
  226.             if (!NT_SUCCESS(status)){
  227.                 [...]
  228.  
  229.                 goto RWBPreCreateCleanup;
  230.             }
  231. #pragma endregion Copy the content from the original file to the backup one
  232.  
  233. RWBPreCreateCleanup:
  234.  
  235.         if (originalHandle != NULL)
  236.             status = FltClose(originalHandle);
  237.  
  238.         if (backupHandle != NULL)
  239.             status = FltClose(backupHandle);
  240.  
  241.         if (pFileNameInfo != NULL)
  242.             FltReleaseFileNameInformation(pFileNameInfo);
  243.  
  244.         RWBFreeUnicodeString(&backupPath);
  245.  
  246.  
  247.         // TODO: Check for object attributes release
  248.  
  249.         return FLT_PREOP_SUCCESS_WITH_CALLBACK;
  250.     }
  251. }
  252.  
  253. NTSTATUS
  254. RWBRollPath(
  255.     _In_ UNICODE_STRING Path,
  256.     _In_ PFLT_FILTER Filter,
  257.     _In_ PFLT_INSTANCE Instance
  258. )
  259. /*
  260. Routine Description:
  261.  
  262. This routine creates the directory specified as input
  263.  
  264. Arguments:
  265.  
  266. Path - The path to create
  267.  
  268. Return Value:
  269.  
  270. STATUS_SUCCESS                  - success
  271.  
  272. */
  273. {
  274.     NTSTATUS status = STATUS_SUCCESS;
  275.     HANDLE directoryHandle = NULL;
  276.     OBJECT_ATTRIBUTES objectAttributes;
  277.     IO_STATUS_BLOCK ioStatusBlock;
  278.     UNICODE_STRING previousFolder;
  279.  
  280.     // Initialize object attributes to set the path
  281.     InitializeObjectAttributes(
  282.         &objectAttributes,
  283.         &Path,
  284.         OBJ_CASE_INSENSITIVE,
  285.         NULL,
  286.         NULL
  287.         );
  288.  
  289.     // Tries to create the directory.
  290.     status = FltCreateFile(
  291.         Filter,
  292.         Instance,
  293.         &directoryHandle,
  294.         FILE_LIST_DIRECTORY | FILE_TRAVERSE,
  295.         &objectAttributes,
  296.         &ioStatusBlock,
  297.         NULL,
  298.         FILE_ATTRIBUTE_NORMAL,
  299.         FILE_SHARE_READ | FILE_SHARE_WRITE,
  300.         FILE_OPEN_IF,
  301.         FILE_DIRECTORY_FILE,
  302.         NULL,
  303.         (ULONG) 0,
  304.         IO_IGNORE_SHARE_ACCESS_CHECK
  305.         );
  306.  
  307.     // If the directory already exists or it have been created, returns STATUS_SUCCESS
  308.     if (ioStatusBlock.Information == FILE_OPENED || ioStatusBlock.Information == FILE_CREATED){
  309.         status = STATUS_SUCCESS;
  310.         goto RWBRollPathCleanup;
  311.     }
  312.  
  313.     // If the create failed, it means that we have to create the previous directories and then try again to create this directory
  314.     if (!NT_SUCCESS(status)){
  315.         UNICODE_STRING finalComponent;
  316.         // Get the final component of the name and creates a new string without
  317.         // it in order to create the previous folder
  318.         FltParseFileName(&Path,
  319.             NULL,
  320.             NULL,
  321.             &finalComponent
  322.             );
  323.  
  324.         previousFolder.MaximumLength = Path.Length - finalComponent.Length - sizeof(WCHAR);
  325.         RWBAllocateUnicodeString(&previousFolder);
  326.         RtlCopyMemory(
  327.             previousFolder.Buffer,
  328.             Path.Buffer,
  329.             previousFolder.MaximumLength
  330.             );
  331.         previousFolder.Length = previousFolder.MaximumLength;
  332.  
  333.         // Creates the previous folders
  334.         RWBRollPath(
  335.             previousFolder,
  336.             Filter,
  337.             Instance
  338.             );
  339.  
  340.         // TODO: check status
  341.  
  342.         // Tries to create the directory again. This time should not fail since the previous folder have been created
  343.         status = FltCreateFile(
  344.             Filter,
  345.             Instance,
  346.             &directoryHandle,
  347.             FILE_LIST_DIRECTORY | FILE_TRAVERSE,
  348.             &objectAttributes,
  349.             &ioStatusBlock,
  350.             NULL,
  351.             FILE_ATTRIBUTE_NORMAL,
  352.             FILE_SHARE_READ | FILE_SHARE_WRITE,
  353.             FILE_OPEN_IF,
  354.             FILE_DIRECTORY_FILE,
  355.             NULL,
  356.             (ULONG)0,
  357.             IO_IGNORE_SHARE_ACCESS_CHECK
  358.             );
  359.         RWBFreeUnicodeString(&previousFolder);
  360.     }
  361.  
  362. RWBRollPathCleanup:
  363.  
  364.     if (directoryHandle != NULL)
  365.         status = FltClose(directoryHandle);
  366.  
  367.     return status;
  368. }
  369.  
  370. NTSTATUS
  371. RWBCopyContent(
  372.     PFLT_INSTANCE Instance,
  373.     PFILE_OBJECT pSourceObject,
  374.     PFILE_OBJECT pDestinationObject
  375. )
  376. /*
  377. Routine Description :
  378. This routine copy the content of a file to another
  379.  
  380. Arguments:
  381.  
  382. Instance - The initiating instance
  383. SourceObject - Source file object
  384. DestinationObject - Destination file object
  385.  
  386. Return Value
  387.  
  388. STATUS_SUCCESS if the operation have been completed, otherwise the status that generated the error
  389.  
  390. */
  391. {
  392.     NTSTATUS status;
  393.     ULONG bytesRead; // Bytes read
  394.     UCHAR buffer[COPY_READ_SIZE]; // Buffer to hold read content during copy
  395.     LARGE_INTEGER readOffset, writeOffset; // Offset for read operation
  396.  
  397.     // Initialize offset for read and write operation
  398.     readOffset.QuadPart = 0;
  399.  
  400.     // Initialize offset for read and write operation
  401.     writeOffset.QuadPart = 0;
  402.  
  403.     // Read content
  404.     status = FltReadFile(
  405.         Instance,
  406.         pSourceObject,
  407.         &readOffset,
  408.         (ULONG)COPY_READ_SIZE,
  409.         buffer,
  410.         FLTFL_IO_OPERATION_NON_CACHED,
  411.         &bytesRead,
  412.         NULL,
  413.         NULL
  414.         );
  415.  
  416.     readOffset.QuadPart += bytesRead;
  417.  
  418.     while (status != STATUS_END_OF_FILE){
  419.  
  420.         // Write content
  421.         status = FltWriteFile(
  422.             Instance,
  423.             pDestinationObject,
  424.             &writeOffset,
  425.             bytesRead,
  426.             buffer,
  427.             FLTFL_IO_OPERATION_NON_CACHED,
  428.             &bytesRead,
  429.             NULL,
  430.             NULL
  431.             );
  432.  
  433.         writeOffset.QuadPart += bytesRead;
  434.        
  435.         if (!NT_SUCCESS(status)){
  436.             PT_DBG_PRINT(PTDBG_TRACE_OPERATION_STATUS,
  437.                 ("[RWB]: RWBCopyContent -> Write failed with error  %llx", status));
  438.  
  439.         }
  440.         // Read new content content
  441.         status = FltReadFile(
  442.             Instance,
  443.             pSourceObject,
  444.             &readOffset,
  445.             (ULONG)COPY_READ_SIZE,
  446.             buffer,
  447.             FLTFL_IO_OPERATION_NON_CACHED,
  448.             &bytesRead,
  449.             NULL,
  450.             NULL
  451.             );
  452.  
  453.         readOffset.QuadPart += bytesRead;
  454.     }
  455.  
  456.     if (status == STATUS_END_OF_FILE)
  457.         return STATUS_SUCCESS;
  458.     else
  459.         return status;
  460. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement