最近学习了一下IDA的使用,正好拿WdfLdr.sys练个手。结合windbg的调试输出,逆向了其中的WdfVersionBind函数。我在文章的结尾部分给出了对应的idb文件的网盘链接(用优快云上传资源的成功率太低了,我只能放弃了...)。
以下是我逆向得到的WdfVersionBind函数实现的伪代码。整个函数中指针变量v5 v9对应的结构体未知,无法逆向出来,比较遗憾,不过应该不影响把握函数主体~
NTSTATUS __stdcall WdfVersionBind(_in DRIVER_OBJECT* a3, _in UNICODE_STRING* a4, _inout WDF_BIND_INFO* a5, _inout WDF_DRIVER_GLOBALS** a6)
{
__int32 v4; // edi@6
int v5; // ecx@9
NTSTATUS result; // eax@13
int v7; // [sp+0h] [bp-14h]@1
int UniStr_DrvRegPath_loc; // [sp+4h] [bp-10h]@1
int v9; // [sp+8h] [bp-Ch]@3
int WDFLDR_LIBRARY_MODULE_Ptr; // [sp+Ch] [bp-8h]@1
int *Client_Info_Ptr; // [sp+10h] [bp-4h]@1
Client_Info_Ptr = 0;
WDFLDR_LIBRARY_MODULE_Ptr = 0;
v7 = 8;
UniStr_DrvRegPath_loc = 0;
if ( WdfLdrDiags & 1 )
{
_DbgPrint("WdfLdr: WdfVersionBind - ", v7, UniStr_DrvRegPath_loc);
_DbgPrint("WdfLdr: WdfVersionBind: enter\n");
}
v9 = 0;
if ( a6 && a5 && *(_DWORD *)(a5 + offsetof(_WDF_BIND_INFO, funcTable)) )
{
v4 = ReferenceVersion(a5, &WDFLDR_LIBRARY_MODULE_Ptr);
if ( v4 < 0 )
goto LABEL_24;
v4 = LibraryLinkInClient(*(void **)(a5 + offsetof(_WDF_BIND_INFO, wdfModule)), a5, (int)Client_Info_Ptr, &v9);
if ( v4 < 0 )
{
if ( WdfLdrDiags & 1 )
{
_DbgPrint("WdfLdr: WdfVersionBind - ");
_DbgPrint("WdfLdr: DereferenceVersion: LibraryLinkInClient failed %X\n", v4);
}
}
else
{
UniStr_DrvRegPath_loc = a4;
Client_Info_Ptr = &v7;
v4 = (*(int (__stdcall **)(int, _DWORD *, int **))(*(_DWORD *)(WDFLDR_LIBRARY_MODULE_Ptr
+ offsetof(WDFLDR_LIBRARY_MODULE, LibraryInfo))
+ offsetof(_WDF_LIBRARY_INFO, LibraryRegisterClient)))(
a5,
a6,
&Client_Info_Ptr);
if ( v4 < 0 )
{
if ( WdfLdrDiags & 1 )
{
_DbgPrint("WdfLdr: WdfVersionBind - ");
_DbgPrint("WdfLdr: libraryRegisterClient: LibraryLinkInClient failed %X\n", v4);
}
}
else
{
v5 = v9;
*(_DWORD *)(v9 + 8) = *a6;
*(_DWORD *)(v5 + 12) = Client_Info_Ptr;
}
}
if ( v4 < 0 )
{
LABEL_24:
if ( WDFLDR_LIBRARY_MODULE_Ptr )
WdfVersionUnbind(a4, a5, *a6);
}
if ( WdfLdrDiags & 1 )
{
_DbgPrint("WdfLdr: WdfVersionBind - ");
_DbgPrint("Returning with Status 0x%x\n", v4);
}
result = v4;
}
else
{
result = -1073741811;
}
return result;
}在前面的博文中,我以wdfsimple.sys为例,粗略的分析了wdf框架的入口。本文中我会继续基于wdfsimple.sys进行分析,以保持行文的连续性。
WdfVersionBind被FxDriverEntryWorker调用时,参数_DRIVER_OBJECT*和_UNICODE_STRING*已经初始化完毕,这和wdm驱动的流程一致。至于参数_WDF_BIND_INFO和WDF_DRIVER_GLOBALS,这是wdfsimple.sys定义的全局变量,在链接阶段已经完成初始化。当然,这不是我的臆测,而是根据以下2个结果,确定它们是由sys文件定义而不是OS定义的全局变量:
1).windbg的符号输出,查找所有WdfBindInfo和符号,windbg告诉我该符号包含在wdfsimple模块中
kd> x *!WdfBindInfo
a7fe3014 wdfsimple!WdfBindInfo = struct _WDF_BIND_INFO
kd> x wdfsimple!WdfDriverGlobals
a7fe3070 wdfsimple!WdfDriverGlobals = 0x00000000
2).ida中进入wdfsimple.sys!data段,可以看到WdfBindInfo结构体变量(注意,是结构体变量,不是指针)和WdfDriverGlobals指针变量(注意,是指针变量)的定义:
上面扯的有点远了,赶紧收回来。我继续分析函数WdfVersionBind最后两个参数的作用。先说_WDF_BIND_INFO,进入FxDriverEntry时,各成员变量并未全部初始化完毕,直到调用ReferenceVersion后。
;这部分输出源自调用ReferenceVersion前 WDF_BIND_INFO各域值
kd> bp WDFLDR!WdfVersionBind
kd> g
Breakpoint 0 hit
WDFLDR!WdfVersionBind:
8793a270 8bff mov edi,edi
kd> kb 1 ;在WDFLDR!WdfVersionBind入口下断点,断下后查看堆栈
ChildEBP RetAddr Args to Child
8ca8b58c a7fc1312 a92e81b0 a7fc3064 a7fc3014 WDFLDR!WdfVersionBind
kd> dd esp L5 ;查看FxDriverEntry传递给WdfVersionBind的参数
8ca8b590 a7fc1312 a92e81b0 a7fc3064 a7fc3014<-wdfsimple!WDF_BIND_INFO类型的指针
8ca8b5a0 a7fc3070<-wdfsimple!WDF_DRIVER_GLOBALS类型的二级指针
kd> dt WDF_BIND_INFO poi(esp+c) ;输出wdfsimple!WDF_BIND_INFO的各成员
wdfsimple!WDF_BIND_INFO
+0x000 Size : 0x20
+0x004 Component : 0xa7fc204c "KmdfLibrary"
+0x008 Version : _WDF_VERSION
+0x014 FuncCount : 0x1bc
+0x018 FuncTable : 0xa7fc3074 -> (null)
+0x01c Module : (null) ====================================================================
;这部分输出源自调用ReferenceVersion后 WDF_BIND_INFO各域值
kd> bp ReferenceVersion
kd> g
Breakpoint 1 hit
WDFLDR!ReferenceVersion:
879323e0 8bff mov edi,edi
kd> gu ;执行到ReferenceVersion函数返回
WDFLDR!WdfVersionBind+0x65:
8793a2d5 8bf8 mov edi,eax
kd> dt WDF_BIND_INFO a7fe3014 ;a7fe3014是WdfVersionBind的第三个参数
Wdf01000!WDF_BIND_INFO
+0x000 Size : 0x20
+0x004 Component : 0xa7fe204c "KmdfLibrary"
+0x008 Version : _WDF_VERSION
+0x014 FuncCount : 0x1bc
+0x018 FuncTable : 0xa7fe3074 -> (null)
+0x01c Module : 0x8b2aceb0 _LIBRARY_MODULE
kd> dt _LIBRARY_MODULE 0x8b2aceb0
WDFLDR!_LIBRARY_MODULE
+0x000 LibraryRefCount : 0n1
+0x004 LibraryListEntry : _LIST_ENTRY [ 0x879391cc - 0x879391cc ]
+0x00c ClientRefCount : 0n21 ;个人认为,所有使用WDF框架的驱动,都被称作Client,这个域记录这些Client的数量,同时,也是包含WdfDriverGlobals变量的数量
+0x010 IsBootDriver : 0x1 ''
+0x011 ImplicitlyLoaded : 0x1 ''
+0x014 Service : _UNICODE_STRING "\Registry\Machine\System\CurrentControlSet\Services\Wdf01000"
+0x01c ImageName : _UNICODE_STRING "Wdf01000.sys"
+0x024 ImageAddress : 0x87880000 Void
+0x028 ImageSize : 0xa6000
+0x02c LibraryFileObject : 0x8b2ace28 _FILE_OBJECT ;指向\Driver\Wdf01000
+0x030 LibraryDriverObject : 0x86ba5378 _DRIVER_OBJECT ;指向\Driver\Wdf01000
+0x034 LibraryInfo : 0x879128c8 _WDF_LIBRARY_INFO ;Wdf01000.sys注册的用于创建WdfDriverGlobal结构的回调函数,见后面的输出信息
+0x038 ClientsListHead : _LIST_ENTRY [ 0xa201d4b0 - 0x86bfd178 ] ;用于将WDF Client通过_LIBRARY_MODULE!_LIST_ENTRY加入双链表
+0x040 ClientsListLock : _ERESOURCE
+0x078 Version : _WDF_VERSION ;wdf01000.sys的版本号,具体数值见后面的输出信息
+0x084 LoaderEvent : _KEVENT
+0x094 LoaderThread : (null)
+0x098 ClassListHead : _LIST_ENTRY [ 0x8dfb1618 - 0x86b07888 ]
kd> dt _WDF_LIBRARY_INFO 0x879128c8 ;Wdf01000.sys注册的用于创建WdfDriverGlobal结构的回调函数
Wdf01000!_WDF_LIBRARY_INFO
+0x000 Size : 0x20
+0x004 LibraryCommission : 0x87896840 long Wdf01000!LibraryCommission+0
+0x008 LibraryDecommission : 0x878d1bf4 long Wdf01000!LibraryDecommission+0
+0x00c LibraryRegisterClient : 0x878a5110 long Wdf01000!LibraryRegisterClient+0
+0x010 LibraryUnregisterClient : 0x878a8da8 long Wdf01000!LibraryUnregisterClient+0
+0x014 Version : _WDF_VERSION
kd> dt _WDF_VERSION 0x8b2aceb0+0x78 ;windbg得到的wdf01000.sys的版本号
Wdf01000!_WDF_VERSION
+0x000 Major : 1
+0x004 Minor : 0xf 0xf对应十进制的15
+0x008 Build : 0实际wdf01000.sys的版本号:
结合ReferenceVersion函数执行前后的输出,可以大概猜出这个函数的作用无外乎根据Wdf01000.sys的内容更新WDF_BIND_INFO!Module域。
这些域中最重要的当属WDF_BIND_INFO!Module!_WDF_LIBRARY_INFO结构,因为WdfVersionBind要调用结构中的各个回调函数,完成最终的初始化,包括后面要提到的WdfDriverGlobal变量
附:idb文件链接及密码:6abo
OS环境:win10 x86 RS2 RTM:
kd> vertarget
Windows 7 Kernel Version 10240 MP (1 procs) Free x86 compatible
Built by: 10240.16384.x86fre.th1.150709-1700
Machine Name:
Kernel base = 0x81868000 PsLoadedModuleList = 0x81aa9a38
Debug session time: Mon Dec 25 22:34:40.472 2017 (UTC + 8:00)
System Uptime: 0 days 0:10:36.174

本文解析了WdfVersionBind函数的实现,并分析了其在加载WDF驱动时的角色。重点介绍了函数如何处理WDF_BIND_INFO结构体以及如何通过调用不同回调函数完成驱动初始化。
1393

被折叠的 条评论
为什么被折叠?



