`
linkyou66
  • 浏览: 228118 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

如何使用lsp的hook技术解决TCP链接超时测试场景的模拟

 
阅读更多
<p><span style="font-size: medium;">问题:在测试网络层链接建立工具的时候,遇到这样的测试用例:需要模拟不同链接按预定的链接先后次序建立,如TCP链接先于UDP链接或者UDP链接先于TCP链接。查用了很多防火墙,都没有提供类似的功能。后来我们使用了<span style="font-size: small;">WinsockLSP 开发了小工具解决了这个问题!</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">关于WinSock LSP网上有详细的例子和讲解如下:</span></span></p>
<p><span style="font-size: medium;"></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">LSP :分层服务提供者,顾名思义是某种服务的提供者且具有分层的特性,它是 WinSock2 的特性吧,与以往的 WinSock1.0 不同,WinSock1.0 仅围绕着TCP/IP协议运行的,但是在Winsock2中却增加了对更多传输协议的支持。“Winsock2不仅提供了一个供应用程序访问网络服务的Windowssocket应用程序编程接口(API),还包含了由传输服务提供者和名字解析服务提供者实现的Winsock服务提供者接口(SPI)和ws2_32.dll。”。就现在 NT 以后的网络而言(不知道Vista及后的了),应用层EXE创建套接字时,会先在 WinSock 目录中寻找全适的协议(如 TCP、UDP ......),找到之后再调用此协议的 提供者 来完成各种功能,其中 提供者 又是通过 SPI函数 来完成任务的。所以,对于这种类型的网络调用而言, LSP 是主题而其中的 SPI 则是灵魂,没有 SPI 的话 LSP 就只是一个框架而已,LSP大概的层次如图 :</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">---------------------------------<br>│ Windows socket 2 EXE│<br>---------------------------------Windows socket 2 API<br>│ WS2_32.DLL │<br>---------------------------------Windows socket 2 传输SPI<br>│ LSP DLL │ <br>-----------------------------------<br>│ 基础服务提供程序 │ <br>----------------------------------</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;"> 现在可以知道几乎所有的 WinSock API 调用都会先告诉 WS2_32.DLL ,再由 WS2_32.DLL 传达给 LSP (类型转换的那些不是,不知道还有没有......-_-!),最后到 基础服务提供程序 全权代理实现。所以,大多数的 WinSock API 都是可以 HOOK 的,前提是要安装了 LSP ,由 SPI 进行 HOOK。</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;"> 上图中已示意了 LSP 其实是 DLL 的形式,它是不可以直接执行的,得由 EXE 程序来安装,所以在想采用 LSP 来过滤封包,还得先编译个可执行程序来安装这,至于这个安装 LSP 的程序很多时候都是一个固定的框架:枚举 LSP、安装 LSP、卸载 LSP ,在实现的时候,我用了一个头文件来实现这个框架(本想用类来封装的~~~):</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">LSPIn-Unstall.h</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">#define UNICODE<br>#define _UNICODE</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">#include &lt;Ws2spi.h&gt;<br>// 定义了WSCWriteProviderOrder函数<br>#include &lt;Sporder.h&gt; <br>#include &lt;windows.h&gt;<br>#include &lt;stdio.h&gt;</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">#pragma comment(lib, "Ws2_32.lib")<br>// 实现了UuidCreate函数<br>#pragma comment(lib, "Rpcrt4.lib")</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">// 要安装的LSP的硬编码,在移除的时候还要使用它<br>GUID ProviderGuid = {0x8a, 0x88b, 0x888c, <br> {0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a}};</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">//获得所有已经安装的传输服务提供者<br>LPWSAPROTOCOL_INFOW GetProvider(LPINT lpnTotalProtocols)<br>{<br>DWORD dwSize = 0;<br>int nError;<br>LPWSAPROTOCOL_INFOW pProtoInfo = NULL;</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">// 取得需要的长度<br>if(::WSCEnumProtocols(NULL, pProtoInfo, &amp;dwSize, &amp;nError) == SOCKET_ERROR)<br>{<br> if(nError != WSAENOBUFS)<br> return NULL;<br>}</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">pProtoInfo = (LPWSAPROTOCOL_INFOW)::GlobalAlloc(GPTR, dwSize);<br>*lpnTotalProtocols = ::WSCEnumProtocols(NULL, pProtoInfo, &amp;dwSize, &amp;nError);<br>return pProtoInfo;<br>}<br>//释放存储空间<br>void FreeProvider(LPWSAPROTOCOL_INFOW pProtoInfo)<br>{<br>::GlobalFree(pProtoInfo);<br>}<br>//安装分层协议,协议链及排序<br>//这里将指定LSP提供者安装到TCP UDP 和原始套节字之上<br>BOOL InstallProvider(WCHAR *pwszPathName)<br>{<br>//LSP的名字<br>WCHAR wszLSPName[] = L"MyFirstLSP";<br>LPWSAPROTOCOL_INFOW pProtoInfo;<br>int nProtocols;<br>WSAPROTOCOL_INFOW OriginalProtocolInfo[3];<br>DWORD dwOrigCatalogId[3];<br>int nArrayCount = 0;</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">// 我们分层协议的目录ID号<br>DWORD dwLayeredCatalogId; </span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">int nError;</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">// 找到我们的下层协议,将信息放入数组中<br>// 枚举所有服务程序提供者<br>pProtoInfo = GetProvider(&amp;nProtocols);<br>BOOL bFindUdp = FALSE;<br>BOOL bFindTcp = FALSE;<br>BOOL bFindRaw = FALSE;<br>for(int i=0; i&lt;nProtocols; i++)<br>{<br> if(pProtoInfo[i].iAddressFamily == AF_INET)<br> {<br> if(!bFindUdp &amp;&amp; pProtoInfo[i].iProtocol == IPPROTO_UDP)<br> {<br> memcpy(&amp;OriginalProtocolInfo[nArrayCount], &amp;pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));<br> OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = <br> OriginalProtocolInfo[nArrayCount].dwServiceFlags1 &amp; (~XP1_IFS_HANDLES); <br><br> dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;"> bFindUdp = TRUE;<br> }</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;"> if(!bFindTcp &amp;&amp; pProtoInfo[i].iProtocol == IPPROTO_TCP)<br> {<br> memcpy(&amp;OriginalProtocolInfo[nArrayCount], &amp;pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));<br> OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = <br> OriginalProtocolInfo[nArrayCount].dwServiceFlags1 &amp; (~XP1_IFS_HANDLES); <br><br> dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;"> bFindTcp = TRUE;<br> } <br> if(!bFindRaw &amp;&amp; pProtoInfo[i].iProtocol == IPPROTO_IP)<br> {<br> memcpy(&amp;OriginalProtocolInfo[nArrayCount], &amp;pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));<br> OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = <br> OriginalProtocolInfo[nArrayCount].dwServiceFlags1 &amp; (~XP1_IFS_HANDLES); <br><br> dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;"> bFindRaw = TRUE;<br> }<br> }<br>}</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">// 安装我们的分层协议,获取一个dwLayeredCatalogId<br>// 随便找一个下层协议的结构复制过来即可<br>WSAPROTOCOL_INFOW LayeredProtocolInfo;<br>memcpy(&amp;LayeredProtocolInfo, &amp;OriginalProtocolInfo[0], sizeof(WSAPROTOCOL_INFOW));<br>// 修改协议名称,类型,设置PFL_HIDDEN标志<br>wcscpy(LayeredProtocolInfo.szProtocol, wszLSPName);<br>LayeredProtocolInfo.ProtocolChain.ChainLen = LAYERED_PROTOCOL; // 0;<br>LayeredProtocolInfo.dwProviderFlags |= PFL_HIDDEN;<br>// 安装<br>if(::WSCInstallProvider(&amp;ProviderGuid, <br> pwszPathName, &amp;LayeredProtocolInfo, 1, &amp;nError) == SOCKET_ERROR)<br>{<br> return FALSE;<br>}<br>// 重新枚举协议,获取分层协议的目录ID号<br>FreeProvider(pProtoInfo);<br>pProtoInfo = GetProvider(&amp;nProtocols);<br>for(i=0; i&lt;nProtocols; i++)<br>{<br> if(memcmp(&amp;pProtoInfo[i].ProviderId, &amp;ProviderGuid, sizeof(ProviderGuid)) == 0)<br> {<br> dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId;<br> break;<br> }<br>}</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">// 安装协议链<br>// 修改协议名称,类型<br>WCHAR wszChainName[WSAPROTOCOL_LEN + 1];<br>for(i=0; i&lt;nArrayCount; i++)<br>{<br> swprintf(wszChainName, L"%ws over %ws", wszLSPName, OriginalProtocolInfo[i].szProtocol);<br> wcscpy(OriginalProtocolInfo[i].szProtocol, wszChainName);<br> if(OriginalProtocolInfo[i].ProtocolChain.ChainLen == 1)<br> {<br> OriginalProtocolInfo[i].ProtocolChain.ChainEntries[1] = dwOrigCatalogId[i];<br> }<br> else<br> {<br> for(int j = OriginalProtocolInfo[i].ProtocolChain.ChainLen; j&gt;0; j--)<br> {<br> OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j] <br> = OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j-1];<br> }<br> }<br> OriginalProtocolInfo[i].ProtocolChain.ChainLen ++;<br> OriginalProtocolInfo[i].ProtocolChain.ChainEntries[0] = dwLayeredCatalogId; <br>}<br>// 获取一个Guid,安装之<br>GUID ProviderChainGuid;<br>if(::UuidCreate(&amp;ProviderChainGuid) == RPC_S_OK)<br>{<br> if(::WSCInstallProvider(&amp;ProviderChainGuid, <br> pwszPathName, OriginalProtocolInfo, nArrayCount, &amp;nError) == SOCKET_ERROR)<br> {<br> return FALSE; <br> }<br>}<br>else<br> return FALSE;</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">// 重新排序Winsock目录,将我们的协议链提前<br>// 重新枚举安装的协议<br>FreeProvider(pProtoInfo);<br>pProtoInfo = GetProvider(&amp;nProtocols);</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">DWORD dwIds[20];<br>int nIndex = 0;<br>// 添加我们的协议链<br>for(i=0; i&lt;nProtocols; i++)<br>{<br> if((pProtoInfo[i].ProtocolChain.ChainLen &gt; 1) &amp;&amp;<br> (pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId))<br> dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;<br>}<br>// 添加其它协议<br>for(i=0; i&lt;nProtocols; i++)<br>{<br> if((pProtoInfo[i].ProtocolChain.ChainLen &lt;= 1) ||<br> (pProtoInfo[i].ProtocolChain.ChainEntries[0] != dwLayeredCatalogId))<br> dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;<br>}<br>// 重新排序Winsock目录<br>if((nError = ::WSCWriteProviderOrder(dwIds, nIndex)) != ERROR_SUCCESS)<br>{<br> return FALSE;<br>}<br>FreeProvider(pProtoInfo);<br>return TRUE;<br>}<br>//卸载分层协议和协议链<br>BOOL RemoveProvider()<br>{<br>LPWSAPROTOCOL_INFOW pProtoInfo;<br>int nProtocols;<br>DWORD dwLayeredCatalogId;</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">// 根据Guid取得分层协议的目录ID号<br>pProtoInfo = GetProvider(&amp;nProtocols);<br>int nError;<br>for(int i=0; i&lt;nProtocols; i++)<br>{<br> if(memcmp(&amp;ProviderGuid, &amp;pProtoInfo[i].ProviderId, sizeof(ProviderGuid)) == 0)<br> {<br> dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId;<br> break;<br> }<br>}<br>if(i &lt; nProtocols)<br>{<br> // 移除协议链<br> for(i=0; i&lt;nProtocols; i++)<br> {<br> if((pProtoInfo[i].ProtocolChain.ChainLen &gt; 1) &amp;&amp;<br> (pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId))<br> {<br> ::WSCDeinstallProvider(&amp;pProtoInfo[i].ProviderId, &amp;nError);<br> }<br> }<br> // 移除分层协议<br> ::WSCDeinstallProvider(&amp;ProviderGuid, &amp;nError);<br>}<br>return TRUE;<br>}</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;"> 接着就是主函数的调用了:</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">LSPControl.cpp</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">#include &lt;iostream.h&gt;<br>#include "LSPIn-Unstall.h"</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">//安装LSP<br>void install();<br>//卸载LSP<br>void remove();<br>//查看已安装了的LSP<br>void view();</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">void main()<br>{<br>//命令参数<br>char order[128];</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">while(1)<br>{<br> cin.getline(order,128);<br> if(strcmp(order,"exit")==0)<br> break;<br> else if(strcmp(order,"install")==0)<br> install();<br> else if(strcmp(order,"remove")==0)<br> remove();<br> else if(strcmp(order,"view")==0)<br> view();<br>}<br>}<br>//安装LSP<br>void install()<br>{<br>TCHAR szPathName[256];<br>TCHAR* p;</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">//LSP所在的路径<br>if(::GetFullPathName(L"MyFirstLSP.dll", 256, szPathName, &amp;p) != 0)<br>{<br> if(InstallProvider(szPathName))<br> {<br> printf(" ^-^ 安装成功!/n");<br> return;<br> }<br>}<br>printf(" o_o! 安装失败!/n");<br>}<br>//卸载LSP<br>void remove()<br>{<br>if(RemoveProvider())<br> printf(" ^-^ 卸载成功!/n");<br>else<br> printf(" o_o! 卸载失败!/n");<br>}<br>//查看已安装了的LSP<br>void view()<br>{<br>LPWSAPROTOCOL_INFOW pProtoInfo;<br>int nProtocols;<br>pProtoInfo = GetProvider(&amp;nProtocols);</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">printf("/n --------------------------- 已安装的LSP --------------------------- /n/n");<br>for(int i=0; i&lt;nProtocols; i++)<br>{<br> printf(" Protocol: %ws /n", pProtoInfo[i].szProtocol);<br> printf(" CatalogEntryId: %d ChainLen: %d /n/n", pProtoInfo[i].dwCatalogEntryId, pProtoInfo[i].ProtocolChain.ChainLen);<br>}<br>printf("/n --------------------------- 已安装的LSP --------------------------- /n/n");<br>}</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;"> 看起来是很繁琐,实际上也就是一些框架,已经实现了查看(view)、安装(install)、卸载(remove)。</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;"> 有了可以操控 LSP 程序,接下来就是生成 LSP 了,LSP 以DLL的形式来实现的,这里用的是 VC++6.0 的动态链接工程,在建立好该工程后,还要在工程里头导入一个 .def 格式的文件,其中有导出 LSP WSPStarUP 函数的 EXPORTS 语句,之后就是编写代码了。LSP 只是提供了一个接口,有些代码跟上面的一样看似繁,实则是一个框架,了解就OK了(汗,说到繁,NDIS 更让人头晕```),下面的代码中,最后的 WSPSendTo()、WSPBind() 函数的定义就是 SPI 了,累了那么久,就是用到这些 SPI 来进行包过滤(甚至是实现防火墙等):</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">Debug.h</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">#ifndef __DEBUG_H__<br>#define __DEBUG_H__<br>#ifdef _DEBUG</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">#define ODS(szOut) /<br>{ /<br> OutputDebugString(szOut); /<br>}</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">#define ODS1(szOut, var) /<br>{ /<br> TCHAR sz[1024]; /<br> _stprintf(sz, szOut, var); /<br> OutputDebugString(sz); /<br>}</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">#else</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">#define ODS(szOut)<br>#define ODS1(szOut, var)</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">#endif</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">#endif</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">LSP.cpp</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">// --- 声明要使用UNICODE字符串---(到了驱动的话,大都是用 UNICODE 的)<br>#define UNICODE<br>#define _UNICODE</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">#include &lt;Winsock2.h&gt;<br>#include &lt;Ws2spi.h&gt;<br>#include &lt;Windows.h&gt;<br>#include &lt;tchar.h&gt;<br>#include "Debug.h"<br>#include &lt;fstream.h&gt;</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">#pragma comment(lib, "Ws2_32.lib")</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">WSPUPCALLTABLE g_pUpCallTable; // 上层函数列表。如果LSP创建了自己的伪句柄,才使用这个函数列表<br>WSPPROC_TABLE g_NextProcTable; // 下层函数列表<br>TCHAR g_szCurrentApp[MAX_PATH]; // 当前调用本DLL的程序的名称</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">BOOL APIENTRY DllMain( HANDLE hModule, <br> DWORD ul_reason_for_call, <br> LPVOID lpReserved<br> )<br>{<br>switch (ul_reason_for_call)<br>{<br>case DLL_PROCESS_ATTACH:<br> {<br> // 取得主模块的名称<br> ::GetModuleFileName(NULL, g_szCurrentApp, MAX_PATH);<br> }<br> break;<br>}<br>return TRUE;<br>}<br>//得到当前所有已安装的LSP<br>LPWSAPROTOCOL_INFOW GetProvider(LPINT lpnTotalProtocols)<br>{<br>DWORD dwSize = 0;<br>int nError;<br>LPWSAPROTOCOL_INFOW pProtoInfo = NULL;</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">// 取得需要的长度<br>if(::WSCEnumProtocols(NULL, pProtoInfo, &amp;dwSize, &amp;nError) == SOCKET_ERROR)<br>{<br> if(nError != WSAENOBUFS)<br> return NULL;<br>}<br>pProtoInfo = (LPWSAPROTOCOL_INFOW)::GlobalAlloc(GPTR, dwSize);<br>*lpnTotalProtocols = ::WSCEnumProtocols(NULL, pProtoInfo, &amp;dwSize, &amp;nError);<br>return pProtoInfo;<br>}<br>//释放空间<br>void FreeProvider(LPWSAPROTOCOL_INFOW pProtoInfo)<br>{<br>::GlobalFree(pProtoInfo);<br>}</span></span></p>
<p><span style="font-size: medium;"><span style="font-size: small;">
<p><br>int WSPAPI WSPSendTo(<br>SOCKET s,<br>LPWSABUF lpBuffers,<br>DWORD dwBufferCount,<br>LPDWORD lpNumberOfBytesSent,<br>DWORD dwFlags,<br>const struct sockaddr FAR * lpTo,<br>int iTolen,<br>LPWSAOVERLAPPED lpOverlapped,<br>LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,<br>LPWSATHREADID lpThreadId,<br>LPINT lpErrno<br>)<br>{<br>ODS1(L" query send to... %s", g_szCurrentApp);</p>
<p>SOCKADDR_IN sa = *(SOCKADDR_IN*)lpTo;<br>if(sa.sin_port == htons(要过滤的端口&lt;为 int 类型&gt;) ) // 若符合则过滤掉了</p>
<p>{<br> int iError;<br> g_NextProcTable.lpWSPShutdown(s, SD_BOTH, &amp;iError);<br> *lpErrno = WSAECONNABORTED;</p>
<p> ODS(L" deny a sendto ");<br> return SOCKET_ERROR;<br>}</p>
<p><br>return g_NextProcTable.lpWSPSendTo(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo<br> , iTolen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);<br>}</p>
<p>int WSPAPI WSPBind(SOCKET s, const struct sockaddr* name, int namelen, LPINT lpErrno)<br>{<br>//这里再进行处理(一般情况之下,Bind 都是作为服务程序用的函数:绑定端口后再进而监听)<br>return g_NextProcTable.lpWSPBind(s, name, namelen, lpErrno);<br>}</p>
<p>//这里为入口函数(必备)<br>int WSPAPI WSPStartup(<br>WORD wVersionRequested,<br>LPWSPDATA lpWSPData,<br>LPWSAPROTOCOL_INFO lpProtocolInfo,<br>WSPUPCALLTABLE UpcallTable,<br>LPWSPPROC_TABLE lpProcTable<br>)<br>{<br>ODS1(L" WSPStartup... %s /n", g_szCurrentApp);</p>
<p>if(lpProtocolInfo-&gt;ProtocolChain.ChainLen &lt;= 1)<br>{ <br> return WSAEPROVIDERFAILEDINIT;<br>}</p>
<p>// 保存向上调用的函数表指针(在这里没有使用它)<br>g_pUpCallTable = UpcallTable;</p>
<p>// 枚举协议,找到下层协议的WSAPROTOCOL_INFOW结构 <br>WSAPROTOCOL_INFOW NextProtocolInfo;<br>int nTotalProtos;<br>LPWSAPROTOCOL_INFOW pProtoInfo = GetProvider(&amp;nTotalProtos);<br>// 下层入口ID <br>DWORD dwBaseEntryId = lpProtocolInfo-&gt;ProtocolChain.ChainEntries[1];<br>for(int i=0; i&lt;nTotalProtos; i++)<br>{<br> if(pProtoInfo[i].dwCatalogEntryId == dwBaseEntryId)<br> {<br> memcpy(&amp;NextProtocolInfo, &amp;pProtoInfo[i], sizeof(NextProtocolInfo));<br> break;<br> }<br>}<br>if(i &gt;= nTotalProtos)<br>{<br> ODS(L" WSPStartup: Can not find underlying protocol /n");<br> return WSAEPROVIDERFAILEDINIT;<br>}</p>
<p>// 加载下层协议的DLL<br>int nError;<br>TCHAR szBaseProviderDll[MAX_PATH];<br>int nLen = MAX_PATH;<br>// 取得下层提供程序DLL路径<br>if(::WSCGetProviderPath(&amp;NextProtocolInfo.ProviderId, szBaseProviderDll, &amp;nLen, &amp;nError) == SOCKET_ERROR)<br>{<br> ODS1(L" WSPStartup: WSCGetProviderPath() failed %d /n", nError);<br> return WSAEPROVIDERFAILEDINIT;<br>}<br>if(!::ExpandEnvironmentStrings(szBaseProviderDll, szBaseProviderDll, MAX_PATH))<br>{<br> ODS1(L" WSPStartup: ExpandEnvironmentStrings() failed %d /n", ::GetLastError());<br> return WSAEPROVIDERFAILEDINIT;<br>}<br>// 加载下层提供程序<br>HMODULE hModule = ::LoadLibrary(szBaseProviderDll);<br>if(hModule == NULL)<br>{<br> ODS1(L" WSPStartup: LoadLibrary() failed %d /n", ::GetLastError());<br> return WSAEPROVIDERFAILEDINIT;<br>}</p>
<p>// 导入下层提供程序的WSPStartup函数<br>LPWSPSTARTUP pfnWSPStartup = NULL;<br>pfnWSPStartup = (LPWSPSTARTUP)::GetProcAddress(hModule, "WSPStartup");<br>if(pfnWSPStartup == NULL)<br>{<br> ODS1(L" WSPStartup: GetProcAddress() failed %d /n", ::GetLastError());<br> return WSAEPROVIDERFAILEDINIT;<br>}</p>
<p>// 调用下层提供程序的WSPStartup函数<br>LPWSAPROTOCOL_INFOW pInfo = lpProtocolInfo;<br>if(NextProtocolInfo.ProtocolChain.ChainLen == BASE_PROTOCOL)<br> pInfo = &amp;NextProtocolInfo;</p>
<p>int nRet = pfnWSPStartup(wVersionRequested, lpWSPData, pInfo, UpcallTable, lpProcTable);<br>if(nRet != ERROR_SUCCESS)<br>{<br> ODS1(L" WSPStartup: underlying provider's WSPStartup() failed %d /n", nRet);<br> return nRet;<br>}<br>// 保存下层提供者的函数表<br>g_NextProcTable = *lpProcTable;<br>// 修改传递给上层的函数表,Hook感兴趣的函数<br>// 好像可以 Hook 30个函数,书里头写着列表有 30 个ISP函数<br>lpProcTable-&gt;lpWSPSendTo = WSPSendTo;<br>lpProcTable-&gt;lpWSPBind = WSPBind;</p>
<p>FreeProvider(pProtoInfo);<br>return nRet;<br>}</p>
<p> 一个防火墙的模型就出来了,不过在用户模式下它虽然不错,但是并非能够过滤所有的封包,除非编写内核模式的 NDIS 驱动(强捍的NDIS)~~~</p>
<span style="font-size: medium;"><font size="3">
<p> 编译成 DLL 后,将上面生成的操作 LSP 的程序与 生成的 DLL 放在同一目录之下,DLL 的由字要是 MyFirstLSP (因为上面:GetFullPathName(L"MyFirstLSP.dll", 256, szPathName, &amp;p) 中的DLL文件就是它,<br> 以前调试的时候忘记看了,试了N次都没找出失误的原因 @_@ )<br></p>
</font></span></span>
<p></p>
</span></p>
<p></p>
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics