8.2 Windows驱动开发:内核解锁与强删文件

news2024/11/16 11:49:45

在某些时候我们的系统中会出现一些无法被正常删除的文件,如果想要强制删除则需要在驱动层面对其进行解锁后才可删掉,而所谓的解锁其实就是释放掉文件描述符(句柄表)占用,文件解锁的核心原理是通过调用ObSetHandleAttributes函数将特定句柄设置为可关闭状态,然后在调用ZwClose将其文件关闭,强制删除则是通过ObReferenceObjectByHandle在对象上提供相应的权限后直接调用ZwDeleteFile将其删除。

在内核中实现解锁和强制删除文件是一种常见的技术,通常用于删除被其他进程占用的文件。下面是一些实现方式:

  • 使用 ZwOpenFile 函数打开文件,并指定 FILE_SHARE_DELETE 标志,这将允许其他进程在文件打开期间进行删除操作。然后,调用 ZwSetInformationFile 函数,将文件句柄作为参数传递给它,并指定 FILE_DISPOSITION_INFORMATION 类型,以删除文件。

  • 使用 NtQuerySystemInformation 函数获取系统进程信息,并枚举每个进程以查找拥有要删除文件的句柄的进程。然后,使用 ZwQuerySystemInformation 函数获取有关进程打开句柄的信息,并枚举每个句柄以查找要删除的文件句柄。一旦找到了该句柄,就可以使用 ZwClose 函数关闭该句柄,并调用 ZwSetInformationFile 函数删除文件。

需要注意的是,强制删除文件可能会引起系统稳定性问题和数据丢失,因此应该谨慎使用,并避免误删重要文件。此外,一些安全软件和操作系统可能会检测到这些操作,并采取防御措施。因此,在实现这些技术时,需要遵循操作系统和安全软件的规定,以确保系统的安全和稳定。

虽此类代码较为普遍,但作为揭秘ARK工具来说也必须要将其分析并讲解一下。

首先封装lyshark.h通用头文件,并定义好我们所需要的结构体,以及特定未导出函数的声明,此处的定义部分是微软官方的规范,如果不懂结构具体含义可自行去微软官方查阅参考资料。

#include <ntddk.h>

// -------------------------------------------------------
// 引用微软结构
// -------------------------------------------------------
// 结构体定义
typedef struct _HANDLE_INFO
{
    UCHAR ObjectTypeIndex;
    UCHAR HandleAttributes;
    USHORT  HandleValue;
    ULONG GrantedAccess;
    ULONG64 Object;
    UCHAR Name[256];
} HANDLE_INFO, *PHANDLE_INFO;

HANDLE_INFO HandleInfo[1024];

typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
    USHORT  UniqueProcessId;
    USHORT  CreatorBackTraceIndex;
    UCHAR ObjectTypeIndex;
    UCHAR HandleAttributes;
    USHORT  HandleValue;
    PVOID Object;
    ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;

