Шифрование файлов в windows

124
20 сентября 2019, 10:00

Задание звучит следующим образом:

Необходимо реализовать программное средство, которое осуществляет шифрование файлов в заданной директории. Файлы в зашифрованном состоянии должны находиться на жестком диске, а при обращении к ним сторонних программ (notepad, Total Commander, Visual Studio, и т.д.) должна выполняться проверка доступности файла для данной программы. Если программа имеет разрешение на просмотр файла – то произвести расшифровку файла и передать открытое содержимое вызывающей программе; если программа не имеет разрешения – то передать зашифрованное содержимое файла. При добавлении файла в директорию автоматически должно производиться его шифрование.

Программное средство должно быть реализовано в виде драйвера, функционирующий в режиме ядра. Программное средство должно функционировать на 64-разрядной версии операционной системы Microsoft Windows 10. Имя и путь к директории задается на ваш выбор в коде драйвера. Список программ, имеющих разрешение на доступ к файлам, задается на ваш выбор.

Кто может подсказать каким образом это можно реализовать? Что нужно знать для этого? Что почитать?

Сам лично я никогда не писал драйвера, и понятия не имею с чего начать.

Answer 1

Я писал такую программу под Windows 95 на C++. Читать и знать надо очень много. Во-первых, нужно DDK, во-вторых, они меняются под каждую версию ОС, и программу приходится переписывать (во всяком случае, тогда пришлось переписывать под Windows XP), в-третьих, не знаю как сейчас, но тогда DDK не содержал подобных примеров, это издавалось отдельно с запретом поставки к нам, и пришлось нужное украсть, благо я работал в ФАПСИ. Так что начните со скачивания DDK, и попробуйте там найти подходящий пример. Если хотите, выложу наш код драйвера под Windows 95.

Answer 2

Вот что нужно знать в первую очередь, а раньше было "труднодоступно", чтобы писать драйверы уровня кернеля ноль для работы с файловой системой:

