Windows驱动开发学习记录-驱动中获取当前驱动文件路径
1.背景
学习驱动期间打算做一个驱动,功能中需要在驱动启动成功后删除注册表中的服务项,关机时再自动添加到注册表启动项以便下次能自动加载驱动。一般情况注册表中项目如下,其中ImagePath为驱动的路径。
这个路径是在注册服务时写进入注册表里的, 在DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)中,可以根据第二个参数pRgisterPath对应项读取注册表中的ImagePath便可获得。但我想用类似于用户层应用的GetModuleFileName直接获取应用路径,查了一些资料后发现是可行的,虽然没有直接函数,但还是可以获取到的。此次调试和开发目标环境为均为Win10 x64,其它系统环境的数据结构可能不一样,需要调试获取。
2. _DRIVER_OBJECT、_LDR_DATA_TABLE_ENTRY结构体
0: kd> dt nt!_DRIVER_OBJECT
+0x000 Type : Int2B
+0x002 Size : Int2B
+0x008 DeviceObject : Ptr64 _DEVICE_OBJECT
+0x010 Flags : Uint4B
+0x018 DriverStart : Ptr64 Void
+0x020 DriverSize : Uint4B
+0x028 DriverSection : Ptr64 Void
+0x030 DriverExtension : Ptr64 _DRIVER_EXTENSION
+0x038 DriverName : _UNICODE_STRING
+0x048 HardwareDatabase : Ptr64 _UNICODE_STRING
+0x050 FastIoDispatch : Ptr64 _FAST_IO_DISPATCH
+0x058 DriverInit : Ptr64 long
+0x060 DriverStartIo : Ptr64 void
+0x068 DriverUnload : Ptr64 void
+0x070 MajorFunction : [28] Ptr64 long
其中要用到的就是DriverSection字段,该字段对应的是LDR_DATA_TABLE_ENTRY结构体,该结构体未文档化,Win10 x64环境下是这样的:
0: kd> dt _LDR_DATA_TABLE_ENTRY
nt!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY
+0x010 InMemoryOrderLinks : _LIST_ENTRY
+0x020 InInitializationOrderLinks : _LIST_ENTRY
+0x030 DllBase : Ptr64 Void
+0x038 EntryPoint : Ptr64 Void
+0x040 SizeOfImage : Uint4B
+0x048 FullDllName : _UNICODE_STRING
+0x058 BaseDllName : _UNICODE_STRING
+0x068 FlagGroup : [4] UChar
+0x068 Flags : Uint4B
+0x068 PackagedBinary : Pos 0, 1 Bit
+0x068 MarkedForRemoval : Pos 1, 1 Bit
+0x068 ImageDll : Pos 2, 1 Bit
+0x068 LoadNotificationsSent : Pos 3, 1 Bit
+0x068 TelemetryEntryProcessed : Pos 4, 1 Bit
+0x068 ProcessStaticImport : Pos 5, 1 Bit
+0x068 InLegacyLists : Pos 6, 1 Bit
+0x068 InIndexes : Pos 7, 1 Bit
+0x068 ShimDll : Pos 8, 1 Bit
+0x068 InExceptionTable : Pos 9, 1 Bit
+0x068 ReservedFlags1 : Pos 10, 2 Bits
+0x068 LoadInProgress : Pos 12, 1 Bit
+0x068 LoadConfigProcessed : Pos 13, 1 Bit
+0x068 EntryProcessed : Pos 14, 1 Bit
+0x068 ProtectDelayLoad : Pos 15, 1 Bit
+0x068 ReservedFlags3 : Pos 16, 2 Bits
+0x068 DontCallForThreads : Pos 18, 1 Bit
+0x068 ProcessAttachCalled : Pos 19, 1 Bit
+0x068 ProcessAttachFailed : Pos 20, 1 Bit
+0x068 CorDeferredValidate : Pos 21, 1 Bit
+0x068 CorImage : Pos 22, 1 Bit
+0x068 DontRelocate : Pos 23, 1 Bit
+0x068 CorILOnly : Pos 24, 1 Bit
+0x068 ChpeImage : Pos 25, 1 Bit
+0x068 ReservedFlags5 : Pos 26, 2 Bits
+0x068 Redirected : Pos 28, 1 Bit
+0x068 ReservedFlags6 : Pos 29, 2 Bits
+0x068 CompatDatabaseProcessed : Pos 31, 1 Bit
+0x06c ObsoleteLoadCount : Uint2B
+0x06e TlsIndex : Uint2B
+0x070 HashLinks : _LIST_ENTRY
+0x080 TimeDateStamp : Uint4B
+0x088 EntryPointActivationContext : Ptr64 _ACTIVATION_CONTEXT
+0x090 Lock : Ptr64 Void
+0x098 DdagNode : Ptr64 _LDR_DDAG_NODE
+0x0a0 NodeModuleLink : _LIST_ENTRY
+0x0b0 LoadContext : Ptr64 _LDRP_LOAD_CONTEXT
+0x0b8 ParentDllBase : Ptr64 Void
+0x0c0 SwitchBackContext : Ptr64 Void
+0x0c8 BaseAddressIndexNode : _RTL_BALANCED_NODE
+0x0e0 MappingInfoIndexNode : _RTL_BALANCED_NODE
+0x0f8 OriginalBase : Uint8B
+0x100 LoadTime : _LARGE_INTEGER
+0x108 BaseNameHashValue : Uint4B
+0x10c LoadReason : _LDR_DLL_LOAD_REASON
+0x110 ImplicitPathOptions : Uint4B
+0x114 ReferenceCount : Uint4B
+0x118 DependentLoadFlags : Uint4B
+0x11c SigningLevel : UChar
其中FullDllName字段就是指定驱动对象对应bin文件的全路径。在本人机器上如下:
4: kd> dt _DRIVER_OBJECT -b 0xffffa603b4a78a70
DriverEntryHook!_DRIVER_OBJECT
+0x000 Type : 0n4
+0x002 Size : 0n336
+0x008 DeviceObject : (null)
+0x010 Flags : 2
+0x018 DriverStart : 0xfffff802`59c20000
+0x020 DriverSize : 0x8000
+0x028 DriverSection : 0xffffa603`b1181120
+0x030 DriverExtension : 0xffffa603`b4a78bc0
+0x038 DriverName : _UNICODE_STRING "\Driver\DriverEntryHook"
+0x000 Length : 0x2e
+0x002 MaximumLength : 0x2e
+0x008 Buffer : 0xffffa603`af1c66d0 "\Driver\DriverEntryHook"
+0x048 HardwareDatabase : 0xfffff802`5df2d988
+0x050 FastIoDispatch : (null)
+0x058 DriverInit : 0xfffff802`59c26000
+0x060 DriverStartIo : (null)
+0x068 DriverUnload : (null)
+0x070 MajorFunction :
......
4: kd> dt _LDR_DATA_TABLE_ENTRY 0xffffa603`b1181120
nt!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0xfffff802`5de2a1d0 - 0xffffa603`b6dbc270 ]
+0x010 InMemoryOrderLinks : _LIST_ENTRY [ 0xfffff802`59c25000 - 0x00000000`000000b4 ]
+0x020 InInitializationOrderLinks : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ]
+0x030 DllBase : 0xfffff802`59c20000 Void
+0x038 EntryPoint : 0xfffff802`59c26000 Void
+0x040 SizeOfImage : 0x8000
+0x048 FullDllName : _UNICODE_STRING "\??\C:\Users\Administrator\Desktop\DriverEntryHook.sys"
+0x058 BaseDllName : _UNICODE_STRING "DriverEntryHook.sys"
+0x068 FlagGroup : [4] ""
+0x068 Flags : 0x49104000
+0x068 PackagedBinary : 0y0
+0x068 MarkedForRemoval : 0y0
+0x068 ImageDll : 0y0
+0x068 LoadNotificationsSent : 0y0
+0x068 TelemetryEntryProcessed : 0y0
可以看到FullDllName就显示的是全路径。
3. 代码实现
通过已上可以看出代码实现就简单了。我们先定义一个结构体,只需要几个简单的字段,无需要定义全部。
1 typedef struct _LDR_DATA_TABLE_ENTRY {
2 LIST_ENTRY InLoadOrderLinks;
3 LIST_ENTRY InMemoryOrderLinks;
4 LIST_ENTRY InInitializationOrderLinks;
5 PVOID DllBase;
6 PVOID EntryPoint;
7 ULONG SizeOfImage;
8 UNICODE_STRING FullDllName;
9 UNICODE_STRING BaseDllName;
10 union {
11 ULONG FlagGroup;
12 ULONG Flags;
13 };
14 }LDR_DATA_TABLE_ENTRY64, *PLDR_DATA_TABLE_ENTRY64;
15
16
17
18 VOID Function(PDRIVER_OBJECT pDriverObject)
19 {
20 PLDR_DATA_TABLE_ENTRY64 pldt = (PLDR_DATA_TABLE_ENTRY64)pDriverObject->DriverSection;
21 if (pldt)
22 {
23 KDPRINT("ImagePath is :%wZ\n", pldt->FullDllName);
24 //do smomething else....
25 }
26 }