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

来源:互联网 发布:直播间送礼物 知乎 编辑:程序博客网 时间:2024/05/21 07:03

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

分类: VC++编程技术 Visual C++2010编程技术 661人阅读 评论(1) 收藏 举报
vc++socketnullhookpathsockets

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安装卸载代码如下

[cpp] view plaincopyprint?
  1. //////////////////////////////////////////////////////////////  
  2. // InstLSP.cpp文件  
  3.   
  4. // 包含了安装LSP的代码  
  5.   
  6. // InstallProvider(WCHAR *pwszPathName) 将指定LSP提供者安装到TCP UDP 和原始套节字之上  
  7. // RemoveProvider()                     移除InstallProvider函数安装的LSP  
  8.   
  9. #define UNICODE  
  10. #define _UNICODE  
  11.   
  12. #include <Ws2spi.h>  
  13. #include <Sporder.h>      // 定义了WSCWriteProviderOrder函数  
  14.   
  15. #include <windows.h>  
  16. #include <stdio.h>  
  17.   
  18. #pragma comment(lib, "Ws2_32.lib")  
  19. #pragma comment(lib, "Rpcrt4.lib")  // 实现了UuidCreate函数  
  20.   
  21.   
  22. // 要安装的LSP的硬编码,在移除的时候还要使用它  
  23. GUID  ProviderGuid = {0xd3c21122, 0x85e1, 0x48f3,   
  24.                             {0x9a,0xb6,0x23,0xd9,0x0c,0x73,0x07,0xef}};  
  25.   
  26.   
  27.   
  28. LPWSAPROTOCOL_INFOW GetProvider(LPINT lpnTotalProtocols)  
  29. {  
  30.     DWORD dwSize = 0;  
  31.     int nError;  
  32.     LPWSAPROTOCOL_INFOW pProtoInfo = NULL;  
  33.       
  34.     // 取得需要的长度  
  35.     if(::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError) == SOCKET_ERROR)  
  36.     {  
  37.         if(nError != WSAENOBUFS)  
  38.             return NULL;  
  39.     }  
  40.       
  41.     pProtoInfo = (LPWSAPROTOCOL_INFOW)::GlobalAlloc(GPTR, dwSize);  
  42.     *lpnTotalProtocols = ::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError);  
  43.     return pProtoInfo;  
  44. }  
  45.   
  46. void FreeProvider(LPWSAPROTOCOL_INFOW pProtoInfo)  
  47. {  
  48.     ::GlobalFree(pProtoInfo);  
  49. }  
  50.   
  51. BOOL InstallProvider(WCHAR *pwszPathName)  
  52. {  
  53.     WCHAR wszLSPName[] = L"PhoenixLSP";  
  54.     LPWSAPROTOCOL_INFOW pProtoInfo;  
  55.     int nProtocols;  
  56.     WSAPROTOCOL_INFOW OriginalProtocolInfo[3];  
  57.     DWORD            dwOrigCatalogId[3];  
  58.     int nArrayCount = 0;  
  59.   
  60.     DWORD dwLayeredCatalogId;       // 我们分层协议的目录ID号  
  61.   
  62.     int nError;  
  63.       
  64.         // 找到我们的下层协议,将信息放入数组中  
  65.     // 枚举所有服务程序提供者  
  66.     pProtoInfo = GetProvider(&nProtocols);  
  67.     BOOL bFindUdp = FALSE;  
  68.     BOOL bFindTcp = FALSE;  
  69.     BOOL bFindRaw = FALSE;  
  70.     for(int i=0; i<nProtocols; i++)  
  71.     {  
  72.         if(pProtoInfo[i].iAddressFamily == AF_INET)  
  73.         {  
  74.         if(!bFindUdp && pProtoInfo[i].iProtocol == IPPROTO_UDP)  
  75.             {  
  76.                 memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));  
  77.                 OriginalProtocolInfo[nArrayCount].dwServiceFlags1 =   
  78.                     OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);   
  79.                   
  80.                 dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;  
  81.   
  82.                 bFindUdp = TRUE;  
  83.             }  
  84.   
  85.         if(!bFindTcp && pProtoInfo[i].iProtocol == IPPROTO_TCP)  
  86.             {  
  87.                 memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));  
  88.                 OriginalProtocolInfo[nArrayCount].dwServiceFlags1 =   
  89.                     OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);   
  90.                   
  91.                 dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;  
  92.   
  93.                 bFindTcp = TRUE;  
  94.             }   
  95.         if(!bFindRaw && pProtoInfo[i].iProtocol == IPPROTO_IP)  
  96.             {  
  97.                 memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));  
  98.                 OriginalProtocolInfo[nArrayCount].dwServiceFlags1 =   
  99.                     OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);   
  100.                   
  101.                 dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;  
  102.   
  103.                 bFindRaw = TRUE;  
  104.             }  
  105.         }  
  106.     }    
  107.   
  108.         // 安装我们的分层协议,获取一个dwLayeredCatalogId  
  109.     // 随便找一个下层协议的结构复制过来即可  
  110.     WSAPROTOCOL_INFOW LayeredProtocolInfo;  
  111.     memcpy(&LayeredProtocolInfo, &OriginalProtocolInfo[0], sizeof(WSAPROTOCOL_INFOW));  
  112.     // 修改协议名称,类型,设置PFL_HIDDEN标志  
  113.     wcscpy(LayeredProtocolInfo.szProtocol, wszLSPName);  
  114.     LayeredProtocolInfo.ProtocolChain.ChainLen = LAYERED_PROTOCOL; // 0;  
  115.     LayeredProtocolInfo.dwProviderFlags |= PFL_HIDDEN;  
  116.     // 安装  
  117.     if(::WSCInstallProvider(&ProviderGuid,   
  118.                     pwszPathName, &LayeredProtocolInfo, 1, &nError) == SOCKET_ERROR)  
  119.     {  
  120.         return FALSE;  
  121.     }  
  122.     // 重新枚举协议,获取分层协议的目录ID号  
  123.     FreeProvider(pProtoInfo);  
  124.     pProtoInfo = GetProvider(&nProtocols);  
  125.     for(i=0; i<nProtocols; i++)  
  126.     {  
  127.         if(memcmp(&pProtoInfo[i].ProviderId, &ProviderGuid, sizeof(ProviderGuid)) == 0)  
  128.         {  
  129.             dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId;  
  130.             break;  
  131.         }  
  132.     }  
  133.   
  134.             // 安装协议链  
  135.     // 修改协议名称,类型  
  136.     WCHAR wszChainName[WSAPROTOCOL_LEN + 1];  
  137.     for(i=0; i<nArrayCount; i++)  
  138.     {  
  139.         swprintf(wszChainName, L"%ws over %ws", wszLSPName, OriginalProtocolInfo[i].szProtocol);  
  140.         wcscpy(OriginalProtocolInfo[i].szProtocol, wszChainName);  
  141.         if(OriginalProtocolInfo[i].ProtocolChain.ChainLen == 1)  
  142.         {  
  143.             OriginalProtocolInfo[i].ProtocolChain.ChainEntries[1] = dwOrigCatalogId[i];  
  144.         }  
  145.         else  
  146.         {  
  147.             for(int j = OriginalProtocolInfo[i].ProtocolChain.ChainLen; j>0; j--)  
  148.             {  
  149.                 OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j]   
  150.                                     = OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j-1];  
  151.             }  
  152.         }  
  153.         OriginalProtocolInfo[i].ProtocolChain.ChainLen ++;  
  154.         OriginalProtocolInfo[i].ProtocolChain.ChainEntries[0] = dwLayeredCatalogId;   
  155.     }  
  156.     // 获取一个Guid,安装之  
  157.     GUID ProviderChainGuid;  
  158.     if(::UuidCreate(&ProviderChainGuid) == RPC_S_OK)  
  159.     {  
  160.         if(::WSCInstallProvider(&ProviderChainGuid,   
  161.                     pwszPathName, OriginalProtocolInfo, nArrayCount, &nError) == SOCKET_ERROR)  
  162.         {  
  163.             return FALSE;     
  164.         }  
  165.     }  
  166.     else  
  167.         return FALSE;  
  168.   
  169.             // 重新排序Winsock目录,将我们的协议链提前  
  170.     // 重新枚举安装的协议  
  171.     FreeProvider(pProtoInfo);  
  172.     pProtoInfo = GetProvider(&nProtocols);  
  173.   
  174.     DWORD dwIds[20];  
  175.     int nIndex = 0;  
  176.     // 添加我们的协议链  
  177.     for(i=0; i<nProtocols; i++)  
  178.     {  
  179.         if((pProtoInfo[i].ProtocolChain.ChainLen > 1) &&  
  180.                     (pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId))  
  181.             dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;  
  182.     }  
  183.     // 添加其它协议  
  184.     for(i=0; i<nProtocols; i++)  
  185.     {  
  186.         if((pProtoInfo[i].ProtocolChain.ChainLen <= 1) ||  
  187.                 (pProtoInfo[i].ProtocolChain.ChainEntries[0] != dwLayeredCatalogId))  
  188.             dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;  
  189.     }  
  190.     // 重新排序Winsock目录  
  191.     if((nError = ::WSCWriteProviderOrder(dwIds, nIndex)) != ERROR_SUCCESS)  
  192.     {  
  193.         return FALSE;  
  194.     }  
  195.     FreeProvider(pProtoInfo);  
  196.   
  197.     return TRUE;  
  198. }  
  199.   
  200. BOOL RemoveProvider()  
  201. {  
  202.     LPWSAPROTOCOL_INFOW pProtoInfo;  
  203.     int nProtocols;  
  204.     DWORD dwLayeredCatalogId;  
  205.   
  206.     // 根据Guid取得分层协议的目录ID号  
  207.     pProtoInfo = GetProvider(&nProtocols);  
  208.     int nError;  
  209.     for(int i=0; i<nProtocols; i++)  
  210.     {  
  211.         if(memcmp(&ProviderGuid, &pProtoInfo[i].ProviderId, sizeof(ProviderGuid)) == 0)  
  212.         {  
  213.             dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId;  
  214.             break;  
  215.         }  
  216.     }  
  217.   
  218.     if(i < nProtocols)  
  219.     {  
  220.         // 移除协议链  
  221.         for(i=0; i<nProtocols; i++)  
  222.         {  
  223.             if((pProtoInfo[i].ProtocolChain.ChainLen > 1) &&  
  224.                     (pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId))  
  225.             {  
  226.                 ::WSCDeinstallProvider(&pProtoInfo[i].ProviderId, &nError);  
  227.             }  
  228.         }  
  229.         // 移除分层协议  
  230.         ::WSCDeinstallProvider(&ProviderGuid, &nError);  
  231.     }  
  232.   
  233.     return TRUE;  
  234. }  
  235.   
  236.   
  237. void main(int argc, char *argv[])  
  238. {  
  239.     if(argc==2)  
  240.     {  
  241.         if(strcmp(argv[1], "-install")==0)     
  242.         {  
  243.             TCHAR szPathName[256];  
  244.             TCHAR* p;  
  245.   
  246.             if(::GetFullPathName(L"LSP.dll", 256, szPathName, &p) != 0)  
  247.             {  
  248.                 if(InstallProvider(szPathName))  
  249.                 {  
  250.                     printf(" Install successully. \n");  
  251.                     return;  
  252.                 }  
  253.             }  
  254.             printf(" Install failed. \n");  
  255.             return;  
  256.         }  
  257.         else if(strcmp(argv[1],"-remove")==0)    
  258.         {  
  259.             if(RemoveProvider())  
  260.                 printf(" Deinstall successully. \n");  
  261.             else  
  262.                 printf(" Deinstall failed. \n");  
  263.             return;  
  264.         }  
  265.     }  
  266.       
  267.     printf(" Usage: Instlsp [ -install │ -remove ] \n");  
  268. }  


 

 LSP实现代码如下

