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. 代码实现
通过已上可以看出代码实现就简单了。我们先定义一个结构体,只需要几个简单的字段,无需要定义全部
typedef struct _LDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
union {
ULONG FlagGroup;
ULONG Flags;
};
}LDR_DATA_TABLE_ENTRY64, *PLDR_DATA_TABLE_ENTRY64;
VOID Function(PDRIVER_OBJECT pDriverObject)
{
PLDR_DATA_TABLE_ENTRY64 pldt = (PLDR_DATA_TABLE_ENTRY64)pDriverObject->DriverSection;
if (pldt)
{
KDPRINT("ImagePath is :%wZ\n", pldt->FullDllName);
//do smomething else....
}
}