加密網(wǎng)絡(luò)數(shù)據(jù)包如何用Winsock2SPI技術(shù)實現(xiàn)

不要以為上網(wǎng)瀏覽網(wǎng)頁很簡單,其實不然。就是你上網(wǎng)打開網(wǎng)頁這一簡單的動作,就需要你先發(fā)送數(shù)據(jù)包給網(wǎng)站,它接收到了之后,根據(jù)你發(fā)連的數(shù)據(jù)包的IP地址,返回給你網(wǎng)頁的數(shù)據(jù)包,也就是說,網(wǎng)頁的瀏覽,實際上就是數(shù)據(jù)包的交換。所以,要保障網(wǎng)頁信息安全,首先就需要保障數(shù)據(jù)包的安全。為此,我們設(shè)計了一種用Winsock2SPI技術(shù)加密數(shù)據(jù)包的方法,接下來就和大家簡單的介紹一下。

一、Winsock2 SPI技術(shù)

Winsock2 SPI(Service Provider Interface)服務(wù)提供者接口建立在Windows開放系統(tǒng)架構(gòu)WOSA(Windows Open System Architecture)之上,是Winsock系統(tǒng)組件提供的面向系統(tǒng)底層的編程接口。Winsock系統(tǒng)組件向上面向用戶應(yīng)用程序提供一個標準的API接口;向下在Winsock組件和Winsock服務(wù)提供者(比如TCP/IP協(xié)議棧)之間提供一個標準的SPI接口。各種服務(wù)提供者是Windows支持的DLL,掛靠在Winsock2 的Ws2_32.dll模塊下。對用戶應(yīng)用程序使用的Winsock2 API中定義的許多內(nèi)部函數(shù)來說,這些服務(wù)提供者都提供了它們的對應(yīng)的運作方式(例如API函數(shù)WSAConnect有相應(yīng)的SPI函數(shù)WSPConnect)。多數(shù)情況下,一個應(yīng)用程序在調(diào)用Winsock2 API函數(shù)時,Ws2_32.dll會調(diào)用相應(yīng)的Winsock2 SPI函數(shù),利用特定的服務(wù)提供者執(zhí)行所請求的服務(wù)。

Winsock2 SPI允許開發(fā)兩類服務(wù)提供者——傳輸服務(wù)提供者和名字空間服務(wù)提供者。“傳輸提供者”(Transport Providers, 一般稱作協(xié)議堆棧,例如TCP/IP)能夠提供建立通信、傳輸數(shù)據(jù)、日常數(shù)據(jù)流控制和錯誤控制等傳輸功能方面的服務(wù)。“名字空間提供者”(Name Space Providers,例如DNS名字解析服務(wù))則把一個網(wǎng)絡(luò)協(xié)議的地址屬性和一個或多個用戶友好名稱關(guān)聯(lián)到一起,以便啟用與應(yīng)用無關(guān)的名字解析方案。

SPI的作用是負責(zé)連接核心層的驅(qū)動程序和高層的應(yīng)用程序,系統(tǒng)產(chǎn)生的所有Winsock請求都由SPI函數(shù)完成。形象地說,就是當(dāng)Winaock的數(shù)據(jù)包經(jīng)過SPI層時,就會被SPI截獲。因此可以通過利用SPI的這個特性,將截獲的網(wǎng)絡(luò)封包進行處理,從而完成所需要的信息加密等功能。

二、Winsok SPI在注冊表中的位置

在win32操作系統(tǒng)中,Windows的傳輸服務(wù)提供者的結(jié)構(gòu)信息都保存在注冊表的HKEY - LOCAL - MACHINE \SYSTEM、CurrentControlSet、Services、WinSock2、Parametera\Protocol - Cata-log9 \CaUrlog - Entries分支下。在這個分支下,每個類型的服務(wù)提供者都會有一個子分支,子分支的PackedCatalogltem鍵保存的鍵值為傳輸服務(wù)提供者的路徑、文件名及WSAPROTOCOLINFOW結(jié)構(gòu)。

