網(wǎng)絡編程之編寫LSP進行Winsock API監(jiān)控攔截或LSP注入
【1】工具介紹:
用到的工具:VS2015 語言:C/C++ 需要系統(tǒng)提供的動態(tài)鏈接庫:1、?sporder.dll????//很多系統(tǒng)不自帶著個dll,導致編譯時缺少dll無法編譯.?(發(fā)布時必須將此dll放到程序目錄) 本人只提供:???WIN7?64位的sporder.dll?:http://download.csdn.net/download/aaron133/10153240 ???????????????其他系統(tǒng)自行網(wǎng)上下載. 安裝、移除LSP、編寫分層提供者DLL、測試程序的源碼:(申明:本人只在Win7?32/64位?和?Win10?64測試過) http://download.csdn.net/download/aaron133/10152873? (除了文章中的源碼之外,包含了測試程序的源碼)
【2】編寫LSP分層服務提供者需知的概念:
1、先看我寫的SPI接口的概念:http://blog.csdn.net/aaron133/article/details/78005779
2、本章就是介紹安裝SPI的分層協(xié)議提供者(LSP),即第三方系統(tǒng)網(wǎng)絡組件。
3、當Windows程序想要使用網(wǎng)絡時,必須加載SPI的基礎提供者(TCP、UDP、原始)才能進行網(wǎng)絡通訊。
4、安裝LSP分層服務提供者就是寫一個DLL,讓網(wǎng)絡程序先加載進去調(diào)用,然后再我們的DLL內(nèi),再調(diào)用基礎服務提供者,進行網(wǎng)絡通訊,所以在這過程中,我們可以對系統(tǒng)上所有使用特定協(xié)議的網(wǎng)絡程序,在用戶模式下進行Winsock API調(diào)用監(jiān)控,HOOK攔截,甚至利用LSP注入DLL。
5、LSP一般是對網(wǎng)絡進行更高級的通訊服務管理、過濾,黑客常用它來進行瀏覽器劫持、監(jiān)控用戶信息等等.
6、360所謂的修復LSP或CMD的netsh winsock reset命令,就是清除第三方的LSP提供者,并清除它的DLL,留下系統(tǒng)的基礎服務提供者.
【3】不能攔截的Winsock API函數(shù):
1、htonl,htons僅在ws2_32.dll中實現(xiàn).
2、inet_addr,inet_ntoa,gethostname,WSACreateEvent,WSACloseEvent等等都不在SPI中.
3、如果程序直接使用傳輸驅動接口(TDI)進行TCP/IP發(fā)送數(shù)據(jù)包,那么攔截不了.
4、所以在用戶模式下,使用LSP過濾網(wǎng)絡封包是一個很好的選擇.
【4】LSP分層服務提供者的編寫:(DLL)
一、簡述:
1、編寫LSP提供者就是寫一個DLL.
2、WSPStartup是LSP必須導出的函數(shù).
3、加載下層提供者的DLL,并調(diào)用它的初始化WSPStartup是LSP必須做的事情.
4、攔截API函數(shù)就是將下層提供者(基礎協(xié)議提供者)的函數(shù)地址記錄下來,將我們自定義的函數(shù)地址替換上去,執(zhí)行到如send時就會先調(diào)用我們的自定義函數(shù),再由我們的自定義函數(shù),考慮要不要調(diào)用真正的send.
二、開始編寫LSP分層服務提供者的DLL:
【開始編寫】
1、步驟 :創(chuàng)建Win32程序 ? ? --> ? ? DLL開發(fā)
2、新建一個.def文件:
EXPORTS
WSPStartup ? ? ?@2
【代碼步驟分析】
1、網(wǎng)絡程序加載LSP分層服務提供者的DLL,并調(diào)用了DLL里的WSPStartup初始化函數(shù).
2、在LSP的WSPStartup函數(shù)中,加載它的下層服務提供者的DLL,并調(diào)用它的WSPStartup初始化函數(shù).
3、對下層提供者的函數(shù)表地址進行修改,修改感興趣的網(wǎng)絡函數(shù)指向我們的自定義函數(shù),進行攔截、監(jiān)視Winsock API.
4、下面的例子中攔截了connect函數(shù)、sendto函數(shù).
頭文件: ? ? ??//在講解SPI篇的時候,用到的函數(shù),用于遍歷系統(tǒng)所有協(xié)議,包括分層協(xié)議
#include#include#includeLPWSAPROTOCOL_INFOW?GetProvider(LPINT?lpnTotalProtocols)
{//遍歷所有協(xié)議
int?nError?=?0;
DWORD?dwSize?=?0;
LPWSAPROTOCOL_INFOW?pProtoInfo?=?NULL;
if?(WSCEnumProtocols(NULL,?pProtoInfo,?&dwSize,?&nError)?==?SOCKET_ERROR)
{
if?(nError?!=?WSAENOBUFS)
return?NULL;
}
pProtoInfo?=?(LPWSAPROTOCOL_INFOW)new?WSAPROTOCOL_INFOW[dwSize?/?sizeof(WSAPROTOCOL_INFOW)];
if?(!pProtoInfo)
return?NULL;
ZeroMemory(pProtoInfo,?dwSize);
*lpnTotalProtocols?=?WSAEnumProtocols(NULL,?pProtoInfo,?&dwSize);
return?pProtoInfo;
}
void?FreeProvider(LPWSAPROTOCOL_INFOW?pProtoInfo)
{
delete[]?pProtoInfo;
}源文件:
WSPPROC_TABLE?g_NextProcTable;??//下層提供者的函數(shù)表????????全局
//LSP的初始化函數(shù)(唯一的導出函數(shù))
int?WSPAPI?WSPStartup(
WORD?wVersionRequested,??????????????????????????//用戶程序加載套接字庫的版本號(in)
LPWSPDATA?lpWSPData,???????????????????????????????//用于取得Winsock服務的詳細信息
LPWSAPROTOCOL_INFO?lpProtocolInfo,???//指定想得到的協(xié)議的特征
WSPUPCALLTABLE?UpcallTable,?????????????????//Ws2_32.dll向上調(diào)用轉發(fā)的函數(shù)表
LPWSPPROC_TABLE?lpProTable?????????????????//下層提供者的函數(shù)表(一般為基礎協(xié)議,共30個服務函數(shù))
)
{???//如果協(xié)議位分層協(xié)議或基礎協(xié)議,那么返回錯誤
if?(lpProtocolInfo->ProtocolChain.ChainLen?ProtocolChain.ChainEntries[1];
//遍歷所有協(xié)議
int?i?=?0;
for?(;?i?<?nTotalProtols;?i++)
{//找到下層提供者協(xié)議
if?(pProtoInfo[i].dwCatalogEntryId?==?dwBaseEntryId)
{
memcpy(&NextProtocolInfo,?&pProtoInfo[i],?sizeof(WSAPROTOCOL_INFOW));
break;
}
}
//如果沒找到
if?(i?>=?nTotalProtols)
return?WSAEPROVIDERFAILEDINIT;
//加載下層協(xié)議的Dll
int?nError?=?0;
TCHAR?szBaseProviderDll[MAX_PATH];
int?nLen?=?MAX_PATH;
//取得下層提供者的DLL路徑(可能包含壞境變量)
if(WSCGetProviderPath(&NextProtocolInfo.ProviderId,?szBaseProviderDll,?&nLen,?&nError)?==?SOCKET_ERROR)
return?WSAEPROVIDERFAILEDINIT;
//壞境變量轉換字符串
if(!ExpandEnvironmentStrings(szBaseProviderDll,?szBaseProviderDll,?MAX_PATH))
return?WSAEPROVIDERFAILEDINIT;
//加載dll
HMODULE?hModdule?=?LoadLibrary(szBaseProviderDll);
if(hModdule?==?NULL)
return?WSAEPROVIDERFAILEDINIT;
//取出下層提供者的WSPStartup函數(shù)
LPWSPSTARTUP?pfnWSPStartup?=?(LPWSPSTARTUP)GetProcAddress(hModdule,?"WSPStartup");
if(NULL?==?pfnWSPStartup?)
return?WSAEPROVIDERFAILEDINIT;
LPWSAPROTOCOL_INFOW?pInfo?=?lpProtocolInfo;
if?(NextProtocolInfo.ProtocolChain.ChainLen?==?BASE_PROTOCOL)//如果下層提供者是基礎協(xié)議
pInfo?=?&NextProtocolInfo;???????????????????????????????//賦給pInfo指針
//調(diào)用下層提供者的初始化函數(shù)
int?nRet?=?pfnWSPStartup(wVersionRequested,?lpWSPData,?lpProtocolInfo,?UpcallTable,?lpProTable);
//初始化失敗
if?(nRet?!=?ERROR_SUCCESS)
return?nRet;
//初始化完成后,復制下層提供者(基礎協(xié)議)的整個函數(shù)表
g_NextProcTable?=?*lpProTable;
//將基礎協(xié)議的SendTo函數(shù)指針,指向我們的WSPSendTo函數(shù),在我們的函數(shù)內(nèi),再確定要不要調(diào)用回基礎協(xié)議的Sendto函數(shù)
lpProTable->lpWSPSendTo?=?WSPSendTo;?
lpProTable->lpWSPConnect?=?WSPConnect;
FreeProvider(pProtoInfo,?nTotalProtols);
return?nRet;
}//下面對sendto、connect函數(shù)的8888端口進行攔截:
int?WSPAPI?WSPConnect(???????//自定義的WSPConnect函數(shù)
SOCKET?s,
const?struct?sockaddr?FAR?*?name,
int?namelen,
LPWSABUF?lpCallerData,
LPWSABUF?lpCalleeData,
LPQOS?lpSQOS,
LPQOS?lpGQOS,
LPINT?lpErrno
)
{
sockaddr_in*?info?=?(sockaddr_in*)name;
USHORT?port?=?ntohs(info->sin_port);
if?(port?==?8888)???//如果是8888端口,那么攔截
{
int?nError?=?0;
???????????????//因為整個dll已經(jīng)加載進程序里,這里對我的控制臺程序進行測試
SetConsoleTitle(_T("sorry,we?shutdown?you?tcp?protocol?port!"));?
g_NextProcTable.lpWSPShutdown(s,?SD_BOTH,?&nError);
//設置錯誤信息
*lpErrno?=?WSAECONNABORTED;???
return?SOCKET_ERROR;?
}
???????//如果不是,調(diào)用下層提供者的函數(shù)表中的WSPConnect函數(shù)
return?g_NextProcTable.lpWSPConnect(s,?name,?namelen,?lpCallerData,?lpCalleeData,?lpSQOS,?lpGQOS,?lpErrno);
}
int?WSPAPI?WSPSendTo?????????//自定義的WSPSendTo函數(shù)
(
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
)
{
sockaddr_in*?info?=?(sockaddr_in*)lpTo;
USHORT?port?=?ntohs(info->sin_port);
if?(port?==?8888)????//如果是8888端口,那么攔截
{
int?nError?=?0;
SetConsoleTitle(_T("sorry,we?shutdown?you?udp?protocol?port!"));
g_NextProcTable.lpWSPShutdown(s,?SD_BOTH,?&nError);
//設置錯誤信息
*lpErrno?=?WSAECONNABORTED;
return?SOCKET_ERROR;
}
????????//如果不是,調(diào)用下層提供者的函數(shù)表中的WSPSendTo函數(shù)
return?g_NextProcTable.lpWSPSendTo(s,?lpBuffers,?dwBufferCount,?lpNumberOfBytesSent,?dwFlags,
lpTo,?iTolen,?lpOverlapped,?lpCompletionRoutine,?lpThreadId,?lpErrno);
}【5】LSP的DLL編寫完成后,編寫安裝與卸載LSP的程序:
一、簡述:1、安裝、卸載LSP必須是管理員用戶組的權限才能使用.2、下面的例子中,我一共安裝了1個分層協(xié)議(DLL),3個協(xié)議鏈(用于搶在TCP、UDP、原始套接字提供者前執(zhí)行)3、在http://blog.csdn.net/aaron133/article/details/78005779篇中的? ? ?“網(wǎng)絡程序是如何調(diào)用Winsock2 服務提供者進行網(wǎng)絡通訊”? ? 調(diào)用網(wǎng)絡通訊的機制,所以要將新安裝的協(xié)議鏈,排在遍歷函數(shù)的最前面,網(wǎng)絡程序先找到適合的協(xié)議,就會用那個協(xié)議,如果排在后面,就可能載入別的相同類型的協(xié)議的提供者,而不使用我們的分層提供者.
二、開始編寫安裝LSP程序:
【編寫步驟分析】一、遍歷所有協(xié)議,將UDP、TCP、原始的Winsock目錄入口(結構體)各復制一份出來.二、隨便找一個下層協(xié)議(基礎服務提供者)的Winsock目錄入口結構體作為模板,用于安裝LSP時作為它的Winsock目錄入口(結構體).1、必須修改協(xié)議名稱(szProtocol成員).2、dwServiceFlags1成員必須將XP1_IFS_HANDLES標志去掉.
3、提供者的類型:ProtocolChain成員ChainLen變量 = LAYERED_PROTOCOL(0) //0暗示為分層協(xié)議提供者 ? ?不懂這個概念的先看我上一篇講解SPI文章.//地址:http://blog.csdn.net/aaron133/article/details/78005779
4、表示方式:dwProviderFlags成員 = PFL_HIDDEN; //由提供者自己設置的Winsock目錄入口.5、安裝分層協(xié)議提供者.
三、安裝3個協(xié)議鏈(協(xié)議鏈,排在第一位的就是我們新安裝的分層提供者)1、為什么有3個協(xié)議鏈,因為它們各對應一個基礎協(xié)議提供者,分別是TCP、UDP、原始,當網(wǎng)絡程序使用TCP、UDP、原始,會先加載我們的分層服務提供者LSP的DLL。
四、重新排序Winsock目錄1、因為新安裝的提供者,都會排在最后,這樣如果前面有網(wǎng)絡程序適合的提供者時,就會直接載入它的DLL,而不載入我們LSP的DLL.頭文件:
#include#include#include#include#include#include#include#includeusing?namespace?std;
#pragma?warning(disable:4996)
#pragma?comment(lib,"Sporder.lib")
#pragma?comment(lib,?"Ws2_32.lib")
#include//安裝LSP
class?installLSP
{
public:
installLSP()
{
WSADATA?wsa;
WSAStartup(MAKEWORD(2,?2),?&wsa);
CoCreateGuid(&this->Layered_guid);
CoCreateGuid(&this->AgreementChain_guid);
}
~installLSP()
{
WSACleanup();
}
public:
//安裝LSP,并安裝3個協(xié)議鏈
BOOL?InstallProvider(WCHAR*?wszDllPath)??//參數(shù):LSP的DLL的地址
{
WCHAR?wszLSPName[]?=?_T("AaronLSP");
LPWSAPROTOCOL_INFOW?pProtoInfo?=?NULL;
int?nProtocols?=?0;?//分層協(xié)議?????取出來的模板
WSAPROTOCOL_INFOW?OriginalProtocolInfo[3];?//數(shù)組成員為TCP、UDP、原始的目錄入口信息
DWORD?dwOrigCatalogId[3];?//記錄入口ID號
int?nArrayCount?=?0;??????//數(shù)組個數(shù)索引
DWORD?dwLayeredCatalogId;?//分層協(xié)議的入口ID號
int?nError;
pProtoInfo?=?GetProvider(&nProtocols);
if?(nProtocols?<?1?||?pProtoInfo?==?NULL)
return?FALSE;
BOOL?bFindUdp?=?FALSE;
BOOL?bFindTcp?=?FALSE;
BOOL?bFindRaw?=?FALSE;
for?(int?i?=?0;?i?<?nProtocols;?i++)
{???//查找地址族為AF_INET的協(xié)議
if?(pProtoInfo[i].iAddressFamily?==?AF_INET)
{
if?(!bFindUdp?&&?pProtoInfo[i].iProtocol?==?IPPROTO_UDP)
{
memcpy(&OriginalProtocolInfo[nArrayCount],?&pProtoInfo[i],?sizeof(WSAPROTOCOL_INFOW));
//去除XP1_IFS_HANDLES標志,防止提供者返回的句柄是真正的操作系統(tǒng)句柄
OriginalProtocolInfo[nArrayCount].dwServiceFlags1?&=?(~XP1_IFS_HANDLES);
//記錄目錄入口ID
dwOrigCatalogId[nArrayCount++]?=?pProtoInfo[i].dwCatalogEntryId;?
bFindUdp?=?TRUE;
}
if?(!bFindTcp?&&?pProtoInfo[i].iProtocol?==?IPPROTO_TCP)
{
memcpy(&OriginalProtocolInfo[nArrayCount],?&pProtoInfo[i],?sizeof(WSAPROTOCOL_INFOW));
//去除XP1_IFS_HANDLES標志,防止提供者返回的句柄是真正的操作系統(tǒng)句柄
OriginalProtocolInfo[nArrayCount].dwServiceFlags1?&=?(~XP1_IFS_HANDLES);
//記錄目錄入口ID
dwOrigCatalogId[nArrayCount++]?=?pProtoInfo[i].dwCatalogEntryId;
bFindTcp?=?TRUE;
}
if?(!bFindRaw?&&?pProtoInfo[i].iProtocol?==?IPPROTO_IP)
{
memcpy(&OriginalProtocolInfo[nArrayCount],?&pProtoInfo[i],?sizeof(WSAPROTOCOL_INFOW));
//去除XP1_IFS_HANDLES標志,防止提供者返回的句柄是真正的操作系統(tǒng)句柄
OriginalProtocolInfo[nArrayCount].dwServiceFlags1?&=?(~XP1_IFS_HANDLES);
//記錄目錄入口ID
dwOrigCatalogId[nArrayCount++]?=?pProtoInfo[i].dwCatalogEntryId;
bFindRaw?=?TRUE;
}
}
}
if?(nArrayCount?==?0)
{
FreeProvider(pProtoInfo);
return?FALSE;
}
//安裝LSP分層協(xié)議
WSAPROTOCOL_INFOW?LayeredProtocolInfo;
memcpy(&LayeredProtocolInfo,?&OriginalProtocolInfo[0],?sizeof(WSAPROTOCOL_INFOW));
//修改協(xié)議名稱的字符串
wcscpy(LayeredProtocolInfo.szProtocol,?wszLSPName);
//表示分層協(xié)議
LayeredProtocolInfo.ProtocolChain.ChainLen?=?LAYERED_PROTOCOL;//0
//表示方式為由提供者自己設置
LayeredProtocolInfo.dwProviderFlags?=?PFL_HIDDEN;
//安裝分層協(xié)議
if?(SOCKET_ERROR?==?WSCInstallProvider(&Layered_guid,?wszDllPath,?&LayeredProtocolInfo,?1,?&nError))
{
FreeProvider(pProtoInfo);
return?FALSE;
}
FreeProvider(pProtoInfo);
//重新遍歷協(xié)議,獲取分層協(xié)議的目錄ID號
pProtoInfo?=?GetProvider(&nProtocols);
if?(nProtocols?<?1?||?pProtoInfo?==?NULL)
return?FALSE;
for?(int?i?=?0;?i?<?nProtocols;?i++)//一般安裝新入口后,會排在最低部
{
if?(memcmp(&pProtoInfo[i].ProviderId,?&Layered_guid,?sizeof(GUID))?==?0)
{
//取出分層協(xié)議的目錄入口ID
dwLayeredCatalogId?=?pProtoInfo[i].dwCatalogEntryId;
break;
}
}
//安裝協(xié)議鏈?????????????????256
WCHAR?wszChainName[WSAPROTOCOL_LEN?+?1];//新分層協(xié)議的名稱??over???取出來的入口模板的名稱
for?(int?i?=?0;?i?<?nArrayCount;?i++)
{
swprintf(wszChainName,?_T("%s?over?%s"),?wszLSPName,?OriginalProtocolInfo[i].szProtocol);
wcscpy(OriginalProtocolInfo[i].szProtocol,?wszChainName);??//將這個模板的名稱改成新名稱↑
if?(OriginalProtocolInfo[i].ProtocolChain.ChainLen?==?1)//這是基礎協(xié)議的模板
{???//修改基礎協(xié)議模板的協(xié)議鏈,?在協(xié)議鏈[1]寫入真正UDP[基礎協(xié)議]的入口ID
OriginalProtocolInfo[i].ProtocolChain.ChainEntries[1]?=?dwOrigCatalogId[i];
}
else
{//如果大于1,相當于是個協(xié)議鏈,表示:將協(xié)議鏈中的入口ID,全部向后退一格,留出[0]
for?(int?j?=?OriginalProtocolInfo[i].ProtocolChain.ChainLen;?j?>?0;?j--)
OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j]?=?OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j?-?1];
}
//讓新分層協(xié)議排在基礎協(xié)議的前面(如果為協(xié)議鏈排就排在開頭了)
OriginalProtocolInfo[i].ProtocolChain.ChainLen++;
OriginalProtocolInfo[i].ProtocolChain.ChainEntries[0]?=?dwLayeredCatalogId;
}
//一次安裝3個協(xié)議鏈
if?(SOCKET_ERROR?==?WSCInstallProvider(&AgreementChain_guid,?wszDllPath,?OriginalProtocolInfo,?nArrayCount,?&nError))
{
FreeProvider(pProtoInfo);
return?FALSE;
}
//第三步:將所有3種協(xié)議進行重新排序,以讓系統(tǒng)先調(diào)用我們的協(xié)議(讓協(xié)議鏈排第一,協(xié)議鏈中[0]是新分層協(xié)議,[1]基礎UDP協(xié)議)
//重新遍歷所有協(xié)議
FreeProvider(pProtoInfo);
pProtoInfo?=?GetProvider(&nProtocols);
if?(nProtocols?<?1?||?pProtoInfo?==?NULL)
return?FALSE;
DWORD?dwIds[20];
int?nIndex?=?0;
//添加我們的協(xié)議鏈
for?(int?i?=?0;?i?<?nProtocols;?i++)
{//如果是我們新創(chuàng)建的協(xié)議鏈
if?(pProtoInfo[i].ProtocolChain.ChainLen?>?1?&&?pProtoInfo[i].ProtocolChain.ChainEntries[0]?==?dwLayeredCatalogId)
dwIds[nIndex++]?=?pProtoInfo[i].dwCatalogEntryId;//將3個協(xié)議鏈排在前3
}
//添加其他協(xié)議
for?(int?i?=?0;?i?<?nProtocols;?i++)
{//如果是基礎協(xié)議,分層協(xié)議(不包括我們的協(xié)議鏈,但包括我們的分層協(xié)議)
if?(pProtoInfo[i].ProtocolChain.ChainLen?<=?1?||?pProtoInfo[i].ProtocolChain.ChainEntries[0]?!=?dwLayeredCatalogId)
dwIds[nIndex++]?=?pProtoInfo[i].dwCatalogEntryId;
}
//重新排序Winsock目錄
if?(WSCWriteProviderOrder(dwIds,?nIndex)?!=?ERROR_SUCCESS)
return?FALSE;
FreeProvider(pProtoInfo);
return?TRUE;
}
????????//卸載LSP
void?RemoveProvider()
{
LPWSAPROTOCOL_INFOW?pProtoInfo?=?NULL;
int?nProtocols?=?0;
DWORD?dwLayeredCatalogId?=?0;?//分層協(xié)議提供者的入口ID號
?//遍歷出所有協(xié)議
pProtoInfo?=?GetProvider(&nProtocols);
if?(nProtocols?<?1?||?pProtoInfo?==?NULL)
return;
int?nError?=?0;
int?i?=?0;
for?(i?=?0;?i?<?nProtocols;?i++)
{?//查找分層協(xié)議提供者
if?(memcmp(&Layered_guid,?&pProtoInfo[i].ProviderId,?sizeof(GUID))?==?0)
{
dwLayeredCatalogId?=?pProtoInfo[i].dwCatalogEntryId;
break;
}
}
if?(i?<?nProtocols)
{
for?(i?=?0;?i?<?nProtocols;?i++)
{//查找協(xié)議鏈(這個協(xié)議鏈的[0]為分層協(xié)議提供者)
if?(pProtoInfo[i].ProtocolChain.ChainLen?>?1?&&?pProtoInfo[i].ProtocolChain.ChainEntries[0]?==?dwLayeredCatalogId)
{//先卸載協(xié)議鏈
WSCDeinstallProvider(&pProtoInfo[i].ProviderId,?&nError);
break;
}
}
WSCDeinstallProvider(&Layered_guid,?&nError);
}
}
private:
???????//這兩個函數(shù)是遍歷所有協(xié)議函數(shù),在編寫DLL時,已經(jīng)把源代碼放出來了,這里就不放出來了.
???????LPWSAPROTOCOL_INFOW?GetProvider(LPINT?lpnTotalProtocols);
???????void?FreeProvider(LPWSAPROTOCOL_INFOW?pProtoInfo);?
private:
GUID?Layered_guid;????????//分層協(xié)議GUID
GUID?AgreementChain_guid;?//協(xié)議鏈GUID
};源文件:
#include?"Hello.h"
#define?PATH?_T("C:\Users\Administrator\Desktop\實例\網(wǎng)絡實驗\安裝LSP服務提供程序\LSPDll\Debug\LSPDll.dll")
int?main(int?argc,char**?argv)
{
system("color?4e");
SetConsoleTitle(_T("安裝LSP提供者程序實驗"));
ProtocolTraversestheExperiment2?s;
printf("安裝LSP前的所有協(xié)議:rn");
s.ShowAllProtocol();
installLSP?LSP;
LSP.InstallProvider(PATH);
printf("安裝LSP后的所有協(xié)議:rn");
s.ShowAllProtocol();
getchar();
LSP.RemoveProvider();
printf("清除LSP完成rn");
getchar();
return?0;
}
【測試】1、安裝了一個LSP分層服務提供者(相當于HOOK了TCP、UDP、原始套接字),三個協(xié)議鏈
2、當有程序使用8888端口進行TCP連接或8888端口使用UDP發(fā)送數(shù)據(jù)時,就會攔截禁止:
附加說明:1、Sporder.dll在編寫LSP程序時,32位放在WOWSys64文件夾、64位放在system32文件夾.2、發(fā)布時必須攜帶著Sporder.dll在程序目錄存放.3、編寫64位LSP程序的程序時,不要包含#pragma comment(lib,"Sporder.lib")否則程序出錯!





