LSP(分层服务提供者)
2019独角兽企业重金招聘Python工程师标准>>>
LSP本身是DLL,可以将它安装到winsock目录,以便创建套接字的应用程序不必知道此LSP的任何信息就能调用它。
运行原理:
套接字创建函数会在winsock目录中寻找合适的协议
调用此协议,的提供者导出的函数 完成各种功能。
编写目的:
让用户调用自定义的服务提供者,有自定义的服务提供者调用下层提供者。这样便截获所有的winsock调用了。
服务提供者本身是DLL,导出一些与winsock API相对应的SPI函数。winsock库加载服务提供者时,便依靠这些函数来实现winsockAPI。
LSP也是如此,它向上导出所有的SPI函数供 Ws2_32.dll调用,在内部通过调用基础提供者实现这些SPI。
安装LSP:
实现LSP之前,要先将分层提供者安装到winsock目录,安装包括一个WSAPPROTOCOL_INFOW结构,定义了分层提供者的特性和LSP填写链的方式。(也叫做协议入口)
协议链:
协议链描述了 分层提供者 加入winsock的目录的顺序。
typedef struct _WSAPROTOCOLCHAIN{int ChainLen;DWORD ChainEntries[Max_PROTOCOL_CHAN];
}WSAPROTOCOLCHAIN,*LPWSAPROTOCOLCHAIN;
ChainLen为0:分层协议 为1 基础协议 大于1 协议链
当ChainLen为0或者1时,ChainEntries数组无意义
大于1时,各个服务提供者的目录ID就包含在数组中。
实现LSP的DLL要么被另一个LSP加载,要么直接被WS2_32.DLL加载。取决于它的位置。
如果LSP没有在协议链的顶端,就会被链中位于它上层的LSP加载,否则的话,将被WS2_32.DLL加载。
安装LSP时,必须在winsock目录中安装两种协议:一个分层协议,一个协议链。
安装分层协议视为了获取winsock库分配的目录ID号,一边在协议链中标识自己的位置。
协议链才是winsock目录中LSP的真正入口,连中包含了自己分层协议的目录ID号和下层提供者的目录ID号。
在安装时,要先安装一个分层协议,用系统分配给此分层协议的目录ID和下层提供者的目录ID构建一个 ChainEntries数组,进而构建一个WSAPROTOCOL_INFOW结构,然后再安装这个协议链。
安装函数:
提供LSP GUID DLL WSAPROTOCOL_INFOW结构便可。
int WSCInstallProvider(
const LPGUID lpProviderId,
const LPWSTR lpszProviderDllPath,
const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
DWORD dwNumberOfEntries,
LPINT lpErrno
);
每一个安装提供者需要一个GUID来标识它的入口,GUID可以通过命令行工具UUIDGEN或者在编程使用UuidCreate函数来生成。
LSP的WSAPROTOCOL_INFOW结构通常从它要分层的下层提供者拷贝
1 szProtocol域要修改,以包含新提供者的名称
2 如果包含XP1_IFS_HANDLES标识,要从dwServiceFlags1域移除。
重新目录排序 WSCWriteProviderOrder
新安装的LSP会默认安装到winsock目录的结尾,这样系统调用的时候,还是会调用原先调用的LSP,因此只有进行重新的排序才能让系统调用到新安装的LSP。
总结:
1 安装分层协议入口,以便获取系统分配的目录ID号。
2 安装一个或者多个协议链,安装的数量取决于要分层的下层协议的数量。
3 在结尾进行目录排序。
示例代码:
////
// InstDemo.cpp
#include <Ws2spi.h>
#include <Sporder.h> // 定义了WSCWriteProviderOrder函数
#include <windows.h>
#include <stdio.h>#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "Rpcrt4.lib") // 实现了UuidCreate函数// 要安装的LSP的硬编码,在移除的时候还要使用它
GUID ProviderGuid = {0xd3c21122, 0x85e1, 0x48f3, {0x9a,0xb6,0x23,0xd9,0x0c,0x73,0x07,0xef}};LPWSAPROTOCOL_INFOW GetProvider(LPINT lpnTotalProtocols)
{DWORD dwSize = 0;int nError;LPWSAPROTOCOL_INFOW pProtoInfo = NULL;// 取得需要的长度if(::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError) == SOCKET_ERROR){if(nError != WSAENOBUFS)return NULL;}pProtoInfo = (LPWSAPROTOCOL_INFOW)::GlobalAlloc(GPTR, dwSize);*lpnTotalProtocols = ::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError);return pProtoInfo;
}void FreeProvider(LPWSAPROTOCOL_INFOW pProtoInfo)
{::GlobalFree(pProtoInfo);
}// 将LSP安装到UDP协议提供者之上
int InstallProvider(WCHAR *wszDllPath)
{WCHAR wszLSPName[] = L"TinyLSP"; // 我们的LSP的名称int nError = NO_ERROR;LPWSAPROTOCOL_INFOW pProtoInfo;int nProtocols;WSAPROTOCOL_INFOW UDPLayeredInfo, UDPChainInfo; // 我们要安装的UDP分层协议和协议链
DWORD dwUdpOrigCatalogId, dwLayeredCatalogId;// 在Winsock目录中找到原来的UDP协议服务提供者,我们的LSP要安装在它之上// 枚举所有服务程序提供者pProtoInfo = GetProvider(&nProtocols);for(int i=0; i<nProtocols; i++){if(pProtoInfo[i].iAddressFamily == AF_INET && pProtoInfo[i].iProtocol == IPPROTO_UDP){memcpy(&UDPChainInfo, &pProtoInfo[i], sizeof(UDPLayeredInfo));// UDPChainInfo.dwServiceFlags1 = UDPChainInfo.dwServiceFlags1 & ~XP1_IFS_HANDLES; // 保存原来的入口IDdwUdpOrigCatalogId = pProtoInfo[i].dwCatalogEntryId;break;}} // 首先安装分层协议,获取一个Winsock库安排的目录ID号,即dwLayeredCatalogId// 直接使用下层协议的WSAPROTOCOL_INFOW结构即可memcpy(&UDPLayeredInfo, &UDPChainInfo, sizeof(UDPLayeredInfo));// 修改协议名称,类型,设置PFL_HIDDEN标志
wcscpy(UDPLayeredInfo.szProtocol, wszLSPName);UDPLayeredInfo.ProtocolChain.ChainLen = LAYERED_PROTOCOL; // LAYERED_PROTOCOL即0UDPLayeredInfo.dwProviderFlags |= PFL_HIDDEN;// 安装if(::WSCInstallProvider(&ProviderGuid, wszDllPath, &UDPLayeredInfo, 1, &nError) == SOCKET_ERROR)return nError;// 重新枚举协议,获取分层协议的目录ID号
FreeProvider(pProtoInfo);pProtoInfo = GetProvider(&nProtocols);for(i=0; i<nProtocols; i++){if(memcmp(&pProtoInfo[i].ProviderId, &ProviderGuid, sizeof(ProviderGuid)) == 0){dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId;break;}}// 安装协议链// 修改协议名称,类型WCHAR wszChainName[WSAPROTOCOL_LEN + 1];swprintf(wszChainName, L"%ws over %ws", wszLSPName, UDPChainInfo.szProtocol);wcscpy(UDPChainInfo.szProtocol, wszChainName);if(UDPChainInfo.ProtocolChain.ChainLen == 1){UDPChainInfo.ProtocolChain.ChainEntries[1] = dwUdpOrigCatalogId;}else{for(i=UDPChainInfo.ProtocolChain.ChainLen; i>0 ; i--){UDPChainInfo.ProtocolChain.ChainEntries[i] = UDPChainInfo.ProtocolChain.ChainEntries[i-1];}}UDPChainInfo.ProtocolChain.ChainLen ++;// 将我们的分层协议置于此协议链的顶层UDPChainInfo.ProtocolChain.ChainEntries[0] = dwLayeredCatalogId; // 获取一个Guid,安装之
GUID ProviderChainGuid;if(::UuidCreate(&ProviderChainGuid) == RPC_S_OK){if(::WSCInstallProvider(&ProviderChainGuid, wszDllPath, &UDPChainInfo, 1, &nError) == SOCKET_ERROR)return nError;}elsereturn GetLastError();// 重新排序Winsock目录,将我们的协议链提前// 重新枚举安装的协议
FreeProvider(pProtoInfo);pProtoInfo = GetProvider(&nProtocols);DWORD dwIds[20];int nIndex = 0;// 添加我们的协议链for(i=0; i<nProtocols; i++){if((pProtoInfo[i].ProtocolChain.ChainLen > 1) &&(pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId))dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;}// 添加其它协议for(i=0; i<nProtocols; i++){if((pProtoInfo[i].ProtocolChain.ChainLen <= 1) ||(pProtoInfo[i].ProtocolChain.ChainEntries[0] != dwLayeredCatalogId))dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;}// 重新排序Winsock目录nError = ::WSCWriteProviderOrder(dwIds, nIndex);FreeProvider(pProtoInfo);return nError;
}void RemoveProvider()
{ LPWSAPROTOCOL_INFOW pProtoInfo;int nProtocols;DWORD dwLayeredCatalogId;// 根据Guid取得分层协议的目录ID号pProtoInfo = GetProvider(&nProtocols);int nError;for(int i=0; i<nProtocols; i++){if(memcmp(&ProviderGuid, &pProtoInfo[i].ProviderId, sizeof(ProviderGuid)) == 0){dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId;break;}}if(i < nProtocols){// 移除协议链for(i=0; i<nProtocols; i++){if((pProtoInfo[i].ProtocolChain.ChainLen > 1) &&(pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId)){::WSCDeinstallProvider(&pProtoInfo[i].ProviderId, &nError);}}// 移除分层协议::WSCDeinstallProvider(&ProviderGuid, &nError);}
}////int binstall = 0;
void main()
{if(binstall){if(InstallProvider(L"lsp.dll") == ERROR_SUCCESS){printf(" Install successully \n");}else{printf(" Install failed \n");}}elseRemoveProvider();
}
转载于:https://my.oschina.net/u/204616/blog/545523
LSP(分层服务提供者)相关推荐
- 网络封包过滤之分层服务提供者(LSP)
分层服务提供者(LSP)(1) 开发过滤数据包的LSP程序可以定义过滤规则,恩,先看看 LSP本身是DLL,可以将它安装至Winsock目录,创建套接字的应用程序不必知道此LSP的任何信息就能调用它 ...
- 网络编程之编写LSP进行Winsock API监控拦截或LSP注入
[1]工具介绍: 用到的工具:VS2015 语言:C/C++ 需要系统提供的动态链接库:1. sporder.dll //很多系统不自带着个dll,导致编译时缺少dll无法编译. (发布时必须将此dl ...
- 网络编程之Winsock2 服务提供者接口(SPI)
[1]Winsock2 服务提供者接口(SPI): 一.简述: 1.一般用于提供给操作系统开发商.传输堆栈商在基础协议的基础上,开发更高级的服务. 2.因为Winsock服务体系符合Windows开放 ...
- 什么是LSP???如何看待LSP???
LSP: layered service privider 分层服务提供商. LSP是TCP/IP等协议的接口. 浏览器,聊天工具等等都要通过这个接口来获取相应的信息. 删除不正确的(也称为&qu ...
- 探索“迅游加速器(LSP)”DLL的大致原理
本人并未在"迅游加速器"有个任何从业经历,与迅游相关的,仅仅只是对"加速器原理"有一些相关的研究但也就仅此而已,你想想我这一个搞"dotNET&quo ...
- Windows Server 2012 中删除或弃用的功能
Features Removed or Deprecated in Windows Server 2012 | Microsoft Docshttps://docs.microsoft.com/en- ...
- vmware workstation虚拟机开机一直黑屏解决方案
vmware workstation虚拟机开机黑屏处理办法 Windows安装虚拟机的时候发现虚拟机开机一直黑屏, 错误原因:可能是由LSP引起的 LSP(分层服务提供程序): LSP即分层服务提供商 ...
- 基于SPI的数据报过滤原理与实现
基于SPI的数据报过滤原理与实现 作者: TOo2y 一)个人防火墙技术概述 随着网络安全问题日益严重,广大用户对网络安全产品也越来越关注.防火墙作为一种网络安全工具,早已受到大家的青睐.在PC机上使 ...
- 网络协议笔记-数据链路层
[数据链路层的基本概念] 数据链路层中数据传输的单位是帧(frame) 链路是一条无源的点到点的物理线路段. 数据链路除了物理线路外,还必须有通信协议来控制这些数据的传输,若把实现这些协议的硬件和软件 ...
最新文章
- android获取图片缩略图,Android系获取图片和视频的缩略图
- java 部分类_为什么微软部分类和Java不?
- static class 静态类(Java)
- js学习总结----编写简单的ajax方法库
- 使用MetalLB在您的Raspberry Pi家庭实验室上安装Kubernetes负载均衡器
- [转]setTimeout() 函数未定义错误
- 孙鑫-MFC笔记四--文本编程
- VS2010中配置OpenGL的一些问题小结
- 3dsMax中Vray渲染器法线贴图用法
- theano java_Windows Theano GPU 版配置
- 1005打印任务取消不了 hp_hp打印机无法取消打印的文档解决方法(最新整理)
- linux 7 查看网卡配置文件,如何查询centos网卡配置文件
- 这些才是Win10真正好用之处:瞬对Win7无爱
- Minecraft mod制作简易教程目录
- 机器学习_正态分布下的贝叶斯分类器
- 0成本截流的三种方法,挣钱从引流开始
- 华为麒麟9000性能提升幅度大,但恐难成安卓一哥
- UE4(虚幻4)做一个双开平移自动门+双开旋转门+使用相对坐标
- 操作系统概念v9 Abraham Silberschatz 全文笔记
- jeecg微服务项目调用接口报错Token验证失效的解决方法
热门文章
- 记录 之 整形数除整形数 产生的数据依然是整形,难搞哦
- xhtml的行内描述性元素
- mysql 创建视图的时候语法易错点
- [BUUCTF-pwn]——hgame2018_flag_server
- java获取web.xml 参数_解析web.xml中在Servlet中获取context-param和init-param内的参数
- 将台式机组成云服务器_云桌面是什么?用了两年云桌面的真实感受
- iBatis resultMap出错 The error happened while setting a property on the result object 解决办法
- OpenEjb使用笔记--让Tomcat可以部署EJB
- Eclipse配置C++时的三个关键环境变量
- mock 测试 MVC