typedef struct _SYSTEM_HANDLE_INFORMATION
{
    ULONG64 NumberOfHandles;
    SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;

typedef enum _OBJECT_INFORMATION_CLASS
{
    ObjectBasicInformation,
    ObjectNameInformation,
    ObjectTypeInformation,
    ObjectAllInformation,
    ObjectDataInformation
} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;

typedef struct _OBJECT_BASIC_INFORMATION
{
    ULONG                   Attributes;
    ACCESS_MASK             DesiredAccess;
    ULONG                   HandleCount;
    ULONG                   ReferenceCount;
    ULONG                   PagedPoolUsage;
    ULONG                   NonPagedPoolUsage;
    ULONG                   Reserved[3];
    ULONG                   NameInformationLength;
    ULONG                   TypeInformationLength;
    ULONG                   SecurityDescriptorLength;
    LARGE_INTEGER           CreationTime;
} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION;

typedef struct _OBJECT_TYPE_INFORMATION
{
    UNICODE_STRING          TypeName;
    ULONG                   TotalNumberOfHandles;
    ULONG                   TotalNumberOfObjects;
    WCHAR                   Unused1[8];
    ULONG                   HighWaterNumberOfHandles;
    ULONG                   HighWaterNumberOfObjects;
    WCHAR                   Unused2[8];
    ACCESS_MASK             InvalidAttributes;
    GENERIC_MAPPING         GenericMapping;
    ACCESS_MASK             ValidAttributes;
    BOOLEAN                 SecurityRequired;
    BOOLEAN                 MaintainHandleCount;
    USHORT                  MaintainTypeList;
    POOL_TYPE               PoolType;
    ULONG                   DefaultPagedPoolCharge;
    ULONG                   DefaultNonPagedPoolCharge;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;

typedef struct _KAPC_STATE
{
    LIST_ENTRY ApcListHead[2];
    PVOID Process;
    BOOLEAN KernelApcInProgress;
    BOOLEAN KernelApcPending;
    BOOLEAN UserApcPending;
}KAPC_STATE, *PKAPC_STATE;

typedef struct _OBJECT_HANDLE_FLAG_INFORMATION
{
    BOOLEAN Inherit;
    BOOLEAN ProtectFromClose;
}OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION;

typedef struct _LDR_DATA_TABLE_ENTRY64
{
  LIST_ENTRY64 InLoadOrderLinks;
  LIST_ENTRY64 InMemoryOrderLinks;
  LIST_ENTRY64 InInitializationOrderLinks;
  ULONG64 DllBase;
  ULONG64 EntryPoint;
  ULONG64 SizeOfImage;
  UNICODE_STRING FullDllName;
  UNICODE_STRING BaseDllName;
  ULONG Flags;
  USHORT LoadCount;
  USHORT TlsIndex;
  LIST_ENTRY64 HashLinks;
  ULONG64 SectionPointer;
  ULONG64 CheckSum;
  ULONG64 TimeDateStamp;
  ULONG64 LoadedImports;
  ULONG64 EntryPointActivationContext;
  ULONG64 PatchInformation;
  LIST_ENTRY64 ForwarderLinks;
  LIST_ENTRY64 ServiceTagLinks;
  LIST_ENTRY64 StaticLinks;
  ULONG64 ContextInformation;
  ULONG64 OriginalBase;
  LARGE_INTEGER LoadTime;
} LDR_DATA_TABLE_ENTRY64, *PLDR_DATA_TABLE_ENTRY64;

// -------------------------------------------------------
// 导出函数定义
// -------------------------------------------------------

NTKERNELAPI NTSTATUS ObSetHandleAttributes
(
    HANDLE Handle,
    POBJECT_HANDLE_FLAG_INFORMATION HandleFlags,
    KPROCESSOR_MODE PreviousMode
);

NTKERNELAPI VOID KeStackAttachProcess
(
    PEPROCESS PROCESS,
    PKAPC_STATE ApcState
);

NTKERNELAPI VOID KeUnstackDetachProcess
(
    PKAPC_STATE ApcState
);

NTKERNELAPI NTSTATUS PsLookupProcessByProcessId
(
    IN HANDLE ProcessId,
    OUT PEPROCESS *Process
);

NTSYSAPI NTSTATUS NTAPI ZwQueryObject
(
    HANDLE  Handle,
    ULONG ObjectInformationClass,
    PVOID ObjectInformation,
    ULONG ObjectInformationLength,
    PULONG  ReturnLength OPTIONAL
);

NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation
(
    ULONG SystemInformationClass,
    PVOID SystemInformation,
    ULONG SystemInformationLength,
    PULONG  ReturnLength
);

NTSYSAPI NTSTATUS NTAPI ZwDuplicateObject
(
    HANDLE    SourceProcessHandle,
    HANDLE    SourceHandle,
    HANDLE    TargetProcessHandle OPTIONAL,
    PHANDLE   TargetHandle OPTIONAL,
    ACCESS_MASK DesiredAccess,
    ULONG   HandleAttributes,
    ULONG   Options
);

NTSYSAPI NTSTATUS NTAPI ZwOpenProcess
(
    PHANDLE       ProcessHandle,
    ACCESS_MASK     AccessMask,
    POBJECT_ATTRIBUTES  ObjectAttributes,
    PCLIENT_ID      ClientId
);

#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004

接下来将具体分析如何解锁指定文件的句柄表,强制解锁文件句柄表,大体步骤如下所示。

  • 1.首先调用ZwQuerySystemInformation的16功能号SystemHandleInformation来枚举系统里的句柄。
  • 2.通过ZwOpenProcess()打开拥有此句柄的进程,通过ZwDuplicateObject创建一个新的句柄,并把此句柄复制到自己的进程内。
  • 3.通过调用ZwQueryObject并传入ObjectNameInformation查询到句柄的名称,并将其放入到pNameInfo变量内。
  • 4.循环这个过程并在每次循环中通过strstr()判断是否是我们需要关闭的文件名,如果是则调用ForceCloseHandle强制解除占用。
  • 5.此时会进入到ForceCloseHandle流程内,通过KeStackAttachProcess附加到进程内,并调用ObSetHandleAttributes将句柄设置为可关闭状态。
  • 6.最后调用ZwClose关闭句柄占用,并KeUnstackDetachProcess脱离该进程。

实现代码流程非常容易理解,此类功能也没有其他别的写法了一般也就这种,但是还是需要注意这些内置函数的参数传递,这其中ZwQuerySystemInformation()一般用于查询系统进程等信息居多,但通过对SystemInformationClass变量传入不同的参数可实现对不同结构的枚举工作,具体的定义可去查阅微软定义规范;

NTSTATUS WINAPI ZwQuerySystemInformation(
  _In_      SYSTEM_INFORMATION_CLASS SystemInformationClass,      // 传入不同参数则输出不同内容
  _Inout_   PVOID                    SystemInformation,           // 输出数据
  _In_      ULONG                    SystemInformationLength,     // 长度
  _Out_opt_ PULONG                   ReturnLength                 // 返回长度
);

函数ZwDuplicateObject(),该函数例程用于创建一个句柄,该句柄是指定源句柄的副本,此函数的具体声明部分如下;

NTSYSAPI NTSTATUS ZwDuplicateObject(
  [in]            HANDLE      SourceProcessHandle,    // 要复制的句柄的源进程的句柄。
  [in]            HANDLE      SourceHandle,           // 要复制的句柄。
  [in, optional]  HANDLE      TargetProcessHandle,    // 要接收新句柄的目标进程的句柄。
  [out, optional] PHANDLE     TargetHandle,           // 指向例程写入新重复句柄的 HANDLE 变量的指针。
  [in]            ACCESS_MASK DesiredAccess,          // 一个ACCESS_MASK值,该值指定新句柄的所需访问。
  [in]            ULONG       HandleAttributes,       // 一个 ULONG,指定新句柄的所需属性。 
  [in]            ULONG       Options                 // 一组标志,用于控制重复操作的行为。
);

函数ZwQueryObject()其可以返回特定的一个对象参数,此函数尤为注意第二个参数,当下我们传入的是ObjectNameInformation则代表需要取出对象名称,而如果使用ObjectTypeInformation则是返回对象类型,该函数微软定义如下所示;

NTSYSAPI NTSTATUS ZwQueryObject(
  [in, optional]  HANDLE                   Handle,                        // 要获取相关信息的对象句柄。
  [in]            OBJECT_INFORMATION_CLASS ObjectInformationClass,        // 该值确定 ObjectInformation 缓冲区中返回的信息的类型。
  [out, optional] PVOID                    ObjectInformation,             // 指向接收请求信息的调用方分配缓冲区的指针。
  [in]            ULONG                    ObjectInformationLength,       // 指定 ObjectInformation 缓冲区的大小(以字节为单位)。
  [out, optional] PULONG                   ReturnLength                   // 指向接收所请求密钥信息的大小(以字节为单位)的变量的指针。 
);

而对于ForceCloseHandle函数中,需要注意的只有一个ObSetHandleAttributes该函数微软并没有格式化文档,但是也并不影响我们使用它,如下最需要注意的是PreviousMode变量,该变量如果传入KernelMode则是内核模式,传入UserMode则代表用户模式,为了权限最大化此处需要写入KernelMode模式;

NTSYSAPI NTSTATUS ObSetHandleAttributes(
  HANDLE Handle,                                        // 传入文件句柄
  POBJECT_HANDLE_FLAG_INFORMATION HandleFlags,          // OBJECT_HANDLE_FLAG_INFORMATION标志
  KPROCESSOR_MODE PreviousMode                          // 指定运行级别KernelMode
)

实现文件解锁,该驱动程序不仅可用于解锁应用层程序,也可用于解锁驱动,如下代码中我们解锁pagefile.sys程序的句柄占用;

#include "lyshark.h"

// 根据PID得到EProcess
PEPROCESS LookupProcess(HANDLE Pid)
{
    PEPROCESS eprocess = NULL;
    if (NT_SUCCESS(PsLookupProcessByProcessId(Pid, &eprocess)))
        return eprocess;
    else
        return NULL;
}

// 将uncode转为char*
VOID UnicodeStringToCharArray(PUNICODE_STRING dst, char *src)
{
    ANSI_STRING string;
    if (dst->Length > 260)
    {
        return;
    }

    RtlUnicodeStringToAnsiString(&string, dst, TRUE);
    strcpy(src, string.Buffer);
    RtlFreeAnsiString(&string);
}

// 强制关闭句柄
VOID ForceCloseHandle(PEPROCESS Process, ULONG64 HandleValue)
{
    HANDLE h;
    KAPC_STATE ks;
    OBJECT_HANDLE_FLAG_INFORMATION ohfi;

    if (Process == NULL)
    {
        return;
    }
    // 验证进程是否可读写
    if (!MmIsAddressValid(Process))
    {
        return;
    }

    // 附加到进程
    KeStackAttachProcess(Process, &ks);
    h = (HANDLE)HandleValue;
    ohfi.Inherit = 0;
    ohfi.ProtectFromClose = 0;

    // 设置句柄为可关闭状态
    ObSetHandleAttributes(h, &ohfi, KernelMode);

    // 关闭句柄
    ZwClose(h);

    // 脱离附加进程
    KeUnstackDetachProcess(&ks);

    DbgPrint("EP = [ %d ] | HandleValue = [ %d ] 进程句柄已被关闭 \n",Process,HandleValue);
}

VOID UnDriver(PDRIVER_OBJECT driver)
{
    DbgPrint("驱动卸载成功 \n");
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
    DbgPrint("Hello lyshark \n");

    PVOID Buffer;
    ULONG BufferSize = 0x20000, rtl = 0;
    NTSTATUS Status, qost = 0;
    NTSTATUS ns = STATUS_SUCCESS;
    ULONG64 i = 0;
    ULONG64 qwHandleCount;

    SYSTEM_HANDLE_TABLE_ENTRY_INFO *p;
    OBJECT_BASIC_INFORMATION BasicInfo;
    POBJECT_NAME_INFORMATION pNameInfo;

    ULONG ulProcessID;
    HANDLE hProcess;
    HANDLE hHandle;
    HANDLE hDupObj;
    CLIENT_ID cid;
    OBJECT_ATTRIBUTES oa;
    CHAR szFile[260] = { 0 };

    Buffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize, "LyShark");
    memset(Buffer, 0, BufferSize);

    // SystemHandleInformation
    Status = ZwQuerySystemInformation(16, Buffer, BufferSize, 0);
    while (Status == STATUS_INFO_LENGTH_MISMATCH)
    {
        ExFreePool(Buffer);
        BufferSize = BufferSize * 2;
        Buffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize, "LyShark");
        memset(Buffer, 0, BufferSize);
        Status = ZwQuerySystemInformation(16, Buffer, BufferSize, 0);
    }

    if (!NT_SUCCESS(Status))
    {
        return;
    }

    // 获取系统中所有句柄表
    qwHandleCount = ((SYSTEM_HANDLE_INFORMATION *)Buffer)->NumberOfHandles;

    // 得到句柄表的SYSTEM_HANDLE_TABLE_ENTRY_INFO结构
    p = (SYSTEM_HANDLE_TABLE_ENTRY_INFO *)((SYSTEM_HANDLE_INFORMATION *)Buffer)->Handles;

    // 初始化HandleInfo数组
    memset(HandleInfo, 0, 1024 * sizeof(HANDLE_INFO));

    // 开始枚举句柄
    for (i = 0; i<qwHandleCount; i++)
    {
        ulProcessID = (ULONG)p[i].UniqueProcessId;
        cid.UniqueProcess = (HANDLE)ulProcessID;
        cid.UniqueThread = (HANDLE)0;
        hHandle = (HANDLE)p[i].HandleValue;

        // 初始化对象结构
        InitializeObjectAttributes(&oa, NULL, 0, NULL, NULL);

        // 通过句柄信息打开占用进程
        ns = ZwOpenProcess(&hProcess, PROCESS_DUP_HANDLE, &oa, &cid);

        // 打开错误
        if (!NT_SUCCESS(ns))
        {
            continue;
        }

        // 创建一个句柄,该句柄是指定源句柄的副本。
        ns = ZwDuplicateObject(hProcess, hHandle, NtCurrentProcess(), &hDupObj, PROCESS_ALL_ACCESS, 0, DUPLICATE_SAME_ACCESS);
        if (!NT_SUCCESS(ns))
        {
            continue;
        }

        // 查询对象句柄的信息并放入BasicInfo
        ZwQueryObject(hDupObj, ObjectBasicInformation, &BasicInfo, sizeof(OBJECT_BASIC_INFORMATION), NULL);

        // 得到对象句柄的名字信息
        pNameInfo = ExAllocatePool(PagedPool, 1024);
        RtlZeroMemory(pNameInfo, 1024);

        // 查询对象信息中的对象名,并将该信息保存到pNameInfo中
        qost = ZwQueryObject(hDupObj, ObjectNameInformation, pNameInfo, 1024, &rtl);

        // 获取信息并关闭句柄
        UnicodeStringToCharArray(&(pNameInfo->Name), szFile);
        ExFreePool(pNameInfo);
        ZwClose(hDupObj);
        ZwClose(hProcess);

        // 检查句柄是否被占用,如果被占用则关闭文件并删除
        if (strstr(_strlwr(szFile), "pagefile.sys"))
        {
            PEPROCESS ep = LookupProcess((HANDLE)(p[i].UniqueProcessId));

            // 占用则强制关闭
            ForceCloseHandle(ep, p[i].HandleValue);
            ObDereferenceObject(ep);
        }
    }

    Driver->DriverUnload = UnDriver;
    return STATUS_SUCCESS;
}

