搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
你好赵伟
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
新魔百和M301H_关于CW代工_JL(南传)代工_zn及sm代工区分及鸿蒙架构全网通卡刷包刷机教程_m301h刷机
2
ajax请求报parsererror错误_ajax parsererror是什么错误
3
云端技术驾驭DAY15——ClusterIP服务、Ingress服务、Dashboard插件、k8s角色的认证与授权
4
kubeCon2020重磅演讲:基于k8s构建新一代私有云和容器云_captain k8s
5
HTML+CSS:3D轮播卡片
6
Python+医学院校二手书管理 毕业设计-附源码201704_基于python的校园二手交易平台论文开题报告
7
python函数递归求和详解_Python函数中多类型传值和冗余参数及函数的递归调用
8
【毕业设计】ASP.NET 网上选课系统的设计与实现(源代码+论文)_aspnet毕业设计含代码
9
Stable Diffusion提示词总结_stable diffusion 提示词详解
10
玩转k8s:Pod详解_k8s pod配置文件查看
当前位置:
article
> 正文
如何使用lsp的hook技术解决TCP链接超时测试场景的模拟
作者:你好赵伟 | 2024-02-28 17:11:31
赞
踩
netfilter hook 可以关tcp 吗skb->sk->sk_err == 超时
<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 <Ws2spi.h><br>// 定义了WSCWriteProviderOrder函数<br>#include <Sporder.h> <br>#include <windows.h><br>#include <stdio.h></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, &dwSize, &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, &dwSize, &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(&nProtocols);<br>BOOL bFindUdp = FALSE;<br>BOOL bFindTcp = FALSE;<br>BOOL bFindRaw = FALSE;<br>for(int i=0; i<nProtocols; i++)<br>{<br> if(pProtoInfo[i].iAddressFamily == AF_INET)<br> {<br> if(!bFindUdp && pProtoInfo[i].iProtocol == IPPROTO_UDP)<br> {<br> memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));<br> OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = <br> OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~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 && pProtoInfo[i].iProtocol == IPPROTO_TCP)<br> {<br> memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));<br> OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = <br> OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~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 && pProtoInfo[i].iProtocol == IPPROTO_IP)<br> {<br> memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));<br> OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = <br> OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~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(&LayeredProtocolInfo, &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(&ProviderGuid, <br> pwszPathName, &LayeredProtocolInfo, 1, &nError) == SOCKET_ERROR)<br>{<br> return FALSE;<br>}<br>// 重新枚举协议,获取分层协议的目录ID号<br>FreeProvider(pProtoInfo);<br>pProtoInfo = GetProvider(&nProtocols);<br>for(i=0; i<nProtocols; i++)<br>{<br> if(memcmp(&pProtoInfo[i].ProviderId, &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<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>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(&ProviderChainGuid) == RPC_S_OK)<br>{<br> if(::WSCInstallProvider(&ProviderChainGuid, <br> pwszPathName, OriginalProtocolInfo, nArrayCount, &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(&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<nProtocols; i++)<br>{<br> if((pProtoInfo[i].ProtocolChain.ChainLen > 1) &&<br> (pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId))<br> dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;<br>}<br>// 添加其它协议<br>for(i=0; i<nProtocols; i++)<br>{<br> if((pProtoInfo[i].ProtocolChain.ChainLen <= 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(&nProtocols);<br>int nError;<br>for(int i=0; i<nProtocols; i++)<br>{<br> if(memcmp(&ProviderGuid, &pProtoInfo[i].ProviderId, sizeof(ProviderGuid)) == 0)<br> {<br> dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId;<br> break;<br> }<br>}<br>if(i < nProtocols)<br>{<br> // 移除协议链<br> for(i=0; i<nProtocols; i++)<br> {<br> if((pProtoInfo[i].ProtocolChain.ChainLen > 1) &&<br> (pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId))<br> {<br> ::WSCDeinstallProvider(&pProtoInfo[i].ProviderId, &nError);<br> }<br> }<br> // 移除分层协议<br> ::WSCDeinstallProvider(&ProviderGuid, &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 <iostream.h><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, &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(&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<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 <Winsock2.h><br>#include <Ws2spi.h><br>#include <Windows.h><br>#include <tchar.h><br>#include "Debug.h"<br>#include <fstream.h></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, &dwSize, &nError) == SOCKET_ERROR)<br>{<br> if(nError != WSAENOBUFS)<br> return NULL;<br>}<br>pProtoInfo = (LPWSAPROTOCOL_INFOW)::GlobalAlloc(GPTR, dwSize);<br>*lpnTotalProtocols = ::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &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(要过滤的端口<为 int 类型>) ) // 若符合则过滤掉了</p>
<p>{<br> int iError;<br> g_NextProcTable.lpWSPShutdown(s, SD_BOTH, &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->ProtocolChain.ChainLen <= 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(&nTotalProtos);<br>// 下层入口ID <br>DWORD dwBaseEntryId = lpProtocolInfo->ProtocolChain.ChainEntries[1];<br>for(int i=0; i<nTotalProtos; i++)<br>{<br> if(pProtoInfo[i].dwCatalogEntryId == dwBaseEntryId)<br> {<br> memcpy(&NextProtocolInfo, &pProtoInfo[i], sizeof(NextProtocolInfo));<br> break;<br> }<br>}<br>if(i >= 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(&NextProtocolInfo.ProviderId, szBaseProviderDll, &nLen, &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 = &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->lpWSPSendTo = WSPSendTo;<br>lpProcTable->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, &p) 中的DLL文件就是它,<br> 以前调试的时候忘记看了,试了N次都没找出失误的原因 @_@ )<br></p>
</font></span></span>
<p></p>
</span></p>
<p></p>
声明:
本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:
https://www.wpsshop.cn/w/你好赵伟/article/detail/160420
推荐阅读
article
React
-
hook
-
form
-
mui
(一):基本
使用
...
本文及以下几篇文章,会从简到难讲解如何
使用
。希望通过这几篇文章的介绍,能够帮助你入门`react-
hook
-
form
-m...
赞
踩
article
黑客爱用的
HOOK
技术_
64
hook
调用
原函数
...
上面几种
HOOK
,修改的都是应用层的函数指针,而操作系统内核中还有一些非常重要的表格,它们的表项中记录了一些更加关键的...
赞
踩
article
v
c++
HOOK
API
黑客外挂编程必知必会...
#include // 定义
API
挂接项结构typedef struct _
HOOK
_ITEM { DWORD dwA...
赞
踩
article
黑客爱用
的
HOOK
技术
大揭秘_
irp
hook
...
病毒木马为何惨遭杀软拦截?商业软件为何频遭免费破解?系统漏洞为何能被补丁修复?这一切
的
背后到底是人性
的
扭曲,还是道德
的
沦...
赞
踩
article
Java
HOOK
-
钩子
机制扫盲_
jeecg
hook
是
干嘛的...
一、什么
是
HOOK
(
钩子
) 对于Windows系统,它
是
建立在事件驱动机制上的,说白了就
是
整个系统都
是
通过消息传递实...
赞
踩
article
Linux
上监控应用程序启动 (
hook
execve
系统调用)_
current
->
group
_le...
对于linuxx86-64平台,
hook
普通的系统调用是一件比较简单的事情,可以看
hook
系统调用完整实例讲解。但是对...
赞
踩
article
linux
进程
启动
hook
,
程序员
攻防实战:
linux
下
这样
隐藏
进程
,
简直太溜了,赶紧用起来.....
某些时候
程序员
为了不让其他人不小心或者恶意破坏掉你运行的程序
,
或者我们要做些“见不得光”的事情
,
就有
隐藏
进程
的需求
,
目的...
赞
踩
article
Linux
hook
技术一个简单
demo
分析_
linux
实现
plt
hook
...
hook
技术分享_
linux
实现
plt
hook
linux
实现
plt
hook
#includ...
赞
踩
相关标签
react.js
javascript
前端
php
服务器
安全
网络
智能路由器
hook
api
vc++
编程
winapi
descriptor
java
windows
开发语言
网络安全
HOOK
linux
kernel
hooks
linux 进程启动 hook
c++
c语言