[cpp] view plaincopyprint?
  1. //////////////////////////////////////////////////  
  2. // LSP.cpp文件  
  3.   
  4.   
  5. // 声明要使用UNICODE字符串  
  6. #define UNICODE  
  7. #define _UNICODE  
  8.   
  9. #include <Winsock2.h>  
  10. #include <Ws2spi.h>  
  11. #include <Windows.h>  
  12. #include <tchar.h>  
  13. #include "Debug.h"  
  14.   
  15. #pragma comment(lib, "Ws2_32.lib")  
  16.   
  17.   
  18.   
  19. WSPUPCALLTABLE g_pUpCallTable;      // 上层函数列表。如果LSP创建了自己的伪句柄,才使用这个函数列表  
  20. WSPPROC_TABLE g_NextProcTable;      // 下层函数列表  
  21. TCHAR   g_szCurrentApp[MAX_PATH];   // 当前调用本DLL的程序的名称  
  22.   
  23.   
  24. BOOL APIENTRY DllMain( HANDLE hModule,   
  25.                        DWORD  ul_reason_for_call,   
  26.                        LPVOID lpReserved  
  27.                      )  
  28. {  
  29.     switch (ul_reason_for_call)  
  30.     {  
  31.     case DLL_PROCESS_ATTACH:  
  32.         {  
  33.             // 取得主模块的名称  
  34.             ::GetModuleFileName(NULL, g_szCurrentApp, MAX_PATH);  
  35.         }  
  36.         break;  
  37.     }  
  38.     return TRUE;  
  39. }  
  40.   
  41.   
  42. LPWSAPROTOCOL_INFOW GetProvider(LPINT lpnTotalProtocols)  
  43. {  
  44.     DWORD dwSize = 0;  
  45.     int nError;  
  46.     LPWSAPROTOCOL_INFOW pProtoInfo = NULL;  
  47.       
  48.     // 取得需要的长度  
  49.     if(::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError) == SOCKET_ERROR)  
  50.     {  
  51.         if(nError != WSAENOBUFS)  
  52.             return NULL;  
  53.     }  
  54.       
  55.     pProtoInfo = (LPWSAPROTOCOL_INFOW)::GlobalAlloc(GPTR, dwSize);  
  56.     *lpnTotalProtocols = ::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError);  
  57.     return pProtoInfo;  
  58. }  
  59.   
  60. void FreeProvider(LPWSAPROTOCOL_INFOW pProtoInfo)  
  61. {  
  62.     ::GlobalFree(pProtoInfo);  
  63. }  
  64.   
  65.   
  66.   
  67. int WSPAPI WSPSendTo(  
  68.     SOCKET          s,  
  69.     LPWSABUF        lpBuffers,  
  70.     DWORD           dwBufferCount,  
  71.     LPDWORD         lpNumberOfBytesSent,  
  72.     DWORD           dwFlags,  
  73.     const struct sockaddr FAR * lpTo,  
  74.     int             iTolen,  
  75.     LPWSAOVERLAPPED lpOverlapped,  
  76.     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,  
  77.     LPWSATHREADID   lpThreadId,  
  78.     LPINT           lpErrno  
  79. )  
  80. {  
  81.     ODS1(L" query send to... %s", g_szCurrentApp);  
  82.   
  83.     // 拒绝所有目的端口为4567的UDP封包  
  84.     SOCKADDR_IN sa = *(SOCKADDR_IN*)lpTo;  
  85.     if(sa.sin_port == htons(4567))  
  86.     {  
  87.         int iError;  
  88.         g_NextProcTable.lpWSPShutdown(s, SD_BOTH, &iError);  
  89.         *lpErrno = WSAECONNABORTED;  
  90.   
  91.         ODS(L" deny a sendto ");  
  92.         return SOCKET_ERROR;  
  93.     }  
  94.   
  95.     return g_NextProcTable.lpWSPSendTo(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo  
  96.             , iTolen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);  
  97.   
  98. }  
  99.   
  100.   
  101. int WSPAPI WSPStartup(  
  102.   WORD wVersionRequested,  
  103.   LPWSPDATA lpWSPData,  
  104.   LPWSAPROTOCOL_INFO lpProtocolInfo,  
  105.   WSPUPCALLTABLE UpcallTable,  
  106.   LPWSPPROC_TABLE lpProcTable  
  107. )  
  108. {  
  109.     ODS1(L"  WSPStartup...  %s \n", g_szCurrentApp);  
  110.       
  111.     if(lpProtocolInfo->ProtocolChain.ChainLen <= 1)  
  112.     {     
  113.         return WSAEPROVIDERFAILEDINIT;  
  114.     }  
  115.       
  116.     // 保存向上调用的函数表指针(这里我们不使用它)  
  117.     g_pUpCallTable = UpcallTable;  
  118.   
  119.     // 枚举协议,找到下层协议的WSAPROTOCOL_INFOW结构    
  120.     WSAPROTOCOL_INFOW   NextProtocolInfo;  
  121.     int nTotalProtos;  
  122.     LPWSAPROTOCOL_INFOW pProtoInfo = GetProvider(&nTotalProtos);  
  123.     // 下层入口ID     
  124.     DWORD dwBaseEntryId = lpProtocolInfo->ProtocolChain.ChainEntries[1];  
  125.     for(int i=0; i<nTotalProtos; i++)  
  126.     {  
  127.         if(pProtoInfo[i].dwCatalogEntryId == dwBaseEntryId)  
  128.         {  
  129.             memcpy(&NextProtocolInfo, &pProtoInfo[i], sizeof(NextProtocolInfo));  
  130.             break;  
  131.         }  
  132.     }  
  133.     if(i >= nTotalProtos)  
  134.     {  
  135.         ODS(L" WSPStartup:  Can not find underlying protocol \n");  
  136.         return WSAEPROVIDERFAILEDINIT;  
  137.     }  
  138.   
  139.     // 加载下层协议的DLL  
  140.     int nError;  
  141.     TCHAR szBaseProviderDll[MAX_PATH];  
  142.     int nLen = MAX_PATH;  
  143.     // 取得下层提供程序DLL路径  
  144.     if(::WSCGetProviderPath(&NextProtocolInfo.ProviderId, szBaseProviderDll, &nLen, &nError) == SOCKET_ERROR)  
  145.     {  
  146.         ODS1(L" WSPStartup: WSCGetProviderPath() failed %d \n", nError);  
  147.         return WSAEPROVIDERFAILEDINIT;  
  148.     }  
  149.     if(!::ExpandEnvironmentStrings(szBaseProviderDll, szBaseProviderDll, MAX_PATH))  
  150.     {  
  151.         ODS1(L" WSPStartup:  ExpandEnvironmentStrings() failed %d \n", ::GetLastError());  
  152.         return WSAEPROVIDERFAILEDINIT;  
  153.     }  
  154.     // 加载下层提供程序  
  155.     HMODULE hModule = ::LoadLibrary(szBaseProviderDll);  
  156.     if(hModule == NULL)  
  157.     {  
  158.         ODS1(L" WSPStartup:  LoadLibrary() failed %d \n", ::GetLastError());  
  159.         return WSAEPROVIDERFAILEDINIT;  
  160.     }  
  161.   
  162.     // 导入下层提供程序的WSPStartup函数  
  163.     LPWSPSTARTUP  pfnWSPStartup = NULL;  
  164.     pfnWSPStartup = (LPWSPSTARTUP)::GetProcAddress(hModule, "WSPStartup");  
  165.     if(pfnWSPStartup == NULL)  
  166.     {  
  167.         ODS1(L" WSPStartup:  GetProcAddress() failed %d \n", ::GetLastError());  
  168.         return WSAEPROVIDERFAILEDINIT;  
  169.     }  
  170.   
  171.     // 调用下层提供程序的WSPStartup函数  
  172.     LPWSAPROTOCOL_INFOW pInfo = lpProtocolInfo;  
  173.     if(NextProtocolInfo.ProtocolChain.ChainLen == BASE_PROTOCOL)  
  174.         pInfo = &NextProtocolInfo;  
  175.   
  176.     int nRet = pfnWSPStartup(wVersionRequested, lpWSPData, pInfo, UpcallTable, lpProcTable);  
  177.     if(nRet != ERROR_SUCCESS)  
  178.     {  
  179.         ODS1(L" WSPStartup:  underlying provider's WSPStartup() failed %d \n", nRet);  
  180.         return nRet;  
  181.     }  
  182.   
  183.     // 保存下层提供者的函数表  
  184.     g_NextProcTable = *lpProcTable;  
  185.   
  186.     // 修改传递给上层的函数表,Hook感兴趣的函数,这里做为示例,仅Hook了WSPSendTo函数  
  187.     // 您还可以Hook其它函数,如WSPSocket、WSPCloseSocket、WSPConnect等  
  188.     lpProcTable->lpWSPSendTo = WSPSendTo;  
  189.   
  190.     FreeProvider(pProtoInfo);  
  191.     return nRet;  
  192. }