SSDT HOOK实现文件保护

提到文件保护,无非就是文件隐藏、文件打开、读写、删除保护等。
 
一、文件隐藏
 
  文件隐藏可以通过HOOK NtQueryDirectoryFile函数来实现,这样可以使得受保护的文件无法在资源管理器之类的文件列表中显示出来。
 
  这种方法比较困难,一是难以稳定地获得目标文件的完整路径,二是难以稳定地将指定文件从返回的信息链表中删除。
 
  实际上,如果是需要实现文件保护,我们并不一定需要将文件进行隐藏,因为SSDT HOOK的隐藏效果并不十分理想,无法绕过调用文件系统驱动或磁盘驱动的程序,例如使用冰刃之类的ARK就可以一目了然地看到需要被隐藏的文件。
 
  综上所述,我们决定放弃对文件的隐藏,专注对文件进行保护。
 
二、文件打开保护
 
  对文件打开主要有两个函数,NtCreateFile和NtOpenFile,通过WRK或反汇编可以看到这两个函数都是直接调用了下层的IoCreateFile,而NtOpenFile并未调用NtCreateFile,因此为了实现文件打开保护,我们必须同时HOOK NtCreateFile、NtOpenFile这两个函数。
 
  需要注意的是,这两个函数中的FileHandle是传出参数,函数被调用后句柄中才有目标文件的路径信息,但这时候文件已经被打开了,我们已经失去了拦截的时机。
 
  实际上,在这两个函数中,我们可以不通过句柄获取文件路径信息,而是通过参数中的ObjectAttributes->RootDirectory和ObjectAttributes->ObjectName来获得。如果ObjectAttributes->RootDirectory不为空,则ObjectAttributes->ObjectName表示的是相对路径,否则为完整路径。
 
  在大多数情况下,ObjectAttributes->RootDirectory都是为空,即ObjectAttributes->ObjectName包含了请求文件的完整路径。
 
三、文件读写保护
 
  一般地,如果我们通过HOOK文件打开函数,应用程序将无法获得受保护文件的句柄,也就无法进行后续的文件读写、文件删除等操作。
 
  但实际情况并非如此,在系统的system进程中拥有所有的句柄信息,因此用户可以通过调用NtDuplicateObject之类的函数复制获得句柄,因此我们仍然需要HOOK文件读写函数。
 
  文件读写函数主要有两个,即NtReadFile和NtWriteFile。在这两个函数中我们可以通过FileHandle获得请求文件的路径信息,判断是否需要保护。
 
四、文件删除保护
 
  通过反汇编DeleteFileW可以看到,它们都是调用NtSetInformationFile删除文件的,当函数NtSetInformationFile的参数FileInformationClass值为FileDispositionInformation时,则它将对目标文件设置一个删除标记,这样等该文件的所有句柄被关闭后文件将会被删除。
 
  因此通过HOOK NtSetInformationFile便可以拦截大多数删除文件过程,但这并不是说NtDeleteFile就没有用处,我们在《The Undocumented Functions》一书中可以看到它对NtDeleteFile的解释如下:
 
  It's very interesting NT System Call... Normally, file deletion is realised as FileDispositionInformation class in a call to NtSetInformationFile. When you use NtDeleteFile, file will be deleted immediatly after call (system isn't waiting for close last HANDLE to file).
 
  从上述说明可以看出,如果我们直接调用NtDeleteFile,目标文件将会被立即删除而不会等到所有句柄都被关闭。通过这个说明我们可以知道,直接调用NtDeleteFile将会绕过对NtSetInformationFile的挂钩,因此我们需要同时HOOK NtDeleteFile。
 
  这里需要说明一点,有人可能会想要通过HOOK NtDuplicateObject而无需HOOK后面这些众多函数以达到目的,我没试过这种情况,假定它是可行的,但即使在这种情况下同样需要HOOK NtDeleteFile。
 
  这是因为NtDeleteFile仅有一个POBJECT_ATTRIBUTES参数,它并不像其它函数那样需要一个FileHandle参数,也就是说它不需要句柄,因此我们必须直接挂钩该函数,虽然ring3的API没有调用它,但并不能排除直接调用NtDeleteFile的可能性存在。
 
