• VC++基于LSP拦截数据封包


    LSP即分层服务提供商,Winsock 作为应用程序的 Windows 的网络套接字工具,可以由称为“分层服务提供商”的机制进行扩展。

    Winsock LSP 可用于非常广泛的实用用途,包括 Internet 家长控制 (parental control) 和 Web 内容筛选。在以前版本的 Windows XP 中,删除不正确的(也称为“buggy”)LSP 可能会导致注册表中的 Winsock 目录损坏,潜在地导致所有网络连接的丢失。
    LSP(Layered Service Provider )  中文名为分层服务提供程序。 LSP就是TCP/IP等协议的接口.LSP用在正途上可以方便程序员们编写监视系统网络通讯情况的Sniffer,可是现在常见的LSP都被用于浏览器劫持.

     LSP安装卸载代码如下

    //////////////////////////////////////////////////////////////
    // InstLSP.cpp文件
    
    // 包含了安装LSP的代码
    
    // InstallProvider(WCHAR *pwszPathName) 将指定LSP提供者安装到TCP UDP 和原始套节字之上
    // RemoveProvider()						移除InstallProvider函数安装的LSP
    
    #define UNICODE
    #define _UNICODE
    
    #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);
    }
    
    BOOL InstallProvider(WCHAR *pwszPathName)
    {
    	WCHAR wszLSPName[] = L"PhoenixLSP";
    	LPWSAPROTOCOL_INFOW pProtoInfo;
    	int nProtocols;
    	WSAPROTOCOL_INFOW OriginalProtocolInfo[3];
    	DWORD			 dwOrigCatalogId[3];
    	int nArrayCount = 0;
    
    	DWORD dwLayeredCatalogId;		// 我们分层协议的目录ID号
    
    	int nError;
    	
    		// 找到我们的下层协议,将信息放入数组中
    	// 枚举所有服务程序提供者
    	pProtoInfo = GetProvider(&nProtocols);
    	BOOL bFindUdp = FALSE;
    	BOOL bFindTcp = FALSE;
    	BOOL bFindRaw = FALSE;
    	for(int i=0; i<nProtocols; i++)
    	{
    		if(pProtoInfo[i].iAddressFamily == AF_INET)
    		{
    		if(!bFindUdp && pProtoInfo[i].iProtocol == IPPROTO_UDP)
    			{
    				memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
    				OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = 
    					OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES); 
    				
    				dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
    
    				bFindUdp = TRUE;
    			}
    
    		if(!bFindTcp && pProtoInfo[i].iProtocol == IPPROTO_TCP)
    			{
    				memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
    				OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = 
    					OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES); 
    				
    				dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
    
    				bFindTcp = TRUE;
    			} 
    		if(!bFindRaw && pProtoInfo[i].iProtocol == IPPROTO_IP)
    			{
    				memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
    				OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = 
    					OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES); 
    				
    				dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
    
    				bFindRaw = TRUE;
    			}
    		}
    	}  
    
    		// 安装我们的分层协议,获取一个dwLayeredCatalogId
    	// 随便找一个下层协议的结构复制过来即可
    	WSAPROTOCOL_INFOW LayeredProtocolInfo;
    	memcpy(&LayeredProtocolInfo, &OriginalProtocolInfo[0], sizeof(WSAPROTOCOL_INFOW));
    	// 修改协议名称,类型,设置PFL_HIDDEN标志
    	wcscpy(LayeredProtocolInfo.szProtocol, wszLSPName);
    	LayeredProtocolInfo.ProtocolChain.ChainLen = LAYERED_PROTOCOL; // 0;
    	LayeredProtocolInfo.dwProviderFlags |= PFL_HIDDEN;
    	// 安装
    	if(::WSCInstallProvider(&ProviderGuid, 
    					pwszPathName, &LayeredProtocolInfo, 1, &nError) == SOCKET_ERROR)
    	{
    		return FALSE;
    	}
    	// 重新枚举协议,获取分层协议的目录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];
    	for(i=0; i<nArrayCount; i++)
    	{
    		swprintf(wszChainName, L"%ws over %ws", wszLSPName, OriginalProtocolInfo[i].szProtocol);
    		wcscpy(OriginalProtocolInfo[i].szProtocol, wszChainName);
    		if(OriginalProtocolInfo[i].ProtocolChain.ChainLen == 1)
    		{
    			OriginalProtocolInfo[i].ProtocolChain.ChainEntries[1] = dwOrigCatalogId[i];
    		}
    		else
    		{
    			for(int j = OriginalProtocolInfo[i].ProtocolChain.ChainLen; j>0; j--)
    			{
    				OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j] 
    									= OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j-1];
    			}
    		}
    		OriginalProtocolInfo[i].ProtocolChain.ChainLen ++;
    		OriginalProtocolInfo[i].ProtocolChain.ChainEntries[0] = dwLayeredCatalogId;	
    	}
    	// 获取一个Guid,安装之
    	GUID ProviderChainGuid;
    	if(::UuidCreate(&ProviderChainGuid) == RPC_S_OK)
    	{
    		if(::WSCInstallProvider(&ProviderChainGuid, 
    					pwszPathName, OriginalProtocolInfo, nArrayCount, &nError) == SOCKET_ERROR)
    		{
    			return FALSE;	
    		}
    	}
    	else
    		return FALSE;
    
    			// 重新排序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目录
    	if((nError = ::WSCWriteProviderOrder(dwIds, nIndex)) != ERROR_SUCCESS)
    	{
    		return FALSE;
    	}
    	FreeProvider(pProtoInfo);
    
    	return TRUE;
    }
    
    BOOL 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);
    	}
    
    	return TRUE;
    }
    
    
    void main(int argc, char *argv[])
    {
    	if(argc==2)
    	{
    		if(strcmp(argv[1], "-install")==0)   
    		{
    			TCHAR szPathName[256];
    			TCHAR* p;
    
    			if(::GetFullPathName(L"LSP.dll", 256, szPathName, &p) != 0)
    			{
    				if(InstallProvider(szPathName))
    				{
    					printf(" Install successully. \n");
    					return;
    				}
    			}
    			printf(" Install failed. \n");
    			return;
    		}
    		else if(strcmp(argv[1],"-remove")==0)  
    		{
    			if(RemoveProvider())
    				printf(" Deinstall successully. \n");
    			else
    				printf(" Deinstall failed. \n");
    			return;
    		}
    	}
    	
    	printf(" Usage: Instlsp [ -install │ -remove ] \n");
    }
    


     

     LSP实现代码如下

    //////////////////////////////////////////////////
    // LSP.cpp文件
    
    
    // 声明要使用UNICODE字符串
    #define UNICODE
    #define _UNICODE
    
    #include <Winsock2.h>
    #include <Ws2spi.h>
    #include <Windows.h>
    #include <tchar.h>
    #include "Debug.h"
    
    #pragma comment(lib, "Ws2_32.lib")
    
    
    
    WSPUPCALLTABLE g_pUpCallTable;		// 上层函数列表。如果LSP创建了自己的伪句柄,才使用这个函数列表
    WSPPROC_TABLE g_NextProcTable;		// 下层函数列表
    TCHAR	g_szCurrentApp[MAX_PATH];	// 当前调用本DLL的程序的名称
    
    
    BOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved
    					 )
    {
    	switch (ul_reason_for_call)
    	{
    	case DLL_PROCESS_ATTACH:
    		{
    			// 取得主模块的名称
    			::GetModuleFileName(NULL, g_szCurrentApp, MAX_PATH);
    		}
    		break;
    	}
    	return TRUE;
    }
    
    
    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);
    }
    
    
    
    int WSPAPI WSPSendTo(
    	SOCKET			s,
    	LPWSABUF		lpBuffers,
    	DWORD			dwBufferCount,
    	LPDWORD			lpNumberOfBytesSent,
    	DWORD			dwFlags,
    	const struct sockaddr FAR * lpTo,
    	int				iTolen,
    	LPWSAOVERLAPPED	lpOverlapped,
    	LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
    	LPWSATHREADID	lpThreadId,
    	LPINT			lpErrno
    )
    {
    	ODS1(L" query send to... %s", g_szCurrentApp);
    
    	// 拒绝所有目的端口为4567的UDP封包
    	SOCKADDR_IN sa = *(SOCKADDR_IN*)lpTo;
    	if(sa.sin_port == htons(4567))
    	{
    		int	iError;
    		g_NextProcTable.lpWSPShutdown(s, SD_BOTH, &iError);
    		*lpErrno = WSAECONNABORTED;
    
    		ODS(L" deny a sendto ");
    		return SOCKET_ERROR;
    	}
    
    	return g_NextProcTable.lpWSPSendTo(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo
    			, iTolen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
    
    }
    
    
    int WSPAPI WSPStartup(
      WORD wVersionRequested,
      LPWSPDATA lpWSPData,
      LPWSAPROTOCOL_INFO lpProtocolInfo,
      WSPUPCALLTABLE UpcallTable,
      LPWSPPROC_TABLE lpProcTable
    )
    {
    	ODS1(L"  WSPStartup...  %s \n", g_szCurrentApp);
    	
    	if(lpProtocolInfo->ProtocolChain.ChainLen <= 1)
    	{	
    		return WSAEPROVIDERFAILEDINIT;
    	}
    	
    	// 保存向上调用的函数表指针(这里我们不使用它)
    	g_pUpCallTable = UpcallTable;
    
    	// 枚举协议,找到下层协议的WSAPROTOCOL_INFOW结构	
    	WSAPROTOCOL_INFOW	NextProtocolInfo;
    	int nTotalProtos;
    	LPWSAPROTOCOL_INFOW pProtoInfo = GetProvider(&nTotalProtos);
    	// 下层入口ID	
    	DWORD dwBaseEntryId = lpProtocolInfo->ProtocolChain.ChainEntries[1];
    	for(int i=0; i<nTotalProtos; i++)
    	{
    		if(pProtoInfo[i].dwCatalogEntryId == dwBaseEntryId)
    		{
    			memcpy(&NextProtocolInfo, &pProtoInfo[i], sizeof(NextProtocolInfo));
    			break;
    		}
    	}
    	if(i >= nTotalProtos)
    	{
    		ODS(L" WSPStartup:	Can not find underlying protocol \n");
    		return WSAEPROVIDERFAILEDINIT;
    	}
    
    	// 加载下层协议的DLL
    	int nError;
    	TCHAR szBaseProviderDll[MAX_PATH];
    	int nLen = MAX_PATH;
    	// 取得下层提供程序DLL路径
    	if(::WSCGetProviderPath(&NextProtocolInfo.ProviderId, szBaseProviderDll, &nLen, &nError) == SOCKET_ERROR)
    	{
    		ODS1(L" WSPStartup: WSCGetProviderPath() failed %d \n", nError);
    		return WSAEPROVIDERFAILEDINIT;
    	}
    	if(!::ExpandEnvironmentStrings(szBaseProviderDll, szBaseProviderDll, MAX_PATH))
    	{
    		ODS1(L" WSPStartup:  ExpandEnvironmentStrings() failed %d \n", ::GetLastError());
    		return WSAEPROVIDERFAILEDINIT;
    	}
    	// 加载下层提供程序
    	HMODULE hModule = ::LoadLibrary(szBaseProviderDll);
    	if(hModule == NULL)
    	{
    		ODS1(L" WSPStartup:  LoadLibrary() failed %d \n", ::GetLastError());
    		return WSAEPROVIDERFAILEDINIT;
    	}
    
    	// 导入下层提供程序的WSPStartup函数
    	LPWSPSTARTUP  pfnWSPStartup = NULL;
    	pfnWSPStartup = (LPWSPSTARTUP)::GetProcAddress(hModule, "WSPStartup");
    	if(pfnWSPStartup == NULL)
    	{
    		ODS1(L" WSPStartup:  GetProcAddress() failed %d \n", ::GetLastError());
    		return WSAEPROVIDERFAILEDINIT;
    	}
    
    	// 调用下层提供程序的WSPStartup函数
    	LPWSAPROTOCOL_INFOW pInfo = lpProtocolInfo;
    	if(NextProtocolInfo.ProtocolChain.ChainLen == BASE_PROTOCOL)
    		pInfo = &NextProtocolInfo;
    
    	int nRet = pfnWSPStartup(wVersionRequested, lpWSPData, pInfo, UpcallTable, lpProcTable);
    	if(nRet != ERROR_SUCCESS)
    	{
    		ODS1(L" WSPStartup:  underlying provider's WSPStartup() failed %d \n", nRet);
    		return nRet;
    	}
    
    	// 保存下层提供者的函数表
    	g_NextProcTable = *lpProcTable;
    
    	// 修改传递给上层的函数表,Hook感兴趣的函数,这里做为示例,仅Hook了WSPSendTo函数
    	// 您还可以Hook其它函数,如WSPSocket、WSPCloseSocket、WSPConnect等
    	lpProcTable->lpWSPSendTo = WSPSendTo;
    
    	FreeProvider(pProtoInfo);
    	return nRet;
    }
    
    
    
    
    


     

  • 相关阅读:
    Promise.all和Promise.race区别,和使用场景
    使用Promise解决多层异步调用的简单学习【转】
    前端性能优化-缓存
    Node.js机制及原理理解初步【转】
    微信小程序 canvas 字体自动换行(支持换行符)
    百度地图-鼠标悬停样式
    文件I/O相关函数
    获取系统限制信息
    标准C头文件
    数据库系统小结:(不包括详细知识点,更像一个大纲)
  • 原文地址:https://www.cnblogs.com/new0801/p/6177713.html
Copyright © 2020-2023  润新知