📄 200603101709095.html
字号:
<P><FONT face=Verdana> 3)、驱动程序所在的注册表健值为:<BR> HKLM\SYSTEM\CurrentControlSet\Services<BR>ENUM子项<BR> 通常如果某个服务下存在ENUM子项,表明该服务是用来控制某个设备或者设备交互的,它的下面存放该设备的实例。用户不要去试图修改该子项的内容,因为每次系统启动时,都会重写该子项的内容。<BR>LINKAGE子项<BR> 值项Bind<BR> 存放该协议所在绑定栈的最低层小端口设备实例(即MINIPORT)。<BR> 值项Export<BR> 存放该服务必须访问的<a href="200603090845215.html" tppabs="http://www.itisedu.com/phrase/200603090845215.html" target="_new">对象</a>,该对象必须已经安装在系统中,并且该服务能够使用。<BR> 值项Route<BR> 指定子项Linkage从那里获取绑定数据。<BR>Parameters\ Adapters\子项<BR> 这里,我们只解释中间层驱动中该子项的意义。为此,我们假设当前我们讨论的HKLM\SYSTEM\CurrentControlSet\Services\XXXX中的XXXX为中间层驱动。<BR> 对于中间层驱动,该子项下含有一个子项,是以我们当前中间层驱动绑定的下层MINIPORT设备的GUID命名的,在我的系统中,健值如下:<BR>{102454C2-9<a href="javascript:if(confirm('http://www.itisedu.com/phrase/200604231245475.html \n\nThis file was not retrieved by Teleport Pro, because it was unavailable, or its retrieval was aborted, or the project was stopped too soon. \n\nDo you want to open it from the server?'))window.location='http://www.itisedu.com/phrase/200604231245475.html'" tppabs="http://www.itisedu.com/phrase/200604231245475.html" target="_new">DB</a>3-42A1-B4CF-6A8B67A516C0}<BR>在{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}子项有个健,名称为UpperBindings,该健的健值是当前中间层驱动的MINIPORT设备名称,在我的系统中为如下健值:<BR>\Device\ {5BF5A311-13E4-4746-8865-339DDD6C73AF}</FONT></P>
<P><FONT face=Verdana>(2)中间层驱动</FONT></P>
<P><FONT face=Verdana> 在我们的函数NDIS_PROTOCOL_CHARACTERISTICS-> BindAdapterHandler()中,会调用一系列函数(如NdisOpenProtocolConfiguration、NdisReadConfiguration)来访问注册表,其实都是访问Parameters\Adapters\{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}子项。<BR> 注意,函数NDIS_PROTOCOL_CHARACTERISTICS-> BindAdapterHandler()的倒数第二个参数是SystemSpecific1,如果我们安装的是XPASSTHRU,则其具体指的是如下字符串:<BR> xfilter\Parameters\Adapters\{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}<BR> 其中xfilter 是XPASSTHRU的,而{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}在不同的系统中不同。<BR> 函数NdisOpenProtocolConfiguration()其实只是构造一个查询注册表的RTL_QUERY<BR>_REGISTRY_TABLE结构(该结构在利用函数RtlQueryRegistryValues()查询注册表是使用)。并将这个结构封装到NDIS_WRAPPER_CONFIGURATION_HANDLE结构中,然后作为NdisOpenProtocolConfiguration()的第二个参数返回。<BR> 其实NdisOpenProtocolConfiguration()构造的RTL_QUERY_REGISTRY_TABLE结构的含义也就是查询HKLM\SYSTEM\CurrentControlSet\Services\ xfilter\Parameters\Adapters\{<BR>102454C2-9DB3-42A1-B4CF-6A8B67A516C0}\下的健值(xfilter 会随着安装不同的中间层驱动而不同,{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}在不同的系统中不同,下面均省略这些注释)。<BR> 函数NdisReadConfiguration()有两个作用,它首先修改在函数NdisOpenProtocolConf<BR>iguration()构造的RTL_QUERY_REGISTRY_TABLE结构。也就是在查询HKLM\SYSTEM<BR>\CurrentControlSet\Services\ xfilter\Parameters\Adapters\{102454C2-9DB3-42A1-B4CF-6A8B6<BR>7A516C0}\的基础上加上了一个健,将其变成HKLM\SYSTEM\CurrentControlSet\Services\ xfilter\Parameters\Adapters\{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}\UpperBindings。然后函数NdisReadConfiguration()会调用函数RtlQueryRegistryValues()查询新构造的这个注册表,并将结果存储在调用函数NdisReadConfiguration()时的第二个参数中。在我的系统中,RtlQueryRegistryValues()读出的这个新构造的这个注册表的健值是:\Device\ {5BF5A311-13E4-4746-8865-339DDD6C73AF}(后面我们称为RESULT1),它其实是我们注册的中间层驱动(XPASSTHRU)的设备输出(其构造是\Device+\GUID)。<BR> 其实我们读出的这个中间层驱动(XPASSTHRU)的设备(即我们刚才读出的那个健值RESULT1)只在后面的函数NdisIMInitializeDeviceInstanceEx()中才用得着,并且RESULT1是作为函数NdisIMInitializeDeviceInstanceEx()的第二个参数的。<BR>这里有个地方让人感到迷惑,即在函数BindAdapterHandler()我们一旦调用了函数NdisOpenAdapter()绑定了一个下层的MINIPORT,为什么还要调用函数NdisIMInitializeDeviceInstanceEx()初始化我们中间层驱动自己的MINIPORT(因为函数NdisIMInitializeDeviceInstanceEx()的参数是RESULT1,而RESULT1代表我们中间层驱动的MINIPORT)。为了解释这个原因,我们先做如下假设。</FONT></P>
<P align=center><FONT face=Verdana><IMG src="200644134617325.gif" tppabs="http://www.itisedu.com/manage/Upload/image/200644134617325.gif" border=0></FONT></P>
<P><FONT face=Verdana> 我们假设我们系统安装了一个中间层驱动(假设为XPASSTRHU),在上图中,PROT-IM和MINIPORT-IM分别代表我们中间层驱动的协议驱动程序和小端口驱动程序,PROT-TCPIP代表真正的协议驱动程序,MINIPORT-NIC代表真是网卡的小端口驱动程序。<BR> 当PROT-TCPIP需要发送数据时,会调用函数NdisSend(),其实它会调用MINIPORT-IM中的发送数据函数,但是MINIPORT-IM和MINIPORT-NIC没联系,按照常规是不能发送数据到MINIPORT-NIC的。但是我们可以看到PROT-IM是可以和MINIPORT-NIC互相发送数据的,所以我们必须将MINIPORT-IM和PROT-IM联系起来。<BR> 另外当MINIPORT-NIC需要将数据提交给PROT-TCPIP时,只能首先将数据提交给PROT-IM,PROT-IM也只能通过MINIPORT-IM才能和PROT-TCPIP联系起来。<BR> 所以必须将PROT-IM和MINIPORT-IM联系起来。有人说这两个东西都是我们中间层驱动注册得,难道还联系不起来吗?不错,但是不管怎样你都得通过你得代码才能将他们联系起来呀!下面我们就介绍联系得方法。<BR> 我们以XPASSTHRU为例,在其函数ProtocolBindAdapter()中,先分配了一个ADAPT结构(这个结构是自己定义的,可根据用户的需要定义)。当调用函数ProtocolBindAdapter()调用函数NdisOpenAdapter()进行绑定时,是以&Adapt->BindingHandle作为函数NdisOpenAdapter()的第三个参数的,这样Adapt->BindingHandle就指向了NDIS_OPEN_BLOCK1(注意,调用函数NdisOpenAdapter()时的第三个参数会返回指向绑定以后的NDIS_OPEN_BLOCK指针)。然后函数ProtocolBindAdapter()会调用函数NdisIMInitializeDeviceInstanceEx(),该函数会进一步调用XPASSTHRU的NDIS_MINIPORT_CHARACTERISTICS->InitializeHandler()函数。上面我们讨论过,NdisIMInitializeDeviceInstanceEx()中的第二个参数就是XPASSTHRU注册的小端口驱动的设备实例(即上面的RESULT1)。在函数NdisIMInitializeDeviceInstanceEx()中会根据设备名称(RESULT1),找到对应的MINIPORT结构,并将其指针作为参数传递给NDIS_MINIPORT_CHARACTERISTICS->InitializeHandler()函数(以后简称InitializeHandler()函数)。在InitializeHandler()函数中,会进一步将MINIPORT结构指针赋值给ADAPT->MiniportHandle(ADAPT就是上面在函数ProtocolBindAdapter()中分配的那个结构)。<BR> 这样数据结构ADAPT中就含有了两个指针,一个指向NDIS_OPEN_BLOCK1,另一个指向MINIPORT-IM,而NDIS_OPEN_BLOCK1和PROT-IM是密切联系的,所以ADAPT就将PROT-IM和MINIPORT-IM紧密的联系起来了。<BR> 另外注意,NDIS_MINIPORT_BLOCK->DeviceContext是指向我们的ADAPT结构的,这个赋值在函数NdisIMInitializeDeviceInstanceEx()中完成。上面谈到了也是在函数NdisIMInitializeDeviceInstanceEx()中完成了从ADAPT-> MiniportHandle到MINIPORT的绑定,所以在函数NdisIMInitializeDeviceInstanceEx()中完成了ADAPT和MINIPORT的互相连接(即指针互相指向)。<BR>函数InitializeHandler()中可以利用句柄MINIPORT的句柄得到我们的ADAPT结构,具体实现这个功能的函数是NdisIMGetDeviceContext(),这个函数的参数是个NDIS_HANDLE<a href="200603051002565.html" tppabs="http://www.itisedu.com/phrase/200603051002565.html" target="_new">类型</a>,但是在该函数内部,会将这个参数转换成NDIS_MINIPORT_BLOCK结构,并返回NDIS_MINIPORT_BLOCK->DeviceContext。<BR>在函数NdisOpenAdapter()中,除了上面提到的完成了由Adapt->BindingHandle到NDIS_OPEN_BLOCK1的指向外,还完成了我们没有提到的由NDIS_OPEN_BLOCK1-> ProtocolBindingContext到ADAPT的指向,所以函数NdisOpenAdapter()完成了ADAPT和NDIS_OPEN_BLOCK1的互相连接(即指针互相指向)。<BR> 讲到这里,我们上图完善为下图:</FONT></P>
<P align=center><FONT face=Verdana><IMG src="200644134631868.gif" tppabs="http://www.itisedu.com/manage/Upload/image/200644134631868.gif" border=0></FONT></P>
<P><FONT face=Verdana> 下面大家也许就可以做一些HOOK了,例如对OPEN_BLOCK结构的HOOK,对ADAPT的HOOK等,这里就不作介绍了(作者:noble <NOBLE _shi @21cn.com>出处:http://www.nsfocus.com)</FONT></P></div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -