LSP(계층형 서비스 제공자)
작동 방법:
플러그인 생성 함수는 winsock 디렉터리에서 적합한 프로토콜을 찾을 것입니다
이 프로토콜을 호출하면 공급자가 내보낸 함수가 각종 기능을 완성합니다.
작성 목적:
사용자로 하여금 사용자 정의 서비스 제공자를 호출하게 하고 사용자 정의 서비스 제공자가 하위 공급자를 호출하게 한다.이렇게 하면 모든 winsock 호출을 캡처할 수 있습니다.
서비스 공급자 자체는 DLL이며 winsock API에 해당하는 SPI 함수를 내보냅니다.winsock 라이브러리에서 서비스 제공자를 불러올 때, 이 함수에 의존하여 winsock API를 실현합니다.
LSP도 마찬가지로, Ws2 에서 모든 SPI 함수를 위로 내보냅니다.32.dll 호출, 내부에서 기본 공급자를 호출하여 이러한 SPI를 실현한다.
LSP를 설치합니다.
LSP를 실현하기 전에, 층 공급자를 winsock 디렉터리에 설치하고, WSAPPROTOCOL을 포함하여 설치해야 한다.INFOW 구조는 계층 공급자의 특성과 LSP가 체인을 채우는 방식을 정의합니다.(프로토콜 포털이라고도 함)
프로토콜 체인:
프로토콜 체인은 층 공급자가 winsock에 가입하는 디렉터리의 순서를 설명합니다.
typedef struct _WSAPROTOCOLCHAIN{
int ChainLen;
DWORD ChainEntries[Max_PROTOCOL_CHAN];
}WSAPROTOCOLCHAIN,*LPWSAPROTOCOLCHAIN;
ChainLen은 0: 계층형 프로토콜은 1 기본 프로토콜이 1 프로토콜 체인보다 큽니다.
ChainLen이 0 또는 1일 경우 ChainEntries 배열은 의미가 없습니다.
1보다 크면 각 서비스 제공자의 디렉터리 ID가 배열에 포함됩니다.
LSP의 DLL을 다른 LSP에 로드하거나 WS232.DLL 로드위치에 따라 다릅니다.
만약 LSP가 프로토콜 체인의 맨 위에 있지 않으면, 체인의 맨 위에 있는 LSP에 의해 불러옵니다. 그렇지 않으면 WS232.DLL 로드
LSP를 설치할 때 winsock 디렉터리에 두 가지 프로토콜을 설치해야 합니다. 하나는 층 프로토콜이고 하나는 프로토콜 체인입니다.
층 프로토콜을 설치하는 것은 winsock 라이브러리에서 분배된 디렉터리 ID 번호를 얻기 위해 프로토콜 체인에 자신의 위치를 표시합니다.
프로토콜 체인이야말로 winsock 디렉터리에서 LSP의 진정한 입구이며, 연결에는 자신의 층 프로토콜의 디렉터리 ID 번호와 하위 공급자의 디렉터리 ID 번호가 포함되어 있다.
설치할 때, 먼저 층 프로토콜을 설치하고, 시스템이 이 층 프로토콜에 분배한 디렉터리 ID와 하위 공급자의 디렉터리 ID로ChainEntries 그룹을 구축하여 WSAPROTOCOLINFOW 구조를 만든 다음 이 프로토콜 체인을 설치합니다.
설치 함수:
LSP GUID DLL WSAPROTOCOL 제공INFOW 구조를 사용할 수 있습니다.
int WSCInstallProvider(
const LPGUID lpProviderId,
const LPWSTR lpszProviderDllPath,
const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
DWORD dwNumberOfEntries,
LPINT lpErrno
);
모든 설치 공급자는 입구를 표시하기 위해 GUID를 필요로 합니다. GUID는 명령행 도구인 UUIDGEN이나 프로그래밍에서 UuidCreate 함수를 사용하여 생성할 수 있습니다.
LSP용 WSAPROTOCOLINFOW 구조는 보통 층을 나누려는 하위 공급자로부터 복사됩니다
1 szProtocol 도메인을 수정하여 새 공급자의 이름을 포함합니다.
2 XP1 이 포함된 경우IFS_HANDLES ID dwServiceFlags1 도메인에서 제거합니다.
WSCWriteProviderOrder 순서재정리
새로 설치된 LSP는 기본적으로 winsock 디렉터리의 끝에 설치되어 있으며, 시스템이 호출될 때 원래 호출된 LSP를 호출하기 때문에, 다시 정렬해야만 시스템이 새로 설치된 LSP로 호출될 수 있습니다.
요약:
1 계층형 프로토콜 포털을 설치하여 시스템에서 할당한 디렉토리 ID 번호를 가져옵니다.
2 하나 이상의 프로토콜 체인을 설치한다. 설치 수량은 층을 나누는 하위 프로토콜의 수량에 달려 있다.
3 디렉토리는 끝에서 정렬됩니다.
코드 예:
////////////////////////////////////////////////////////
// InstDemo.cpp
#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
// 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;
//
if(::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError) == SOCKET_ERROR)
{
if(nError != WSAENOBUFS)
return NULL;
}
pProtoInfo = (LPWSAPROTOCOL_INFOW)::GlobalAlloc(GPTR, dwSize);
*lpnTotalProtocols = ::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError);
return pProtoInfo;
}
void FreeProvider(LPWSAPROTOCOL_INFOW pProtoInfo)
{
::GlobalFree(pProtoInfo);
}
// LSP UDP
int InstallProvider(WCHAR *wszDllPath)
{
WCHAR wszLSPName[] = L"TinyLSP"; // LSP
int nError = NO_ERROR;
LPWSAPROTOCOL_INFOW pProtoInfo;
int nProtocols;
WSAPROTOCOL_INFOW UDPLayeredInfo, UDPChainInfo; // UDP
DWORD dwUdpOrigCatalogId, dwLayeredCatalogId;
// Winsock UDP , LSP
//
pProtoInfo = GetProvider(&nProtocols);
for(int i=0; i<nProtocols; i++)
{
if(pProtoInfo[i].iAddressFamily == AF_INET && pProtoInfo[i].iProtocol == IPPROTO_UDP)
{
memcpy(&UDPChainInfo, &pProtoInfo[i], sizeof(UDPLayeredInfo));
//
UDPChainInfo.dwServiceFlags1 = UDPChainInfo.dwServiceFlags1 & ~XP1_IFS_HANDLES;
// ID
dwUdpOrigCatalogId = pProtoInfo[i].dwCatalogEntryId;
break;
}
}
// , Winsock ID , dwLayeredCatalogId
// WSAPROTOCOL_INFOW
memcpy(&UDPLayeredInfo, &UDPChainInfo, sizeof(UDPLayeredInfo));
// , , PFL_HIDDEN
wcscpy(UDPLayeredInfo.szProtocol, wszLSPName);
UDPLayeredInfo.ProtocolChain.ChainLen = LAYERED_PROTOCOL; // LAYERED_PROTOCOL 0
UDPLayeredInfo.dwProviderFlags |= PFL_HIDDEN;
//
if(::WSCInstallProvider(&ProviderGuid,
wszDllPath, &UDPLayeredInfo, 1, &nError) == SOCKET_ERROR)
return nError;
// , 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];
swprintf(wszChainName, L"%ws over %ws", wszLSPName, UDPChainInfo.szProtocol);
wcscpy(UDPChainInfo.szProtocol, wszChainName);
if(UDPChainInfo.ProtocolChain.ChainLen == 1)
{
UDPChainInfo.ProtocolChain.ChainEntries[1] = dwUdpOrigCatalogId;
}
else
{
for(i=UDPChainInfo.ProtocolChain.ChainLen; i>0 ; i--)
{
UDPChainInfo.ProtocolChain.ChainEntries[i] = UDPChainInfo.ProtocolChain.ChainEntries[i-1];
}
}
UDPChainInfo.ProtocolChain.ChainLen ++;
//
UDPChainInfo.ProtocolChain.ChainEntries[0] = dwLayeredCatalogId;
// Guid,
GUID ProviderChainGuid;
if(::UuidCreate(&ProviderChainGuid) == RPC_S_OK)
{
if(::WSCInstallProvider(&ProviderChainGuid,
wszDllPath, &UDPChainInfo, 1, &nError) == SOCKET_ERROR)
return nError;
}
else
return GetLastError();
// Winsock ,
//
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;
}
//
for(i=0; i<nProtocols; i++)
{
if((pProtoInfo[i].ProtocolChain.ChainLen <= 1) ||
(pProtoInfo[i].ProtocolChain.ChainEntries[0] != dwLayeredCatalogId))
dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;
}
// Winsock
nError = ::WSCWriteProviderOrder(dwIds, nIndex);
FreeProvider(pProtoInfo);
return nError;
}
void RemoveProvider()
{
LPWSAPROTOCOL_INFOW pProtoInfo;
int nProtocols;
DWORD dwLayeredCatalogId;
// Guid ID
pProtoInfo = GetProvider(&nProtocols);
int nError;
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);
}
}
//
::WSCDeinstallProvider(&ProviderGuid, &nError);
}
}
////////////////////////////////////////////////////
int binstall = 0;
void main()
{
if(binstall)
{
if(InstallProvider(L"lsp.dll") == ERROR_SUCCESS)
{
printf(" Install successully
");
}
else
{
printf(" Install failed
");
}
}
else
RemoveProvider();
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.