编译并运行这段驱动程序,则会将pagefile.sys内核文件进行解锁,输出效果如下所示;

聊完了文件解锁功能,接下来将继续探讨如何实现强制删除文件的功能,文件强制删除的关键在于ObReferenceObjectByHandle函数,该函数可在对象句柄上提供访问验证,并授予访问权限返回指向对象的正文的相应指针,当有了指定的权限以后则可以直接调用ZwDeleteFile()将文件强制删除。

在调用初始化句柄前提之下需要先调用KeGetCurrentIrql()函数,该函数返回当前IRQL级别,那么什么是IRQL呢?

Windows中系统中断请求(IRQ)可分为两种,一种外部中断(硬件中断),一种是软件中断(INT3),微软将中断的概念进行了扩展,提出了中断请求级别(IRQL)的概念,其中就规定了32个中断请求级别。

  • 其中0-2级为软中断,顺序由小到大分别是:PASSIVE_LEVEL,APC_LEVEL,DISPATCH_LEVEL
  • 其中27-31为硬中断,顺序由小到大分别是:PROFILE_LEVEL,CLOCK1_LEVEL,CLOCK2_LEVEL,IPI_LEVEL,POWER_LEVEL,HIGH_LEVEL

我们的代码中开头部分KeGetCurrentIrql() > PASSIVE_LEVEL则是在判断当前的级别不大于0级,也就是说必须要大于0才可以继续执行。

