|
读取另一驱动
驱动通过"\\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 "\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 [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\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虚拟机下查看该结构
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的驱动,应该是做了特殊处理 |
|
|