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; }