好开始步入正题,函数ObReferenceObjectByHandle需要传入一个文件句柄,而此句柄需要通过IoCreateFileSpecifyDeviceObjectHint对其进行初始化,文件系统筛选器驱动程序使用IoCreateFileSpecifyDeviceObjectHint函数创建,该函数的微软完整定义如下所示;

NTSTATUS IoCreateFileSpecifyDeviceObjectHint(
  [out]          PHANDLE            FileHandle,               // 指向变量的指针,该变量接收文件对象的句柄。
  [in]           ACCESS_MASK        DesiredAccess,            // 标志的位掩码,指定调用方需要对文件或目录的访问类型。
  [in]           POBJECT_ATTRIBUTES ObjectAttributes,         // 指向已由 InitializeObjectAttributes 例程初始化的OBJECT_ATTRIBUTES结构的指针。
  [out]          PIO_STATUS_BLOCK   IoStatusBlock,            // 指向 IO_STATUS_BLOCK 结构的指针,该结构接收最终完成状态和有关所请求操作的信息。
  [in, optional] PLARGE_INTEGER     AllocationSize,           // 指定文件的初始分配大小(以字节为单位)。
  [in]           ULONG              FileAttributes,           // 仅当文件创建、取代或在某些情况下被覆盖时,才会应用显式指定的属性。
  [in]           ULONG              ShareAccess,              // 指定调用方希望的对文件的共享访问类型(为零或 1,或以下标志的组合)。
  [in]           ULONG              Disposition,              // 指定一个值,该值确定要执行的操作,具体取决于文件是否已存在。
  [in]           ULONG              CreateOptions,            // 指定要在创建或打开文件时应用的选项。
  [in, optional] PVOID              EaBuffer,                 // 指向调用方提供的 FILE_FULL_EA_INFORMATION结构化缓冲区的指针。
  [in]           ULONG              EaLength,                 // EaBuffer 的长度(以字节为单位)。
  [in]           CREATE_FILE_TYPE   CreateFileType,           // 驱动程序必须将此参数设置为 CreateFileTypeNone。
  [in, optional] PVOID              InternalParameters,       // 驱动程序必须将此参数设置为 NULL。
  [in]           ULONG              Options,                  // 指定要在创建请求期间使用的选项。
  [in, optional] PVOID              DeviceObject              // 指向要向其发送创建请求的设备对象的指针。
);