五、总结
 
  现在总结一下,为了实现文件保护,我们必须HOOK NtCreateFile、NtOpenFile、NtReadFile、NtWriteFile、NtSetInformationFile、NtDeleteFile这几个函数。考虑不周之处还望见谅!

 六、函数说明

NtCreateFile
NTSYSAPI 
NTSTATUS
NTAPI

NtCreateFile(

OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength );


(Avaiable also in 2000 DDK.)

  • FileHandle
  •     Result of call - HANDLE to File Object.
  • DesiredAccess
  •     Access mask based on definitions in schema FILE_* from <WinNT.h>.
  • ObjectAttributes
  •     Name of file to create (or open), optionally path in name string. You can also define root directory, security descriptor and attributesOBJ_CASE_INSENSITIVE and OBJ_INHERIT.
  • IoStatusBlock
  •     Pointer to IO_STATUS_BLOCK structure, that receive final status of function call. Can be one of:
    • FILE_CREATED
    • FILE_OPENED
    • FILE_OVERWRITTEN
    • FILE_SUPERSEDED
    • FILE_EXISTS
    • FILE_DOES_NOT_EXIST
  • AllocationSize
  •     File size after creation.
  • FileAttributes
  •     Attributes for newly created file, as follows:
    • FILE_ATTRIBUTE_READONLY
    • FILE_ATTRIBUTE_HIDDEN
    • FILE_ATTRIBUTE_SYSTEM
    • FILE_ATTRIBUTE_ARCHIVE
    • FILE_ATTRIBUTE_NORMAL
    • FILE_ATTRIBUTE_TEMPORARY
    • FILE_ATTRIBUTE_OFFLINE
    • FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
  • ShareAccess
  •     Specifies share method for opened object. Can be set to zero or any combination of flags:
    • FILE_SHARE_READ
    • FILE_SHARE_WRITE
    • FILE_SHARE_DELETE
  • CreateDisposition
  •     Specifies disposition how to create or open object and can be one of:
    • FILE_SUPERSEDE - If file exists, deletes it before creation of new one.
    • FILE_OPEN - Fails, if file not exists.
    • FILE_CREATE - Fails, if file exists.
    • FILE_OPEN_IF - If file exists, opens it. If not, creates new one and then open it.
    • FILE_OVERWRITE - If file not exists, create and open it. If exists, open them and reset content.
    • FILE_OVERWRITE_IF - As FILE_OVERWRITE, but fails if file not exists.
  • CreateOptions
  •     Creation options.
  • EaBuffer
  •     Buffer for Extended Attributes contains one or more of FILE_FULL_EA_INFORMATION structures.
  • EaLength
  •     Length of EaBuffer.

    Requirements:

             Library: ntdll.lib

     


     

    NtOpenFile

     

    NTSYSAPI 
    NTSTATUS
    NTAPI
    

    NtOpenFile(

    OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG ShareAccess, IN ULONG OpenOptions );

    (Also avaiable in 2000 DDK.)

  • FileHandle
  •     Result of call.
  • DesiredAccess
  •     Access mask to opened file object.
  • ObjectAttributes
  •     File name, path etc. See NtCreateFile for more information.
  • IoStatusBlock
  •     Completion status of call.
  • ShareAccess
  •     Sharing option defined as FILE_SHARE_*.
  • OpenOptions
  •     Open options.

    Requirements:

             Library: ntdll.lib

     

    NtDeleteFile

     

    NTSYSAPI 
    NTSTATUS
    NTAPI
    

    NtDeleteFile(

    IN POBJECT_ATTRIBUTES ObjectAttributes );

     

    It's very interesting NT System Call... Normally, file deletion is realised as FileDispositionInformation class in a call to NtSetInformationFile. When you use NtDeleteFile, file will be deleted immediatly after call (system isn't waiting for close last HANDLE to file).
    
      
      
    ObjectAttributes
    You can manipulate ObjectName and RootDirectory members. Example: If you have only file name as Unicode string, use it as ObjectName. If you have only a HANDLE to file, set it as RootDirectory. Set ObjectName as empty string.

     

    Requirements:

    Library: ntdll.lib
     

     NtSetInformationFile

    NTSYSAPI 
    NTSTATUS
    NTAPI
    

    NtSetInformationFile(

    IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass );



    (Description of this function is also avaiable in Win2000 DDK)

  • FileHandle
  •     HANDLE to File Object.
  • IoStatusBlock
  •     IO result of call.
  • FileInformation
  •     User's allocated buffer contains data to set to.
  • Length
  •     Length of FileInformation buffer, in bytes.
  • FileInformationClass
  •     See FILE_INFORMATION_CLASS for possible information classes and required contents ofFileInformation buffer.

    Requirements:

  • Library: ntdll.lib

     

    NtWriteFile
    NTSYSAPI 
    NTSTATUS
    NTAPI
    

    NtWriteFile(

    IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN PULONG Key OPTIONAL );




    (Also descripted in Win 2000 DDK)

  • FileHandle
  •     HANDLE to File Object opened with FILE_WRITE_DATA access.
  • Event
  •     HANDLE to Event Object signaled when write finished.
  • ApcRoutine
  •     User APC routine executed after writing is complete.
  • ApcContext
  •     Parameter to ApcRoutine.
  • IoStatusBlock
  •     IO result of call.
  • Buffer
  •     Buffer with data to write.
  • Length
  •     Length of Buffer, in bytes.
  • ByteOffset
  •     Offset from begining of file, where write starts.
  • Key
  •     - ??? (See NtReadFile).

    Requirements:

  • Library: ntdll.lib

     

    来源:

    http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/FILE_INFORMATION_CLASS.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vt hook ssdt是一种技术,用于在操作系统内核中拦截和修改系统服务调用。通过Vt(Virtualization Technology)技术,可以在操作系统运行时对系统服务进行动态修改,从而实现对系统行为的控制和修改。 以下是一个Vt hook ssdt的示例代码: ```c #include <ntddk.h> ULONG_PTR OriginalServiceAddress = 0; NTSTATUS HookServiceCall(IN PUNICODE_STRING ServiceName, IN ULONG_PTR NewServiceAddress) { NTSTATUS status = STATUS_SUCCESS; ULONG_PTR serviceAddress = 0; // 获取系统服务地址 status = ZwQuerySystemInformation(SystemModuleInformation, NULL, 0, &serviceAddress); if (status != STATUS_INFO_LENGTH_MISMATCH) { return status; } // 遍历系统服务表 PSYSTEM_MODULE_INFORMATION pModuleInfo = (PSYSTEM_MODULE_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, serviceAddress, 'hook'); if (pModuleInfo == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } status = ZwQuerySystemInformation(SystemModuleInformation, pModuleInfo, serviceAddress, NULL); if (!NT_SUCCESS(status)) { ExFreePoolWithTag(pModuleInfo, 'hook'); return status; } for (ULONG i = 0; i < pModuleInfo->NumberOfModules; i++) { PRTL_PROCESS_MODULES pModule = &pModuleInfo->Modules[i]; // 找到ntoskrnl.exe模块 if (wcsstr(pModule->FullPathName, L"ntoskrnl.exe") != NULL) { // 计算SSDT地址 ULONG_PTR ssdtAddress = (ULONG_PTR)pModule->ImageBase + pModule->OffsetToFileName; // 保存原始的系统服务地址 OriginalServiceAddress = *(ULONG_PTR*)ssdtAddress; // 修改系统服务地址为新的地址 *(ULONG_PTR*)ssdtAddress = NewServiceAddress; break; } } ExFreePoolWithTag(pModuleInfo, 'hook'); return status; } NTSTATUS UnhookServiceCall() { if (OriginalServiceAddress != 0) { // 恢复原始的系统服务地址 *(ULONG_PTR*)ssdtAddress = OriginalServiceAddress; OriginalServiceAddress = 0; } return STATUS_SUCCESS; } ``` 以上代码是一个简单的Vt hook ssdt的示例,通过调用`HookServiceCall`函数可以将指定的系统服务地址替换为新的地址,通过调用`UnhookServiceCall`函数可以恢复原始的系统服务地址。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值