读取另一驱动

驱动通过"\\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是所有权限
  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. NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
  87. {
  88. pDriverObject->DriverUnload = UnFilterDriverRoutine;
  89. FilterDriverQuery ();
  90.  
  91. return STATUS_SUCCESS;
  92. }

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驱动的详细信息:

  1. dt _DRIVER_OBJECT -b 84F79858

WinDbg输出如下:

  1. lkd> dt_DRIVER_OBJECT -b 84F79858
  2. nt!_DRIVER_OBJECT
  3. +0x000 Type :
  4. +0x002 Size :
  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 "\Driver\XueTr"
  12. +0x000 Length : 0x1a
  13. +0x002 MaximumLength : 0x1a
  14. +0x004 Buffer : 0xe1605358 "\Driver\XueTr"
  15. +0x024 HardwareDatabase : 0x80691b90
  16. +0x028 FastIoDispatch : (null)
  17. +0x02c DriverInit : 0xed62b03e
  18. +0x030 DriverStartIo : (null)
  19. +0x034 DriverUnload : 0xed619668
  20. +0x038 MajorFunction :
  21. [] 0xed619792
  22. [] 0x804fe101
  23. [] 0xed619792
  24. [] 0x804fe101
  25. [] 0x804fe101
  26. [] 0x804fe101
  27. [] 0x804fe101
  28. [] 0x804fe101
  29. [] 0x804fe101
  30. [] 0x804fe101
  31. [] 0x804fe101
  32. [] 0x804fe101
  33. [] 0x804fe101
  34. [] 0x804fe101
  35. [] 0xf7c37000
  36. [] 0x804fe101
  37. [] 0x804fe101
  38. [] 0x804fe101
  39. [] 0x804fe101
  40. [] 0x804fe101
  41. [] 0x804fe101
  42. [] 0x804fe101
  43. [] 0x804fe101
  44. [] 0x804fe101
  45. [] 0x804fe101
  46. [] 0x804fe101
  47. [] 0x804fe101
  48. [] 0x804fe101

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

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

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

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

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

  1. 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 = ;
  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\t%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虚拟机下查看该结构

  1. lkd> dt_LDR_DATA_TABLE_ENTRY
  2. nt!_LDR_DATA_TABLE_ENTRY
  3. +0x000 InLoadOrderLinks : _LIST_ENTRY
  4. +0x008 InMemoryOrderLinks : _LIST_ENTRY
  5. +0x010 InInitializationOrderLinks : _LIST_ENTRY
  6. +0x018 DllBase : Ptr32 Void
  7. +0x01c EntryPoint : Ptr32 Void
  8. +0x020 SizeOfImage : Uint4B
  9. +0x024 FullDllName : _UNICODE_STRING
  10. +0x02c BaseDllName : _UNICODE_STRING
  11. +0x034 Flags : Uint4B
  12. +0x038 LoadCount : Uint2B
  13. +0x03a TlsIndex : Uint2B
  14. +0x03c HashLinks : _LIST_ENTRY
  15. +0x03c SectionPointer : Ptr32 Void
  16. +0x040 CheckSum : Uint4B
  17. +0x044 TimeDateStamp : Uint4B
  18. +0x044 LoadedImports : Ptr32 Void
  19. +0x048 EntryPointActivationContext : Ptr32 Void
  20. +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;
  1. InLoadOrderLinks是一个双向的循环链表,保存了所有驱动的地址。我们只要遍历它,就能够找到所有的驱动了。
  1. FullDllName是驱动的完整路径(路径+名称),BaseDllName是驱动的名称(不包含路径)
  2.  
  3. 驱动加载后的输出如下:

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

