基於SPI的LSP網絡封包截獲

、、、首先我不是原創、、、、、

轉載別人的然後自己學習,網上有很多資料。大家可以先看《windows防火牆與網絡封包截獲》然後再看“基於SPI 的網絡封包截獲”。應該就差不多了

我會在地址下方給出這些資料鏈接、、、、

還有源碼。

首先先安裝LSP:

#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()函數
#pragma comment(lib, sporder.lib )
 
//定義要安裝的LSP的硬編碼,在卸載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;  //用於申請存放服務提供者結構的內存空間;
 
 // 取得需要的長度,即通過將WSCEnumProtocols函數的dwSize參數置0進行第一次調用,後
 //以獲得枚舉服務提供者所需的緩衝區大小,置於dwSize變量中;
 if(::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError) == SOCKET_ERROR)
 {
  if(nError != WSAENOBUFS)
   return NULL;
 }
 
 //根據dwSize中的值來申請內存空間;
 pProtoInfo = (LPWSAPROTOCOL_INFOW)::GlobalAlloc(GPTR, dwSize);
 //第二次通過WSCEnumProtocols()正式枚舉到各服務提供者並存放於pProtoInfo(數組)中,
 //並將服務提供者的個數存到lpnTotalProtocols中;
 *lpnTotalProtocols = ::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError);
 //將pProtoInfo返回給函數調用者;
 return pProtoInfo;
}
 

void FreeProvider(LPWSAPROTOCOL_INFOW pProtoInfo)
{
 //釋放用於存放服務提供者數組的內存空間,pProtoInfo;
 ::GlobalFree(pProtoInfo);
}
 

//枚舉現有的各服務提供者;
void query()
{
 LPWSAPROTOCOL_INFOW pProtoInfo;
 int nProtocols;
 pProtoInfo = GetProvider(&nProtocols);
 for(int i=0; i<nProtocols; i++)
 {
  
  printf(" Protocol: %ws \n", pProtoInfo[i].szProtocol);
  printf(" CatalogEntryId: %d  ChainLen: %d \n\n", 
   pProtoInfo[i].dwCatalogEntryId, pProtoInfo[i].ProtocolChain.ChainLen);
  
 }
}

//安裝LSP
int InstallProvider(WCHAR *pwszPathName)
{
 //標識我們自定義安裝的LSP的名字;
 WCHAR wszLSPName[]=L"^_^LSP";
 LPWSAPROTOCOL_INFOW pProtoInfo;  
 int nProtocols; 
 WSAPROTOCOL_INFOW OriginalProtocolInfo[3];  
 DWORD dwOrigCatalogId[3];  
 int nArrayCount=0;
 DWORD dwLayeredCatalogId;  
 int nError;
 //枚舉所有的服務提供者;
 pProtoInfo=GetProvider(&nProtocols);
 //通過以下三個布爾變量,來判斷是否找到對應服務提供者;
 BOOL bFindTcp=FALSE;
 BOOL bFindUdp=FALSE;
 BOOL bFindRaw=FALSE;
 //遍歷pProtoInfo數據裏的每個服務提供者,並將TCP、UDP、RAW對應的服務提供者結構保存;
 for(int i=0;i<nProtocols;i++)
 {
  if(pProtoInfo[i].iAddressFamily==AF_INET)
  {
   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(!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(!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,即LSP入口ID;
 
 //任意將一個下層服務提供者的結構複製到LayeredProtocolInfo中,進行LSP
 //服務提供者結構的自定義;
 WSAPROTOCOL_INFOW LayeredProtocolInfo; 
 memcpy(&LayeredProtocolInfo,&OriginalProtocolInfo[0],sizeof(WSAPROTOCOL_INFOW));
 //構造我們自定義的LSP結構;
 wcscpy(LayeredProtocolInfo.szProtocol,wszLSPName);  
 LayeredProtocolInfo.ProtocolChain.ChainLen=LAYERED_PROTOCOL;  
 LayeredProtocolInfo.dwProviderFlags|=PFL_HIDDEN;
 //通過WSCInstallProvider()開始安裝我們自定義的LSP;
 if(::WSCInstallProvider(&ProviderGuid,pwszPathName,&LayeredProtocolInfo,1,&nError)==SOCKET_ERROR)
 {
  return nError;
 }
 //重新枚舉各服務提供者,獲取剛纔我們安裝好的自定義的LSP的入口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,並通過OriginalProtocol數組來安裝三個協議鏈;
 GUID ProviderChainGuid;
 if(::UuidCreate(&ProviderChainGuid)==RPC_S_OK)
 {
  if(::WSCInstallProvider(&ProviderChainGuid,pwszPathName,OriginalProtocolInfo,nArrayCount,&nError)==SOCKET_ERROR)
  {
   return nError;
  }
 }
 else
  return GetLastError();

 //協議鏈安裝完畢後,需要重新排序,將我們的協議鏈提到最前面;

 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;
 }
 //添加其他的服務提供者入口ID;
 for(i=0;i<nProtocols;i++)
 {
  if((pProtoInfo[i].ProtocolChain.ChainLen<=1)||(pProtoInfo[i].ProtocolChain.ChainEntries[0]!=dwLayeredCatalogId))
   dwIds[nIndex++]=pProtoInfo[i].dwCatalogEntryId;
 }

 //通過WSCWriteProviderOrder()重新按照dwIds的順序排序;
 if((nError=::WSCWriteProviderOrder(dwIds,nIndex))!=ERROR_SUCCESS)
 {
  return nError;
 }
 FreeProvider(pProtoInfo);
 return nError;
}
 

//移除我們自定義的LSP及協議鏈;
void RemoveProvider()
{
 LPWSAPROTOCOL_INFOW pProtoInfo;
 int nProtocols;
 DWORD dwLayeredCatalogId;
 
 pProtoInfo=GetProvider(&nProtocols);
 int nError;
 
 //根據GUID來獲得分層協議的入口ID;
 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);
   }
  }
  //最後移除分層服務提供者LSP;
  ::WSCDeinstallProvider(&ProviderGuid, &nError);
 }
}
 

///////////////////////////////////////////////////////////////////////////////////////

int usage()
{
 printf("\n*********************************************************\n"
       "*  nfilter.exe,by miyagi&echo                           *\n"
    "*                                                       *\n"
       "*  usage:nfilter.exe [-install] [-uninstall] [-query]   *\n"
       "*********************************************************\n");
 return 0;
}
 
int main(int argc,char* argv[])
{
 if(argc<2)
 {
  usage();
 }
 else
 {
   if(strcmp(argv[1],"-install")==0)
   { 
    if(InstallProvider(L"wskfilter.dll") == ERROR_SUCCESS)
    {
     printf(" Install successully!^_^ \n");
    }
    else
    {
     printf(" Install failed!~o~ \n");
    }
   }     
   if(strcmp(argv[1],"-uninstall")==0)
   {
    RemoveProvider();
    printf(" Uninstall successully!^_^ \n");
   }
   if(strcmp(argv[1],"-query")==0)
   {
    query();
    printf(" Query successully!^_^ \n");
   }

 }

 return 1;
 
}

將輸出路徑改爲:
../Release/install.exe
在此過程中可能會出現external symbol _WSCWriteProviderOrder@8。然後解決方法呢就是、、<a target=_blank href="http://blog.csdn.net/u013675958/article/details/21302423">點擊打開鏈接</a>
。。。。。
發佈了148 篇原創文章 · 獲贊 65 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章