//
// undocumented ntoskrnl variable
//
extern PSHORT           NtBuildNumber;
//
// NT Final Build number
//
#define NT4FINAL     1381
typedef struct _FILE_RENAME_INFORMATION {
    BOOLEAN          ReplaceIfExists;
    HANDLE           RootDirectory;
    ULONG            FileNameLength;
    WCHAR            FileName[1];
} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION;
typedef struct _FILE_NAME_INFORMATION {
    ULONG            FileNameLength;
    WCHAR            FileName[1];
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
// Using NTREGMON-type "hooking" on ZwCreateFile;
// ObReferenceObjectByHandle, System WORKITEMS;
// ObOpenObjectByPointer and ZwReadFile I finally have a solution that
// appears stable.
NTKERNELAPI
NTSTATUS
ObOpenObjectByPointer(
    IN PVOID Object,
    IN ULONG HandleAttributes,
    IN PACCESS_STATE PassedAccessState OPTIONAL,
    IN ACCESS_MASK DesiredAccess OPTIONAL,
    IN POBJECT_TYPE ObjectType OPTIONAL,
    IN KPROCESSOR_MODE AccessMode,
    OUT PHANDLE Handle
    );

// There are two steps in getting the threads context. First you 
// must get a handle to the thread via PsGetCurrentThread() or 
// KeGetCurrentThread(). After you get the handle to the thread, 
// you must call the following function:
NTSYSAPI NTSTATUS NTAPI ZwGetContextThread 
(
    IN HANDLE ThreadHandle,
    IN OUT PCONTEXT ThreadContext
);
// Remember, when creating the thread, you must specify an access 
// type of THREAD_GET_CONTEXT in order to read the context information 
// from the thread.
NTSYSAPI
NTSTATUS 
NTAPI
ZwOpenFile( OUT PHANDLE FileHandle,
            IN ACCESS_MASK DesiredAccess,
            IN POBJECT_ATTRIBUTES ObjectAttributes,
            IN PIO_STATUS_BLOCK IoStatusBlock,
            IN ULONG ShareAccess,
            IN ULONG CreateOptions );
NTSYSAPI
VOID
NTAPI
HalDisplayString( PCHAR String );

NTKERNELAPI
NTSTATUS
IoQueryFileInformation(
    IN PFILE_OBJECT FileObject,
    IN FILE_INFORMATION_CLASS FileInformationClass,
    IN ULONG Length,
    OUT PVOID FileInformation,
    OUT PULONG ReturnedLength
    );

NTSYSAPI // preliminary guess
NTSTATUS
NTAPI
ZwQueryVolumeInformationFile(
    IN HANDLE FileHandle,
    OUT PIO_STATUS_BLOCK IoStatusBlock,
    OUT PVOID FsInformation,
    IN ULONG Length,
    IN FS_INFORMATION_CLASS FsInformationClass
    );

NTKERNELAPI // preliminary guess
NTSTATUS
IoQueryFileVolumeInformation(
    IN PFILE_OBJECT FileObject,
    IN FS_INFORMATION_CLASS FsInformationClass,
    IN ULONG Length,
    OUT PVOID FsInformation,
    OUT PULONG ReturnedLength
    );

NTSTATUS
ZwOpenDirectoryObject( OUT PHANDLE DirectoryHandle,
                       IN ULONG DesiredAccess,
                       IN POBJECT_ATTRIBUTES ObjectAttributes ); 
NTSTATUS
ZwOpenSymbolicLinkObject( OUT PHANDLE SymbolicLinkHandle,
                          IN ULONG DesiredAccess,
                          IN POBJECT_ATTRIBUTES ObjectAttributes ); 

NTSTATUS
ZwQuerySymbolicLinkObject( IN HANDLE SymbolicLinkHandle,
                           OUT PUNICODE_STRING ReturnedString,
                           OUT PULONG ReturnedLength ); 
NTSYSAPI
NTSTATUS 
NTAPI
ZwCreateSection( OUT PHANDLE SectionHandle,
                 IN ACCESS_MASK DesiredAccess,
                 IN POBJECT_ATTRIBUTES ObjectAttributes,   // Optional
                 IN PLARGE_INTEGER MaximumSize,            // Optional
                 IN ULONG SectionPageProtection,
                 IN ULONG AllocationAttributes,
                 IN HANDLE FileHandle );                   // Optional
//
// Parameters:
// SectionHandle   if routine succeeds, you get back a section handle 
//                 in this argument. If you want to use the section
//                 object in the context of some other process, use the
//                 ObReferenceObjectByHandle() and ObOpenObjectByPointer() 
//                 combination to do so ...
//
// DesiredAccess   set this to one of SECTION_MAP_EXECUTE, ...MAP_READ, or
//                 ..._MAP_WRITE 
//
// ObjectAttributes - NULL, or use 
//                 InitializeObjectAttributes() macro to initialize this. 
//                 Use this to create a named section object if you wish 
//                 to share it with user mode process.
//
// MaximumSize     Must be non-NULL for a page-file backed section. If value
//                 specified for a mapped file and the file is not large enough, 
//                 file will be extended. NOTE: this is a POINTER to a large int.
//
// SectionPageProtection  use from PAGE_READONLY, READWRITE, ...WRITEONLY, 
//                 and/or WRITECOPY.
//
// AllocationAttributes  use SEC_IMAGE (executable only), SEC_FILE (for
//                 mapping in a data file), SEC_RESERVE, SEC_COMMIT. 
//                 NOTE: These defines are ONLY in the "winnt.h" file as part 
//                 of the SDK!!!
//
// FileHandle      optional, BUT you must supply if you wish to map in a data
//                 file. Else VMM will create a section object backed by a 
//                 page file.
//
//
// CcCanIWrite()
//
BOOLEAN
CcCanIWrite (
        IN PFILE_OBJECT FileObject,
        IN ULONG                        BytesToWrite,
        IN BOOLEAN                      Wait,
        IN BOOLEAN                      Retrying
);
//
// Resource Acquisition Constraints:
//
// If Wait is TRUE, the file system should ensure that no resources 
// have been acquired. Else, the caller can choose the have the FCB 
// resources unowned, acquired shared or exclusively.
//
// Parameters:
//
// FileObject      Pointer to the file object structure representing 
//                 the open operation performed by the thread.
//
// BytesToWrite    Number of bytes to be modified.
//
// Wait            This argument is used by the Cache Manager to determine 
//                 whether the caller is prepared to wait in the routine 
//                 until it is acceptable for the caller to be allowed 
//                 to perform the write operation.
//
// Retrying        The file system may have to keep requesting permission 
//                 to proceed with a write operation (if Wait is supplied 
//                 as FALSE), until it is allowed to do so. This argument 
//                 allows the file system to notify the Cache Manager 
//                 whether it had previously requested permission for the 
//                 same write request (or if the current instance was the 
//                 first time permission was being requested for the specific 
//                 write operation).
//
// Functionality Provided:
//
// This routine is part of a group of routines that allow the file system 
// to defer executing a write request until it is appropriate to do so. 
// A number of reasons may make executing a write operation immediately, 
// unattractive. They include the following:
//
//  - The file system may wish to restrict the number of dirty pages 
// outstanding per file stream at any given instance in time. This allows 
// the file system to ensure that cached data for other file streams does 
// not get discarded to make space for data belonging to a single file stream. 
// Such a situation may arise if some process kept modifying data for a 
// specific file stream at a very fast rate.
//
// - The Cache Manager tries to keep the total number of modified pages 
// for all files that have their data cached. within a certain limit. 
// This helps ensure that sufficient number of free pages are available 
// for other purposes including memory for loading executable files, 
// memory-mapped files, and memory for other system components.
//
// - The Virtual Memory Manager sets certain limits on the maximum number 
// of dirty pages within the system (based upon the total amount of physical 
// memory present on the system). If the write operation causes the limit 
// to be exceeded, the VMM would prefer that the write be deferred until 
// the modified page writer has flushed some of the existing dirty data to disk.
//
// In order to assist the Cache Manager and the Virtual Memory Manager in 
// managing physical memory optimally, the file system driver can use 
// the CcCanIWrite() routine to determine whether the current write operation 
// should be allowed to proceed. Use of this routine is optional.
//
// The Wait argument allows the file system to specify whether the thread 
// can be blocked until the write can be allowed to proceed. If Wait is 
// FALSE and the write operation should be deferred, the routine returns FALSE.
// The file system can then determine an appropriate course of action - this 
// might be to postpone the operation using the CcDeferWrite() routine described 
// next in this section. Setting WAIT to TRUE causes the Cache Manager to block 
// the current thread (by putting it to sleep) until the write can be allowed 
// to proceed. Of course, the file system should ensure that no resources are 
// acquired by the thread since this may lead to a system deadlock.
//
// The Retrying argument allows a file system to notify the Cache Manager 
// whether permission is being requested (for the same write request) either 
// for the first time, or whether such permission had been requested (and 
// denied) at least once before. If set to TRUE, the Cache Manager assigns a 
// slightly higher priority to the current request while determining whether  
// it should be allowed to proceed or not (e.g. if two write requests are 
// pending and one of them is being retried, the Cache Manager will try its 
// best to allow the one being retried to proceed first. Note however, that 
// there are no guarantees to ensure that the one being retried will indeed 
// be allowed to proceed before the one not being retried).
//
// Conceptually, the functionality provided by the Cache Manager in this 
// routine is fairly simple and is as follows:
//
// - First, check whether the current write operation can proceed based 
// upon different criteria. These criteria include (among others): checking 
// whether the outstanding number of dirty pages associated with a file 
// stream have been exceeded, whether the total number of dirty pages 
// in the system cache have exceeded some limit, or whether the Virtual 
// Memory Manager might wish to block this write for some time until 
// enough unmodified pages are available in the system.
//
// - If the write operation can proceed, return TRUE.
//
// - Else, if Wait is set to TRUE, put the current thread to sleep until 
// the write operation can be allowed to proceed. Once the thread is woken 
// from the sleep, return TRUE. However, if Wait is FALSE, return FALSE 
// immediately.
//

typedef
VOID (*PCC_POST_DEFERRED_WRITE) (
        IN PVOID                                Context1,
        IN PVOID                                Context2
);
//
// CcDeferWrite()
//
VOID
CcDeferWrite (
        IN PFILE_OBJECT                         FileObject,
        IN PCC_POST_DEFERRED_WRITE              PostRoutine,
        IN PVOID                                Context1,
        IN PVOID                                Context2,
        IN ULONG                                BytesToWrite,
        IN BOOLEAN                              Retrying
);

//
// Resource Acquisition Constraints:
//
// No resources should be acquired before invoking this routine.
//
// Parameters:
//
// FileObject      Pointer to the file object structure representing 
//                 the open operation performed by the thread.
//
// PostRoutine     The routine to be invoked whenever it is appropriate 
//                 for the current write request to proceed. Typically, 
//                 this is a recursive call into the file system write 
//                 routine.
//
// Context1 & Context2   These are arguments that the PostRoutine will 
//                       accept (when invoked). Typically, if the post 
//                       routine is the same as the generic write routine, 
//                       these arguments are the DeviceObject and the Irp 
//                       (for the current request).
//
// BytesToWrite    Number of bytes being modified.
//
// Retrying        Allows the file system to specify whether the check 
//                 (should the write be allowed to proceed ?) is being 
//                 performed for the first time - or has already been 
//                 performed before.
//
// Functionality Provided:
//
// This routine is part of a group of routines that allow the file system 
// to defer executing a write request until it is appropriate to do so. 
// As discussed above, the CcCanIWrite() routine allows a file system driver 
// to query the Cache Manager whether the current write request should be 
// allowed to proceed immediately. If the CcCanIWrite() routine returns FALSE, 
// the file system can utilize the CcDeferWrite() routine to queue up the 
// write until it is appropriate for the write to proceed.
//
// The PostRoutine argument allows the file system to specify the routine 
// that will perform the actual write operation when invoked. It is quite 
// possible that the Cache Manager might chose to invoke the post routine 
// immediately (in the context of the thread invoking the CcDeferWrite() 
// routine). Typically however, the post routine is invoked asynchronously 
// whenever sufficient number of dirty pages have been flushed to disk and 
// the Cache Manager and Virtual Memory Manager feel more comfortable with 
// allowing the particular write operation to proceed.
//
READ ALSO
Сжать .avi или .mp4 реально ли?

Сжать .avi или .mp4 реально ли?

возник вопрос: Возможно ли сжать видеофайлы или видеопоток? Пытался использовать lz4 для сжатия данных, сначала использовал этот метод сжатия...

100
Неожиданное потребление памяти

Неожиданное потребление памяти

Пишу алгоритм бинарной сортировки (в целях обучения)Компилятор - MinGW-w64 с флагом оптимизации -o0

114
удаление объекта в C++ [дубликат]

удаление объекта в C++ [дубликат]

На данный вопрос уже ответили:

111