梦织未来Windows驱动编程 第05课 小结(读取另一驱动,遍历所有驱动)的更多相关文章

  1. 梦织未来Windows驱动编程 第03课 驱动的编程规范

    最近根据梦织未来论坛的驱动教程学习了一下Windows下的驱动编程,做个笔记备忘.这是第03课<驱动的编程规范>. 驱动部分包括基本的驱动卸载函数.驱动打开关闭读取写入操作最简单的分发例程 ...

  2. 梦织未来Windows驱动编程 第06课 驱动对磁盘文件的操作

    代码部分: 实现一个文件C:\\text.txt,并读取写入内容到文件,然后将文件设置为只读,并隐藏文件.代码如下: //MyCreateFile.c //2016.07.22 #include &l ...

  3. 梦织未来Windows驱动编程 第04课 驱动相关的数据结构

  4. Windows游戏编程之从零开始d

    Windows游戏编程之从零开始d I'm back~~恩,几个月不见,大家还好吗? 这段时间真的好多童鞋在博客里留言说或者发邮件说浅墨你回来继续更新博客吧. woxiangnifrr童鞋说每天都在来 ...

  5. (转)Windows驱动编程基础教程

    版权声明     本书是免费电子书. 作者保留一切权利.但在保证本书完整性(包括版权声明.前言.正文内容.后记.以及作者的信息),并不增删.改变其中任何文字内容的前提下,欢迎任何读者 以任何形式(包括 ...

  6. 《天书夜读:从汇编语言到windows内核编程》五 WDM驱动开发环境搭建

    (原书)所有内核空间共享,DriverEntery是内核程序入口,在内核程序被加载时,这个函数被调用,加载入的进程为system进程,xp下它的pid是4.内核程序的编写有一定的规则: 不能调用win ...

  7. 《天书夜读:从汇编语言到windows内核编程》六 驱动、设备、与请求

    1)跳入到基础篇的内核编程第7章,驱动入口函数DriverEnter的返回值决定驱动程序是否加载成功,当打算反汇编阅读驱动内核程序时,可寻找该位置. 2)DRIVER_OBJECT下的派遣函数(分发函 ...

  8. 《逐梦旅程 WINDOWS游戏编程之从零开始》笔记5——Direct3D中的顶点缓存和索引缓存

    第12章 Direct3D绘制基础 1. 顶点缓存 计算机所描绘的3D图形是通过多边形网格来构成的,网网格勾勒出轮廓,然后在网格轮廓的表面上贴上相应的图片,这样就构成了一个3D模型.三角形网格是构建物 ...

  9. storysnail的Windows串口编程笔记

    storysnail的Windows串口编程笔记 作者 He YiJun – storysnail<at>gmail.com 团队 ls 版权 转载请保留本声明! 本文档包含的原创代码根据 ...

随机推荐

  1. [转]关于CLOB存储Base64图片编码,直接在前台显示解决方案

    转至:http://ouapi.com/tool/imgtob 两种方案: Base64在CSS中的使用 .yanshishuxing{ background-image: url("dat ...

  2. 【mysql-索引+存储过程+函数+触发器-更新。。。】

    BaseOn ===>MySQL5.6 一:索引 1:创建索引: create index nameIndex on seckill(name) ; 2:查看索引: show index fro ...

  3. ICP备案接入商

    1. 什么是ICP备案中的接入商 ICP备案系统中所说的接入商:是指为您提供虚拟主机.服务器托管或者专线接入的公司. 现在ICP备案的原则是“谁接入谁负责”,接入商一般都有自己的电子平台和工信部对接, ...

  4. [Xcode 实际操作]四、常用控件-(7)UIStepper控件的使用

    目录:[Swift]Xcode实际操作 本文将演示步进控件的基本用法.步进控件常用于小范围数值的调整. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import ...

  5. Linux调优(文件系统)

    查看单个文件是否发生碎片化(被存在磁盘非连续磁盘块上) # filefrag -v /var/log/messages 查看文件系统是否存在大量碎片(会显示空闲离散的块) # dumpe2fs /de ...

  6. HDU1425 A Chess Game

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1524 思路:题目就是给你一个拓扑图,然后指定点的位置放棋子,然后两人轮流移动棋子(题目中的边的关系),直到 ...

  7. js原型链,作用域,闭包讲解

    当面试的时候遇到问原型链,闭包,还有作用域,直接 拿张纸和笔把原型链画出来,闭包跟作用域直接用笔写几道题出来加深理解(因为我们是理科生,图形和题目以及控制台输出结果才是最直观的方法) 问:什么是原型链 ...

  8. JS事件之鼠标悬浮窗(鼠标悬浮窗抖动问题的解决)

    鼠标进入显示悬浮窗,思路有简单有困难. 首先要注意的是我们要给悬浮窗设置position为absolute,不然我们改了 style.left style.top发现没有变化很尴尬.其余的内容看起来就 ...

  9. JAVAFX-6 面板总结

    说明:转至:https://www.cnblogs.com/lensener/p/7978225.html 便于集中看到这些文章 面板列表: Accordion 手风琴面板:就是一个折叠展开功能,一般 ...

  10. 1105 Spiral Matrix(25 分)

    This time your job is to fill a sequence of N positive integers into a spiral matrix in non-increasi ...