当调用IoCreateFileSpecifyDeviceObjectHint()函数完成初始化并创建设备后,则下一步就是调用ObReferenceObjectByHandle()并传入初始化好的设备句柄到Handle参数上,

NTSTATUS ObReferenceObjectByHandle(
  [in]            HANDLE                     Handle,             // 指定对象的打开句柄。
  [in]            ACCESS_MASK                DesiredAccess,      // 指定对对象的请求访问类型。
  [in, optional]  POBJECT_TYPE               ObjectType,         // 指向对象类型的指针。
  [in]            KPROCESSOR_MODE            AccessMode,         // 指定要用于访问检查的访问模式。 它必须是 UserMode 或 KernelMode。
  [out]           PVOID                      *Object,            // 指向接收指向对象正文的指针的变量的指针。
  [out, optional] POBJECT_HANDLE_INFORMATION HandleInformation   // 驱动程序将此设置为 NULL。
);

通过调用如上两个函数将权限设置好以后,我们再手动将ImageSectionObject也就是映像节对象填充为0,然后再将DeleteAccess删除权限位打开,最后调用ZwDeleteFile()函数即可实现强制删除文件的效果,其核心代码如下所示;

#include "lyshark.h"

// 强制删除文件
BOOLEAN ForceDeleteFile(UNICODE_STRING pwzFileName)
{
    PEPROCESS pCurEprocess = NULL;
    KAPC_STATE kapc = { 0 };
    OBJECT_ATTRIBUTES fileOb;
    HANDLE hFile = NULL;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    IO_STATUS_BLOCK iosta;
    PDEVICE_OBJECT DeviceObject = NULL;
    PVOID pHandleFileObject = NULL;


    // 判断中断等级不大于0
    if (KeGetCurrentIrql() > PASSIVE_LEVEL)
    {
        return FALSE;
    }
    if (pwzFileName.Buffer == NULL || pwzFileName.Length <= 0)
    {
        return FALSE;
    }

    __try
    {
        // 读取当前进程的EProcess
        pCurEprocess = IoGetCurrentProcess();

        // 附加进程
        KeStackAttachProcess(pCurEprocess, &kapc);

        // 初始化结构
        InitializeObjectAttributes(&fileOb, &pwzFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

        // 文件系统筛选器驱动程序 仅向指定设备对象下面的筛选器和文件系统发送创建请求。
        status = IoCreateFileSpecifyDeviceObjectHint(&hFile,
            SYNCHRONIZE | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_READ_DATA,
            &fileOb,
            &iosta,
            NULL,
            0,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            FILE_OPEN,
            FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
            0,
            0,
            CreateFileTypeNone,
            0,
            IO_IGNORE_SHARE_ACCESS_CHECK,
            DeviceObject);
        if (!NT_SUCCESS(status))
        {
            return FALSE;
        }

        // 在对象句柄上提供访问验证,如果可以授予访问权限,则返回指向对象的正文的相应指针。
        status = ObReferenceObjectByHandle(hFile, 0, 0, 0, &pHandleFileObject, 0);
        if (!NT_SUCCESS(status))
        {
            return FALSE;
        }

        // 镜像节对象设置为0
        ((PFILE_OBJECT)(pHandleFileObject))->SectionObjectPointer->ImageSectionObject = 0;

        // 删除权限打开
        ((PFILE_OBJECT)(pHandleFileObject))->DeleteAccess = 1;

        // 调用删除文件API
        status = ZwDeleteFile(&fileOb);
        if (!NT_SUCCESS(status))
        {
            return FALSE;
        }
    }

    _finally
    {
        if (pHandleFileObject != NULL)
        {
            ObDereferenceObject(pHandleFileObject);
            pHandleFileObject = NULL;
        }
        KeUnstackDetachProcess(&kapc);

        if (hFile != NULL || hFile != (PVOID)-1)
        {
            ZwClose(hFile);
            hFile = (PVOID)-1;
        }
    }
    return TRUE;
}

VOID UnDriver(PDRIVER_OBJECT driver)
{
    DbgPrint("驱动卸载成功 \n");
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
    DbgPrint("Hello lyshark \n");

    UNICODE_STRING local_path;
    UNICODE_STRING file_path;
    BOOLEAN ref = FALSE;
    
    // 初始化被删除文件
    RtlInitUnicodeString(&file_path, L"\\??\\C:\\lyshark.exe");

    // 获取自身驱动文件
    local_path = ((PLDR_DATA_TABLE_ENTRY64)Driver->DriverSection)->FullDllName;

    // 删除lyshark.exe
    ref = ForceDeleteFile(file_path);
    if (ref == TRUE)
    {
        DbgPrint("[+] 已删除 %wZ \n",file_path);
    }

    // 删除WinDDK.sys
    ref = ForceDeleteFile(local_path);
    if (ref == TRUE)
    {
        DbgPrint("[+] 已删除 %wZ \n", local_path);
    }

    Driver->DriverUnload = UnDriver;
    return STATUS_SUCCESS;
}

编译并运行如上程序,则会分别将c://lyshark.exe以及驱动程序自身删除,并输出如下图所示的提示信息;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1234421.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【前端】vue中合并表格行

做平台功能时&#xff0c;遇到一个需求是需要将表格某列有相同值时进行合并展示&#xff0c;比如 1、通过在Element中得知需要在表格中增加span-method方法 <el-table:data"tableData":span-method"cellMerge"borderstyle"width: 100%; margin-to…

LeetCode算法心得——打家劫舍(记忆化搜索)

大家好&#xff0c;我是晴天学长&#xff0c;准备开始深入动态规划啦&#xff0c;先从记忆化搜索开始&#xff0c;需要的小伙伴可以关注支持一下哦&#xff01;后续会继续更新的。&#x1f4aa;&#x1f4aa;&#x1f4aa; 1) .打家劫舍 你是一个专业的小偷&#xff0c;计划偷窃…

如何选择适合的开源框架来构建微服务架构?

随着科技的飞速发展&#xff0c;云计算和大规模应用的需求日益显著&#xff0c;这促使微服务架构在软件开发领域中占据了主流地位。微服务架构的广泛应用为开发人员提供了灵活性、可伸缩性和高可用性&#xff0c;从而推动了快速的应用程序开发。然而&#xff0c;在构建微服务架…

React函数组件渲染两次

渲染两次是因为react默认开启了严格模式 React.StrictMode标签作用&#xff1a; 1、识别不安全的生命周期 2、关于使用过时字符串 ref API 的警告 3、关于使用废弃的 findDOMNode 方法的警告 4、检测意外的副作用 5、检测过时的 context API 注释掉React.StrictMode即为关闭严…

2024测试工程师必学系列之Jmeter(36):jmeter对图片验证码的处理

jmeter对图片验证码的处理 在web端的登录接口经常会有图片验证码的输入&#xff0c;而且每次登录时图片验证码都是随机的&#xff1b;当通过jmeter做接口登录的时候要对图片验证码进行识别出图片中的字段&#xff0c;然后再登录接口中使用&#xff1b; 通过jmeter对图片验证码…

【蓝桥杯省赛真题44】Scratch像素画板 蓝桥杯少儿编程scratch图形化编程 蓝桥杯省赛真题讲解

scratch像素画板 第十四届青少年蓝桥杯scratch编程省赛真题 一、题目要求 编程实现 1.点击绿旗,角色、背景如图所示(三种颜色调色盘、清除图标及方格角色请自行创建,点击绿旗后立刻呈现下图效果); 2.用鼠标点击红色调色盘,红色调色盘变为选中状态(如下图所示),此时鼠…

实战 | SQL注入漏洞

在页面参数增加 and -1-1&#xff0c;页面回显正常 这里如果 and 11 会被拦截 然后尝试-1-2 页面报错&#xff0c;此处存在数字型sql注入漏洞 接下来就是查字段数 order by 1 页面依旧报错 如果大家在渗透的时候遇到这种情况 要考虑是不是某些参数被拦截等 换一种思路&#xf…

SQL常见函数整理 —— lead()向下偏移

1. 用法 是在窗口函数中使用的函数&#xff0c;它用于获取当前行的下一行&#xff08;后一行&#xff09;的某个列的值。具体来说&#xff0c;LEAD() 函数可用于查找任何给定行的下一行&#xff08;后一行&#xff09;的值&#xff0c;同时也可控制行数偏移量&#xff08;offse…

ChainLight zkSync Era漏洞揭秘

1. 引言 ChainLight研究人员于2023年9月15日&#xff0c;发现了zkSync Era主网的ZK电路的一个soundness bug&#xff0c;并于2023年9月17日&#xff0c;向Matter Labs团队报告了该问题。Matter Labs团队修复了该问题&#xff0c;并奖励了ChainLight团队5万USDC——为首个zkSync…

用Auth Analyzer插件批量测试接口越权,安全测试快人一步!

随着信息化技术的不断发展&#xff0c;软件安全成了软件行业的重大挑战&#xff0c;因此安全测试也成为了测试人员必备的技能之一。 沐沐在安全测试过程中较为常见的就是接口越权漏洞&#xff0c;在尝试过多种工具进行越权漏洞测试后&#xff0c;最终找到了个人认为最便捷最有…

ModBus TCP/RTU 报文解析

Modbus Tcp https://gitee.com/szwzhsz/Modbus-TCP-client-server-DotNetty.?_fromgitee_search 固定协议格式 事务标识(2byte)&#xff1a;00 00&#xff0c;可变(递增) 协议标识(2byte)&#xff1a;00 00&#xff0c;固定 长度(2byte)&#xff1a;00 06&#xff0c;可变 单…

【GUI】-- 10 贪吃蛇小游戏之静态面板绘制

GUI编程 04 贪吃蛇小游戏 4.1 第一步&#xff1a;先绘制一个静态的面板 首先&#xff0c;需要新建两个类&#xff0c;一个StartGame类作为游戏的主启动类&#xff1b;一个GamePanel类作为游戏的面板类。此外&#xff0c;再新建一个Data类作为数据中心(存放了小蛇各部分图像的…

目标文件(ELF格式)

1.linux中有三类目标文件 **&#xff08;1&#xff09;可重定位目标文件&#xff08;.o或者.a&#xff09;&#xff1a;**包含二进制代码和数据&#xff0c;其形式可以和其他目标文件进行合并&#xff0c;创建一个可执行目标文件。&#xff08;.a文件是由很多个.o文件的集合&a…

解决uncompyle6反编译报错KeyError

报错内容&#xff1a;KeyError&#xff1a;3.11.0 &#xff08;这个是我自己的Python版本号&#xff09; 主要原因就是你的Python版本没在它库文件支持的版本里&#xff0c;我们需要进行手动添加即可。 首先找到文件&#xff1a;magics.py 我的是在这个路径下&#xff1a;D:\…

《QT从基础到进阶·三十六》QWidget实现收缩栏的效果

功能&#xff1a; 1、可以在收缩栏插件中添加界面 2、可以把界面展开或收缩 3、可以用鼠标拖动界面改变界面的排放顺序 源码放在最下方 1、可以在收缩栏插件中添加界面 virtual void addWidget(QWidget* widget, const QString& label, const QIcon& icon QIcon())…

基于单片机加热炉多参数检测和PID炉温系统

**单片机设计介绍&#xff0c; 基于单片机加热炉多参数检测和PID炉温系统 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的公交安全预警系统可以被设计成能够实时监测公交车辆的行驶状态&#xff0c;并在发生异常情况…

华为云IoT与OpenHarmony深度协同,加速设备上鸿即上云【云驻共创】

本次专题论坛探讨了华为云IoT与Open Harmony的深度协同、边缘屏蔽硬件差异、实现智慧隧道全方位智能化管理&#xff0c;以及华为云与Open Harmony生态的合作。同时也介绍了华为云物联网卡平台、HTTP2协议以及华为物联网在交通领域的应用。 一&#xff0e;华为云IoT与Open Harm…

了解一下公网IP和域名的区别与联系

​  公网IP和域名是互联网中两个重要的概念&#xff0c;它们在网络通信和网站访问中起着不同的作用。 我们来了解一下公网IP。公网IP是指在全球范围内唯一的IP地址&#xff0c;用于标识互联网上的设备。每个设备连接到互联网时都会被分配一个公网IP地址&#xff0c;这个地址可…

手把手设计C语言版循环队列(力扣622:设计循环队列)

文章目录 前言描述分析力扣AC代码 力扣&#xff1a; 622.设计循环队列 前言 队列会出现“假溢出”现象&#xff0c;即队列的空间有限&#xff0c;队列是在头和尾进行操作的&#xff0c;当元素个数已经达到最大个数时&#xff0c;队尾已经在空间的最后面了&#xff0c;但是对头…

北邮22级信通院数电:Verilog-FPGA(0)怎么使用modelsim进行仿真?modelsim仿真教程一份请签收~

北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章&#xff0c;请访问专栏&#xff1a; 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客 最近很多uu问我怎么用quartus连接的modelsim软件进…