Ring0内核层下实现删除文件或空目录

DemonGan

发布日期: 2019-01-26 18:53:59 浏览量: 645
评分:
star star star star star star star star star_border star_border
*转载请注明来自write-bug.com

背景

本文讲解的文件的基础操作就是指对文件进行增、删、改、查等基础的操作,这也是管理文件常用的操作。在应用层,我们都是直接使用 WIN32 API 来直接操作。到了内核层,虽然不能使用 WIN32 API,但是 Windows 也专门提供了相应的内核 API 给我们开发者使用,我们直接调用内核 API 就能实现我们的功能。

现在,我就单独将文件基础管理的常用操作一一解析,每个技术点都形成独立文档,来向大家讲解下怎么使用内核 API 在内核下创建文件或目录、删除文件或目录、 计算获取文件大小、文件的读和写操作实现文件复制、文件重命名、文件查询遍历等。

本文主要讲解的是,使用内核 API 删除文件或空目录的实现原理和过程。

函数介绍

InitializeObjectAttributes 函数

InitializeObjectAttributes宏初始化不透明OBJECT_ATTRIBUTES结构,该结构指定了打开句柄的例程的对象句柄的属性。

函数声明

  1. VOID InitializeObjectAttributes(
  2. [out] POBJECT_ATTRIBUTES InitializedAttributes,
  3. [in] PUNICODE_STRING ObjectName,
  4. [in] ULONG Attributes,
  5. [in] HANDLE RootDirectory,
  6. [in, optional] PSECURITY_DESCRIPTOR SecurityDescriptor
  7. );

参数

  • InitializedAttributes [out]
    指定要初始化的OBJECT_ATTRIBUTES结构。
  • ObjectName [in]
    指向Unicode字符串的指针,该字符串包含要打开句柄的对象的名称。这必须是完全限定的对象名称,或者是由RootDirectory参数指定的对象目录的相对路径名。
  • Attributes[in]
    指定一个或多个以下标志:
    OBJ_INHERIT
    该句柄可以由当前进程的子进程继承。
    OBJ_PERMANENT
    此标志仅适用于在对象管理器中命名的对象。默认情况下,当所有打开的句柄关闭时,这些对象将被删除。如果指定了此标志,则当所有打开的手柄都关闭时,该对象不会被删除。驱动程序可以使用ZwMakeTemporaryObject删除永久对象。
    OBJ_EXCLUSIVE
    此对象只能打开单个句柄。
    OBJ_CASE_INSENSITIVE
    如果指定了此标志,则在将ObjectName参数与现有对象的名称匹配时使用不区分大小写的比较。否则,使用默认系统设置比较对象名称。
    OBJ_OPENIF
    如果将此标志指定给创建对象的例程,并且该对象已经存在,则例程应该打开该对象。否则,创建对象的例程将返回STATUS_OBJECT_NAME_COLLISION的NTSTATUS代码。
    OBJ_KERNEL_HANDLE
    指定句柄只能在内核模式下访问。
    OBJ_FORCE_ACCESS_CHECK
    打开句柄的例程应强制执行对象的所有访问检查,即使在内核模式下打开句柄。
  • RootDirectory [in]
    在ObjectName参数中指定的路径名的根对象目录的句柄。如果ObjectName是一个完全限定的对象名称,则RootDirectory为NULL。使用ZwCreateDirectoryObject获取对象目录的句柄。
  • SecurityDescriptor [in]
    指定在对象创建时应用于安全描述符。此参数是可选的。驱动程序可以指定NULL来接受对象的默认安全性。

返回值

  • 无返回值。

ZwDeleteFile 函数

删除指定文件。

函数声明

  1. NTSTATUS ZwDeleteFile(
  2. _In_ POBJECT_ATTRIBUTES ObjectAttributes
  3. );

参数

  • ObjectAttributes [in]
    指向OBJECT_ATTRIBUTES结构的指针,其中包含调用者为文件对象提供的属性。 这些属性将包括ObjectName和SECURITY_DESCRIPTOR。 该参数通过调用InitializeObjectAttributes宏来初始化。

返回值

  • 成功时,返回STATUS_SUCCESS;失败时,返回适当的NTSTATUS错误代码。

实现原理

对于文件的删除,在应用层上我们使用 DeleteFile 来实现,删除空目录则使用 RemoveDirectory。而对于内核层来说,我们直接可以使用 ZwDeleteFile 函数来删除指定文件以及空目录。现在,我们给出具体实现步骤:

首先,我们调用 InitializeObjectAttributes 宏来初始化对象属性,包括文件或者目录路径和其它属性。

然后,再调用 ZwDeleteFile 函数,根据传入的对象属性参数删除指定对象。如果对象是个文件,则删除文件;若对象是一个空目录,则删除目录。注意,若对象是一个非空目录,则返回不操作。

特别注意一点,内核下表示的文件或者目录路径要在路径前面加上 \??\,例如表示 C 盘下的 test.txt 文件路径:\??\C:\test.txt。

编码实现

删除文件或空目录

  1. // 删除文件或是空目录 \??\C:\MyCreateFolder\520\520.exe
  2. BOOLEAN MyDeleteFileOrFileFolder(UNICODE_STRING ustrFileName)
  3. {
  4. NTSTATUS status = STATUS_SUCCESS;
  5. OBJECT_ATTRIBUTES objectAttributes = { 0 };
  6. InitializeObjectAttributes(&objectAttributes, &ustrFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
  7. // 执行删除操作
  8. status = ZwDeleteFile(&objectAttributes);
  9. if (!NT_SUCCESS(status))
  10. {
  11. ShowError("ZwDeleteFile", status);
  12. return FALSE;
  13. }
  14. return TRUE;
  15. }

程序测试

在 Win7 32 位系统下,驱动程序正常执行;在 Win10 64 位系统下,驱动程序正常执行。

总结

ZwDeleteFile 内核函数和应用层的 DeleteFile 函数类似的,都是删除指定文件。不同的是,ZwDeleteFile 还可以删除目录,若对象是一个空目录,则删除目录。注意,若对象是一个非空目录,则返回不操作。

特别注意一点,内核下表示的文件或者目录路径要在路径前面加上 \??\,例如表示 C 盘下的 test.txt 文件路径:\??\C:\test.txt。

参考

参考自《Windows黑客编程技术详解》一书

上传的附件 cloud_download FileManager_Test.7z ( 13.63kb, 3次下载 )

发送私信

这一切都不是我的,但总有一天,会是我的

73
文章数
67
评论数
最近文章
eject