• 梦织未来Windows驱动编程 第05课 小结(读取另一驱动,遍历所有驱动)


    读取另一驱动

    驱动通过"\Driver\XueTr"获取到了XueTr工具的驱动,并Hook了XueTr驱动的分发函数。

    具体的驱动代码如下:

     1 //FilterDriver.c
     2 //2016.07.15
     3 
     4 #include "ntddk.h"
     5 
     6 NTKERNELAPI
     7 NTSTATUS
     8 ObReferenceObjectByName(
     9     IN PUNICODE_STRING ObjectName,
    10     IN ULONG Attributes,
    11     IN PACCESS_STATE PassedAccessState OPTIONAL,
    12     IN ACCESS_MASK DesiredAccess OPTIONAL,
    13     IN POBJECT_TYPE ObjectType,
    14     IN KPROCESSOR_MODE AccessMode,
    15     IN OUT PVOID ParseContext OPTIONAL,
    16     OUT PVOID *Object
    17     );
    18 
    19 extern POBJECT_TYPE *IoDriverObjectType; 
    20 
    21 //global
    22 PDRIVER_OBJECT g_FilterDriverObject;
    23 PDRIVER_DISPATCH gfn_OrigReadCompleteRoutine;
    24 
    25 //我们的驱动分发函数
    26 NTSTATUS FilterReadCompleteRoutine(
    27     __in struct _DEVICE_OBJECT *DeviceObject,
    28      __inout struct _IRP *Irp)
    29 {
    30     KdPrint(("IRP_MJ_DEVICE_CONTROL coming."));
    31 
    32     //处理完毕后,要调用原分发例程
    33     return gfn_OrigReadCompleteRoutine(DeviceObject, Irp);
    34 }
    35 
    36 //驱动卸载函数
    37 VOID UnFilterDriverRoutine(__in struct _DRIVER_OBJECT *DriverObject)
    38 {
    39     //此内存可读时,恢复
    40     if (MmIsAddressValid(gfn_OrigReadCompleteRoutine))
    41     {
    42         KdPrint(("UnFilterDriverRoutine Success."));
    43 
    44         //卸载时恢复原分发例程
    45         g_FilterDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = gfn_OrigReadCompleteRoutine;
    46     }
    47 }
    48 
    49 //过滤函数
    50 NTSTATUS FilterDriverQuery()
    51 {
    52     NTSTATUS Status;
    53     UNICODE_STRING usObjectName;
    54     
    55     RtlInitUnicodeString (&usObjectName, L"\Driver\XueTr");
    56 
    57     //根据驱动名称获得驱动对象
    58     Status = ObReferenceObjectByName (
    59         &usObjectName,
    60         OBJ_CASE_INSENSITIVE,    //大小写不敏感
    61         NULL,
    62         0,    //访问权限,0是所有权限
    63         *IoDriverObjectType,
    64         KernelMode,    //处理器模式
    65         NULL,
    66         (PVOID*)&g_FilterDriverObject
    67         );
    68     if (!NT_SUCCESS(Status))
    69     {
    70         KdPrint(("Filter Failed!"));
    71         return Status;
    72     }
    73 
    74     KdPrint(("0x%X", g_FilterDriverObject));    //打印驱动对象地址
    75 
    76     //保存原分发例程,并修改为我们的函数
    77     gfn_OrigReadCompleteRoutine = g_FilterDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL];
    78     g_FilterDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)FilterReadCompleteRoutine;
    79 
    80     ObDereferenceObject(g_FilterDriverObject);    //清除引用计数
    81 
    82     return STATUS_SUCCESS;
    83 }
    84 
    85 
    86 //驱动程序入口函数
    87 NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
    88 {
    89     pDriverObject->DriverUnload = UnFilterDriverRoutine;
    90     FilterDriverQuery ();
    91 
    92     return STATUS_SUCCESS;
    93 }
    FilterDriver.c

    其中,ObReferenceObjectByName函数能够根据驱动名获取到相应的驱动对象,函数原型如下:

     1 NTKERNELAPI
     2 NTSTATUS
     3 ObReferenceObjectByName(
     4     IN PUNICODE_STRING ObjectName,
     5     IN ULONG Attributes,
     6     IN PACCESS_STATE PassedAccessState OPTIONAL,
     7     IN ACCESS_MASK DesiredAccess OPTIONAL,
     8     IN POBJECT_TYPE ObjectType,
     9     IN KPROCESSOR_MODE AccessMode,
    10     IN OUT PVOID ParseContext OPTIONAL,
    11     OUT PVOID *Object
    12     );

    由于ObReferenceObjectByName函数没有文档化,但是被导出了。所以我们需要在代码中对ObReferenceObjectByName函数进行声明。

    另外调用ObReferenceObjectByName函数后,要调用ObDereferenceObject来清除对象的引用计数,否则会造成内存泄漏。

    根据XueTr获取到XueTr的驱动对象地址是0x84F79858,大小是0x00068000

    根据WinObj工具获得XueTr驱动的路径为"\Driver\XueTr"

    用InstDrv安装并启动驱动FilterDriver.sys后,DbgView输出0x84F79858,此地址与上面用XueTr查看的地址相同。说明获取到的XueTr驱动对象的地址是正确的。

    在WinDbg输入以下命令查看XueTr驱动的详细信息:

    dt _DRIVER_OBJECT -b 84F79858

    WinDbg输出如下:

     1 lkd> dt_DRIVER_OBJECT -b 84F79858
     2 nt!_DRIVER_OBJECT
     3    +0x000 Type             : 4
     4    +0x002 Size             : 168
     5    +0x004 DeviceObject     : 0x8617b100 
     6    +0x008 Flags            : 0x12
     7    +0x00c DriverStart      : 0xed5ce000 
     8    +0x010 DriverSize       : 0x68000
     9    +0x014 DriverSection    : 0x862e2220 
    10    +0x018 DriverExtension  : 0x84f79900 
    11    +0x01c DriverName       : _UNICODE_STRING "DriverXueTr"
    12       +0x000 Length           : 0x1a
    13       +0x002 MaximumLength    : 0x1a
    14       +0x004 Buffer           : 0xe1605358  "DriverXueTr"
    15    +0x024 HardwareDatabase : 0x80691b90 
    16    +0x028 FastIoDispatch   : (null) 
    17    +0x02c DriverInit       : 0xed62b03e 
    18    +0x030 DriverStartIo    : (null) 
    19    +0x034 DriverUnload     : 0xed619668 
    20    +0x038 MajorFunction    : 
    21     [00] 0xed619792 
    22     [01] 0x804fe101 
    23     [02] 0xed619792 
    24     [03] 0x804fe101 
    25     [04] 0x804fe101 
    26     [05] 0x804fe101 
    27     [06] 0x804fe101 
    28     [07] 0x804fe101 
    29     [08] 0x804fe101 
    30     [09] 0x804fe101 
    31     [10] 0x804fe101 
    32     [11] 0x804fe101 
    33     [12] 0x804fe101 
    34     [13] 0x804fe101 
    35     [14] 0xf7c37000 
    36     [15] 0x804fe101 
    37     [16] 0x804fe101 
    38     [17] 0x804fe101 
    39     [18] 0x804fe101 
    40     [19] 0x804fe101 
    41     [20] 0x804fe101 
    42     [21] 0x804fe101 
    43     [22] 0x804fe101 
    44     [23] 0x804fe101 
    45     [24] 0x804fe101 
    46     [25] 0x804fe101 
    47     [26] 0x804fe101 
    48     [27] 0x804fe101 

    上面代码中修改的分发函数是IRP_MJ_DEVICE_CONTROL,也就是14号分发例程(0至27)

    XueTr驱动的14号分发函数地址为0xf7c37000

    由XueTr知道我们的驱动FilterDriver.sys基地址为0xF7C36000,大小为0x00006000。

    所以XueTr驱动的14号分发函数地址(0xf7c37000)在我们的驱动内(0xF7C36000~0xF7C36000+0x00006000)

    然后当我们在XueTr工具内刷新时,DbgView内输出

    IRP_MJ_DEVICE_CONTROL coming.

    遍历所有驱动

    遍历所有驱动需要用到一个结构_LDR_DATA_TABLE_ENTRY,具体的驱动代码如下:

     1 //EnumDriver.c
     2 //2016.07.17
     3 
     4 #include <ntddk.h>
     5 
     6 typedef struct _LDR_DATA_TABLE_ENTRY{
     7     LIST_ENTRY InLoadOrderLinks;            //链表 保存了所有已经读取到内存中的驱动地址
     8     LIST_ENTRY InMemoryOrderLinks;            //链表 保存了已经安装,但没启动(没执行DriverEntry)的驱动地址
     9     LIST_ENTRY InInitializationOrderLinks;    //链表 保存了已经安装,同时也启动了(执行了DriverEntry)的驱动地址
    10     PVOID DllBase;
    11     PVOID EntryPoint;
    12     ULONG SizeOfImage;
    13     UNICODE_STRING FullDllName; 
    14     UNICODE_STRING BaseDllName;
    15     ULONG Flags;
    16     USHORT LoadCount;
    17     USHORT TlsIndex;
    18     LIST_ENTRY HashLinks;
    19     PVOID SectionPointer;
    20     ULONG CheckSum;
    21     ULONG TimeDateStamp;
    22     PVOID LoadedImports;
    23     PVOID EntryPointActivationContext;
    24     PVOID PatchInformation;
    25 }LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
    26 
    27 VOID MyDriverUnload(PDRIVER_OBJECT pDriverObject)
    28 {
    29     //
    30     KdPrint(("Unload EnumDriver.sys Success."));
    31 }
    32 
    33 VOID EnumDriver(PDRIVER_OBJECT pDriverObject)
    34 {
    35     PLDR_DATA_TABLE_ENTRY pLdrDataTableEntry, pTempLdrDataTableEntry; 
    36     PLIST_ENTRY pList;
    37     int i = 0;
    38     
    39     pLdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;
    40     if (!MmIsAddressValid(pLdrDataTableEntry))
    41     {
    42         return;
    43     }
    44 
    45     pList = &pLdrDataTableEntry->InLoadOrderLinks;
    46 
    47     while (pList != pLdrDataTableEntry->InLoadOrderLinks.Blink)
    48     {
    49         //ToDo
    50         pTempLdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)pList;
    51         i++;
    52 
    53         if(MmIsAddressValid(pTempLdrDataTableEntry))
    54         {
    55             if (MmIsAddressValid(&pTempLdrDataTableEntry->BaseDllName) && MmIsAddressValid(&pTempLdrDataTableEntry->BaseDllName))
    56                 KdPrint(("%d:%wZ	%wZ", i, &pTempLdrDataTableEntry->BaseDllName, &pTempLdrDataTableEntry->FullDllName));
    57         }
    58 
    59         pList = pList->Flink;
    60     }
    61 }
    62 
    63 NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
    64 {
    65     pDriverObject->DriverUnload = MyDriverUnload;
    66     EnumDriver(pDriverObject);
    67 
    68     return STATUS_SUCCESS;
    69 }
    EnumDriver.c

    用Windbg在XP虚拟机下查看该结构

    lkd> dt_LDR_DATA_TABLE_ENTRY
    nt!_LDR_DATA_TABLE_ENTRY
       +0x000 InLoadOrderLinks : _LIST_ENTRY
       +0x008 InMemoryOrderLinks : _LIST_ENTRY
       +0x010 InInitializationOrderLinks : _LIST_ENTRY
       +0x018 DllBase          : Ptr32 Void
       +0x01c EntryPoint       : Ptr32 Void
       +0x020 SizeOfImage      : Uint4B
       +0x024 FullDllName      : _UNICODE_STRING
       +0x02c BaseDllName      : _UNICODE_STRING
       +0x034 Flags            : Uint4B
       +0x038 LoadCount        : Uint2B
       +0x03a TlsIndex         : Uint2B
       +0x03c HashLinks        : _LIST_ENTRY
       +0x03c SectionPointer   : Ptr32 Void
       +0x040 CheckSum         : Uint4B
       +0x044 TimeDateStamp    : Uint4B
       +0x044 LoadedImports    : Ptr32 Void
       +0x048 EntryPointActivationContext : Ptr32 Void
       +0x04c PatchInformation : Ptr32 Void

    因为结构_LDR_DATA_TABLE_ENTRY是未导出的,所以要在代码开头定义一下:

     1 typedef struct _LDR_DATA_TABLE_ENTRY{
     2     LIST_ENTRY InLoadOrderLinks;              //链表 保存了所有已经读取到内存中的驱动地址
     3     LIST_ENTRY InMemoryOrderLinks;            //链表 保存了已经安装,但没启动(没执行DriverEntry)的驱动地址
     4     LIST_ENTRY InInitializationOrderLinks;    //链表 保存了已经安装,同时也启动了(执行了DriverEntry)的驱动地址
     5     PVOID DllBase;
     6     PVOID EntryPoint;
     7     ULONG SizeOfImage;
     8     UNICODE_STRING FullDllName; 
     9     UNICODE_STRING BaseDllName;
    10     ULONG Flags;
    11     USHORT LoadCount;
    12     USHORT TlsIndex;
    13     LIST_ENTRY HashLinks;
    14     PVOID SectionPointer;
    15     ULONG CheckSum;
    16     ULONG TimeDateStamp;
    17     PVOID LoadedImports;
    18     PVOID EntryPointActivationContext;
    19     PVOID PatchInformation;
    20 }LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
    InLoadOrderLinks是一个双向的循环链表,保存了所有驱动的地址。我们只要遍历它,就能够找到所有的驱动了。
    FullDllName是驱动的完整路径(路径+名称),BaseDllName是驱动的名称(不包含路径)


    驱动加载后的输出如下:

    其中的第二个 2:(null)(null)是XueTr的驱动,应该是做了特殊处理

  • 相关阅读:
    下载并安装chrome插件的方法
    QString转化为char *的方式
    a socket demo
    TCP/IP相关知识总结(马士兵教育)视频对应图片
    C++中的按位或的用意
    dll路径加载顺序
    【第二周】【作业七】四人小组项目
    【第二周】【作业六】结对项目,四则运算++
    【第二周】【作业八】个人项目词频统计++
    【第二周】【作业三】效能测试
  • 原文地址:https://www.cnblogs.com/linuxxiaoyu/p/5673394.html
Copyright © 2020-2023  润新知