三、加密網(wǎng)絡(luò)數(shù)據(jù)包如何用Winsock2SPI技術(shù)實現(xiàn)

1、安裝SPI服務(wù)

SPI提供兩種服務(wù),基礎(chǔ)服務(wù)提供者和分層服務(wù)提供者,這里我們只用到分層服務(wù)提供者,具體實現(xiàn)方法請參照源碼中的InBtkp類。

要安裝分層式服務(wù)提供者,需要建立兩個WSAPROTO-IoLJNFOW目錄條目結(jié)構(gòu)。一個代表分層提供者(比如協(xié)議鏈長度等于O)。另一個代表一個協(xié)議鏈(比如,協(xié)議鏈長度大于1)。該協(xié)議鏈把分層提供者與一個基礎(chǔ)提供者鏈接起來。應(yīng)該用一個現(xiàn)成服務(wù)提供者的WSAPROTOTOL_INFOW目錄條目結(jié)構(gòu)的屬性來初始化這兩個結(jié)構(gòu)。調(diào)用WSCEnrunProto-caLs函數(shù),便可獲得這個現(xiàn)成服務(wù)提供者的WSAPROTO-TOIJNFOW目錄條目結(jié)構(gòu)了。

利用WSClnsLaIIProvider安裝SPI。函數(shù)實現(xiàn)如下:

WSClnstaIIPrOYider(&Pmv如rGuid,PROVIDER_pATH, &I—PLayeredlnfo,1.EmuCode); VVSCInstaIIPrmrider()是一個win-dows函數(shù),其中的參數(shù)可以查閱MSND,這里不作多述。如果成功安裝,會發(fā)表注冊表:。HKEY。LOCAL - MACHINE\SYSTEM \CurrentControISet\Services \WinSock2 \Parameters \Proto-col - Catalog9 \Calalog- Entries分支下會多一項寸如果要御載
SPI,則利用函數(shù)CDeinstaIIProvider e LPGUID j lpProviderld,LPINT lpErrno)f該函數(shù)返回值為整型。

2、WSPStartup()函數(shù)的處理

WSPStartup函數(shù)是Winsoket應(yīng)用程序調(diào)用SPI的初始化函數(shù),在自己設(shè)計的服務(wù)提供者DLL模塊中必須重新編寫WSP-Startup函數(shù)的實現(xiàn)過程,并用Export導(dǎo)出,一以便Winsock應(yīng)用程序調(diào)用。其中我們用WSPSend()和WSPRecv()兩個函數(shù)為例,這兩個函數(shù)相當(dāng)于Winsock API中的Send()和Recv()。

WSPStartup()中對應(yīng)代碼表示為:

int WSPAPI WSPStartup(WORD wVersion, LPWSPDAT AlpWSPData, PWSAPROTOCOL_INFOWlpProtocollnfo, WSPUPCALLTABLE UpCaIITable, LPWSPPROC_TABLE ,lpProcTable)

{

//關(guān)鍵代碼段;其它省略

ipProcTable ->lpWSPSend - WSPSend;

lpProcTable - >lpWSPRecv= WSPRecv;

這樣,Winsock API WSASend()和WSARecv()就映射到WSPSend()和WSPRecv(),如果應(yīng)用程序調(diào)用WSASend(),就會先調(diào)用YVSPSend(),調(diào)用WSAReeV()就會先調(diào)用WSPRecv()我們就能在WSPRecv()接收緩坤區(qū)中進行解密,同理,可以在WSPSend()發(fā)送前,對發(fā)送緩沖區(qū)加密,因此不必要每個WSASend()的接收緩沖區(qū)解密。

3、實現(xiàn)在WSASend()加密

在發(fā)送數(shù)據(jù)包前,對數(shù)據(jù)包加密,本文加密算法是把數(shù)據(jù)包中每一個(lpBuffers[i].buf[j])作加10操作。

關(guān)鍵代碼如下:
int WSPAPI WSPSend (SOCKETs,LPWSABUF,lpBufters, D\NORDdwBufferCount, LPDWORD lpNumberOfBytesSent DWORD dwFlagst

LPWSAOVERLAPPEDlpOvsrlappad, LPWSAOVERLAPPED_COMPLETiONBOUTINE - IlpCompletionRoutin Errno)

LPWSATHREADIDlpThread'd, IPINT lpEr INT Ret;

SOCKjNFO*SocketContext;

LPWSAOVERLAPPED ProviderOverlapped;

int type;

SOCKADDRJN m.locaIBddr;

SOCK ADDRJN nUemote_addr;;

int namelen;

namelen=sizeof(SOCKADDR_IN),

//用getsockname得到套接宇的屬性,從中可以得到

//IP地址,端口號,可以根據(jù)應(yīng)用程序需要

//對特定IP或PORT接收到的包進行加密。

type =getsockname(s, (SOCKADDR8)&

mjocal3ddr,&namelen.)

type =getpeername(s, (SQCKADDR*)&

rruemote_addr,&namelen);

//加密,可以根據(jù)應(yīng)用程序的要求,對特定IP和PORT

//進行加密,

inti.j;

//可以根據(jù)應(yīng)用程序的要求用一條if語句判斷發(fā)送包;

//的IP或PORT是否是要加密的包的標志

//根據(jù)getsockname()和getpeername()判斷是否要

//入加密循環(huán),,此處省略判斷,對所有的數(shù)據(jù)包加密

這樣,根據(jù)應(yīng)用程序的要求.1以IP或PORT。為判斷標志;’可以對發(fā)送的數(shù)據(jù)包進行加密。

4、實現(xiàn)在WSPRecv()中解密

得到接收的數(shù)據(jù)包,再對接收的數(shù)據(jù)包進行解密,本處解密算法是把每一個(lpBuflers[i].buf[j])的值減10,如果要用專用的解密算法只用在for循環(huán)中對(lpBuflers[i].buf[j])進行解密。

int WSPAPl WSPRecv( SOCKET s, LPWSABUF _lpBuffers, DWORD dwBufrerCount . LPDWORD

lpNumberOfBytesRecvd, LPDWORDlpFlags,

LPWSAOVERLAPPEDlpOverfapped,

LPWSAOVERLAPPED COMPLETION_ROUTINE-,

lpCompletionRoutine, . LPWSATHREADID lpTh readld,LPINT lpErrno) .

SOCKJNFO *SocketContext;

intRet

PWSAOVERLAPPED ProviderOverlapped; .:i: 'A,

Tf (MainUpCaIITable; lpWPUQuerySockcatHandleContcaxt

('si :(:LPDWORD) & SocketContext, lpErrno)*

SOCKET_ERROR)

return SOCKET_ERROR;

inttype;

SOCKADDRINmjocaIBddr;f v .. ,

SOC K ADDR_IN m remote addr; -i :

Int namelen;

namele3n : sizeof{SOC KADDRJN);

此處可以根據(jù)應(yīng)用程序的要求;對特定的I或PORT進行解密,可以用ijf語句判斷上面用getsockname()和gelpeenle()得到的I或PORT是不是應(yīng)用程序要求解密的判斷標志。這里是對所有的數(shù)據(jù)包解密。

這樣,根據(jù)應(yīng)用程序的要求,以IP或PORT為判斷標志,可以對接收的數(shù)據(jù)包進行解密。

小知識之?dāng)?shù)據(jù)包

包(Packet)是TCP/IP協(xié)議通信傳輸中的數(shù)據(jù)單位,一般也稱“數(shù)據(jù)包”。有人說,局域網(wǎng)中傳輸?shù)牟皇恰皫?Frame)嗎?沒錯,但是TCP/IP協(xié)議是工作在OSI模型第三層(網(wǎng)絡(luò)層)、第四層(傳輸層)上的,而幀是工作在第二層(數(shù)據(jù)鏈路層)。上一層的內(nèi)容由下一層的內(nèi)容來傳輸,所以在局域網(wǎng)中,“包”是包含在“幀”里的。