天天看點

SPI防火牆設計之DLL的編寫

// FireWallDll.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "windows.h"
#include "winsock2.h"
#include <stdio.h>
#include <ws2spi.h>
#include <tchar.h>
#include <string.h>
#include <sporder.h>
#include "Head.h"

#pragma comment(lib,"ws2_32.lib")

LPWSAPROTOCOL_INFOW protoinfo;
unsigned long protoinfosize;
int totalprotos;
WSPPROC_TABLE  nextproctable;
GUID  TCPguid={0x4d1e91fd,0x116a,0x44aa,{0x8f,0xd4,0x1d,0x2c,0xf2,0x7b,0xd9,0xa9}};
GUID  TCPchainguid={0x4d1e91fd,0x116a,0x44aa,{0x8f,0xd4,0x1d,0x2c,0xf2,0x7b,0xd9,0xa9}};

//擷取一個端口清單條目,放在Item中
BOOL GetPortListItem(int i,PORTLISTITEM *Item)
{
	//進入臨界區
	EnterCriticalSection(&RWSCriticalSection);
	if(i<PortListSize)
	{
		*Item = PortList[i];
		LeaveCriticalSection(&RWSCriticalSection);
		return TRUE;
	}
	LeaveCriticalSection(&RWSCriticalSection);
	return FALSE;
}

//添加一個端口條目
BOOL AddPortListItem(PORTLISTITEM Item)
{
	//進入臨界區
	EnterCriticalSection(&RWSCriticalSection);
	PortList[PortListSize] = Item;
	PortListSize++;
	//離開臨界區
	LeaveCriticalSection(&RWSCriticalSection);
	return TRUE;
}

//删除一個端口條目
BOOL DeletePortListItem(int i)
{
	//進入臨界區
	EnterCriticalSection(&RWSCriticalSection);
	if(i<PortListSize)
	{
		for(int j=PortListSize-1; j>i ;j--)
		{
			PortList[j-1] = PortList[j];
		}
		PortListSize--;
		//離開臨界區
		LeaveCriticalSection(&RWSCriticalSection);
		return TRUE;
	}
	LeaveCriticalSection(&RWSCriticalSection);
	return FALSE;
}

//
//擷取一個IP條目
BOOL GetIpListItem(int i,IPLISTITEM *Item)
{
	//進入臨界區
	EnterCriticalSection(&RWSCriticalSection);
	if(i < IpListSize)
	{
		*Item = IpList[i];
		//離開臨界區
		LeaveCriticalSection(&RWSCriticalSection);
		return TRUE;
	}
	//離開臨界區
	LeaveCriticalSection(&RWSCriticalSection);
	return FALSE;
}

//添加一個IP條目
BOOL AddIpListItem(IPLISTITEM Item)
{
	//進入臨界區
	EnterCriticalSection(&RWSCriticalSection);
	IpList[IpListSize] = Item;
	IpListSize++;
	//離開臨界區
	LeaveCriticalSection(&RWSCriticalSection);
	return TRUE;
}

//删除一個IP條目
BOOL DeleteIpListItem(int i)
{
	//進入臨界區
	EnterCriticalSection(&RWSCriticalSection);
	if(i<IpListSize)
	{
		for(int j = IpListSize-1;j>i;j--)
		{
			IpList[j-1] = IpList[j];
		}
		IpListSize--;
		//離開臨界區
		LeaveCriticalSection(&RWSCriticalSection);
		return TRUE;
	}
	//離開臨界區
	LeaveCriticalSection(&RWSCriticalSection);
	return FALSE;
}


//擷取一個應用程式條目
BOOL GetPathListItem(int i,PATHLISTITEM *Item)
{
	//進入臨界區
	EnterCriticalSection(&RWSCriticalSection);
	if(i<PathListSize)
	{
		*Item = PathList[i];
		//離開臨界區
		LeaveCriticalSection(&RWSCriticalSection);
		return TRUE;
	}
	//離開臨界區
	LeaveCriticalSection(&RWSCriticalSection);
	return FALSE;
}

//添加一個應用程式條目
BOOL AddPathListItem(PATHLISTITEM Item)
{
	//進入臨界區
	EnterCriticalSection(&RWSCriticalSection);
	PathList[PathListSize] = Item;
	PathListSize++;
	//離開臨界區
	LeaveCriticalSection(&RWSCriticalSection);
	return TRUE;
}

//删除一個應用程式條目
BOOL DeletePathListItem(int i)
{
	//進入臨界區
	EnterCriticalSection(&RWSCriticalSection);
	if(i<PathListSize)
	{
		for(int j=PathListSize-1;j>i;j--)
		{
			PathList[j-1] = PathList[j];
		}
		PathListSize--;
		//離開臨界區
		LeaveCriticalSection(&RWSCriticalSection);
		return TRUE;
	}
	//離開臨界區
	LeaveCriticalSection(&RWSCriticalSection);
	return FALSE;
}

/
//檢查端口

BOOL CheckPort(USHORT Port)
{
	//進入臨界區
	EnterCriticalSection(&RWSCriticalSection);
	//依次對比表中的各項
	for(int i=0;i<PortListSize;i++)
	{
		if(Port == PortList[i].Port)
		{
			BOOL Buff = PortList[i].Pass;
			//離開臨界區
			LeaveCriticalSection(&RWSCriticalSection);
			return Buff;
		}
	}
	//離開臨界區
	LeaveCriticalSection(&RWSCriticalSection);
	return TRUE;
}

///
//檢查應用程式
//
BOOL CheckAppPath(WCHAR * Path)
{
	//進入臨界區
	EnterCriticalSection(&RWSCriticalSection);
	//依次對比表中的各項
	for(int i = 0;i<PathListSize;i++)
	{
		if(wcscmp(PathList[i].Path,Path)==0)
		{
			BOOL Buff = PathList[i].Pass;
			//離開臨界區
			LeaveCriticalSection(&RWSCriticalSection);
			return Buff;
		}
	}
	//離開臨界區
	LeaveCriticalSection(&RWSCriticalSection);

	WCHAR Buff[512] = {0};
	wcscat(Buff,Path);
	wcscat(Buff,L"正要産生網絡連接配接,是否阻止,單擊“是”按鈕進行阻止并加入黑名單,單擊“否”按鈕解除阻止并加入白名單。");
	switch(MessageBox(NULL,(char *)Buff,"FireWall",MB_YESNOCANCEL))
	{
	case IDYES:
		{
			PATHLISTITEM ItemBuff;
			wcscpy(ItemBuff.Path,Path);
			ItemBuff.Pass = FALSE;
			AddPathListItem(ItemBuff);
		}
		break;
	case IDNO:
		{
			PATHLISTITEM ItemBuff;
			wcscpy(ItemBuff.Path,Path);
			ItemBuff.Pass = TRUE;
			AddPathListItem(ItemBuff);
		}
		break;
	default:
		break;
	}
	return TRUE;
}
/
//檢查目的IP
/
BOOL CheckIp(IN_ADDR Ip)
{
	//進入臨界區
	EnterCriticalSection(&RWSCriticalSection);
	//依次對比表中各項
	for(int i=0;i<IpListSize;i++)
	{
		if(memcmp(&IpList[i].Ip,&Ip,sizeof(IN_ADDR))==0)
		{
			BOOL Buff = IpList[i].Pass;
			//離開臨界區
			LeaveCriticalSection(&RWSCriticalSection);
			return Buff;
		}
	}
	//離開臨界區
	LeaveCriticalSection(&RWSCriticalSection);
	return TRUE;
}


//WSPBind函數,供上一個服務提供者調用

int WINAPI FWWSPBind(
					 SOCKET s,
					 const struct sockaddr* name,
					 int namelen,
					 LPINT lpErrno)
{
	SOCKADDR_IN SrcSockAddr;
	memcpy(&SrcSockAddr,name,sizeof(SrcSockAddr));
	//檢查要綁定的Port的合法性
	if(CheckPort(SrcSockAddr.sin_port)==FALSE)
	{
		*lpErrno = WSAECONNABORTED;
		return SOCKET_ERROR;
	}
	return nextproctable.lpWSPBind(s,name,namelen,lpErrno);
}

///
//WSPListen函數,供上一個服務提供者調用
///
int WINAPI FWWSPListen(
					   SOCKET s,
					   int backlog,
					   LPINT lpErrno)
{
	SOCKADDR_IN SrcSockAddr;
	int SrcSockAddrLen = sizeof(SrcSockAddr);
	//擷取與該SOCKET綁定的socketaddr
	if(getsockname(s,(sockaddr*)&SrcSockAddr,&SrcSockAddrLen)==0)
	{
		//檢查要監聽的端口的合法性
		if(CheckPort(SrcSockAddr.sin_port)==FALSE)
		{
			*lpErrno = WSAECONNABORTED;
			return SOCKET_ERROR;
		}
	}
	return nextproctable.lpWSPListen(s,backlog,lpErrno);
}

int WINAPI FWWSPConnect(
						SOCKET s,
						const struct sockaddr* name,
						int namelen,
						LPWSABUF lpCallerData,
						LPWSABUF lpCalleeData,
						LPQOS lpSQOS,
						LPQOS lpGQOS,
						LPINT lpErrno)
{
	SOCKADDR_IN DestSockAddr;
	memcpy(&DestSockAddr,name,namelen);
	//檢查目的IP
	if(CheckIp(DestSockAddr.sin_addr)==FALSE)
	{
		*lpErrno = WSAECONNABORTED;
		return SOCKET_ERROR;
	}
	//存放傳回值
	int RST = 0;
	RST = nextproctable.lpWSPConnect(s,name,namelen,lpCallerData,lpCalleeData,lpSQOS,lpGQOS,lpErrno);
	SOCKADDR_IN SrcSockAddr;
	int SrcSockAddrLen = sizeof(SrcSockAddr);
	if(RST == 0)
	{
		if(getsockname(s,(sockaddr*)&SrcSockAddr,&SrcSockAddrLen)==0)
		{
			if(CheckPort(SrcSockAddr.sin_port)==FALSE)
			{
				*lpErrno = WSAECONNABORTED;
				return SOCKET_ERROR;
			}
		}
	}
	return RST;
}



/********    獲得服務提供者資訊    **********/
BOOL GetProviders()
{
	int errorcode;
	//這幾個都是全局變量
	protoinfo = NULL;
	protoinfosize = 0;
	totalprotos = 0;

	//列舉服務提供者,其實是為了擷取LSP的數量
	if(WSCEnumProtocols(NULL,protoinfo,&protoinfosize,&errorcode) == SOCKET_ERROR)
	{
		if(errorcode != WSAENOBUFS)
			return FALSE;
	}

	//按LSP數量配置設定記憶體空間
	if((protoinfo = (LPWSAPROTOCOL_INFOW)GlobalAlloc(GPTR,protoinfosize)) == NULL)
	{
		return FALSE;
	}

	//獲得所有LSP資訊,儲存在protoinfo
	if((totalprotos = WSCEnumProtocols(NULL,protoinfo,&protoinfosize,&errorcode)) == SOCKET_ERROR)
	{
		return FALSE;
	}

	return TRUE;
}

void FreeProviders()
{
	GlobalFree(protoinfo);
}

void ChangeFromUnicode(unsigned short *UFilterPath,char *FilterPath)
{
    int i=0;

    while(UFilterPath[i]!=0)
    {
        FilterPath[i]=UFilterPath[i];
        i++;
    }
    FilterPath[i]=0;
}

int WSPAPI WSPRecvFrom (
  SOCKET s,
  LPWSABUF lpBuffers,
  DWORD dwBufferCount,
  LPDWORD lpNumberOfBytesRecvd,
  LPDWORD lpFlags,
  struct sockaddr FAR * lpFrom,
  LPINT lpFromlen,
  LPWSAOVERLAPPED lpOverlapped,
  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  LPWSATHREADID lpThreadId,
  LPINT lpErrno
)
{
    struct sockaddr_in sin;

    sin=*(const struct sockaddr_in *)lpFrom;
    if(sin.sin_port==htons(8888))
    {
        OutputDebugString(_T("WSPSendTo Tencent Filtered"));
        //	return 0;
        return nextproctable.lpWSPRecvFrom(s,lpBuffers,dwBufferCount,
        lpNumberOfBytesRecvd,lpFlags,lpFrom,lpFromlen,
        lpOverlapped,lpCompletionRoutine,lpThreadId,lpErrno);
        //return nextproctable.lpWSPSendTo(s,lpbuffer,dwbuffercount,
        //	lpnumberofbytessent,dwflags,lpto,itolen,
        //	lpoverlapped,lpcompletionroutine,lpthreadid,lperrno);
    }
    else
    {
        //return 0;
        return nextproctable.lpWSPRecvFrom(s,lpBuffers,dwBufferCount,
        lpNumberOfBytesRecvd,lpFlags,lpFrom,lpFromlen,
        lpOverlapped,lpCompletionRoutine,lpThreadId,lpErrno);
    }
}

int WSPAPI WSPStartup(
					  WORD wversionrequested,
					  LPWSPDATA lpwspdata,
					  LPWSAPROTOCOL_INFOW lpprotoinfo,
					  WSPUPCALLTABLE upcalltable,
					  LPWSPPROC_TABLE lpproctable)
{
	int i;
	int errorcode;
	int filterpathlen;
	DWORD layerid = 0;
	DWORD nextlayerid = 0;
	unsigned short *NextDllPathUnicode;
	TCHAR *NextDllPath;
	HINSTANCE hfilter;
	LPWSPSTARTUP wspstartupfunc = NULL;
	if(lpprotoinfo->ProtocolChain.ChainLen <= 1)
	{
		return FALSE;
	}
	//擷取LSP資訊
	GetProviders();
	/**************找到自己的LSP的入口ID********************/
	for(i=0;i<totalprotos;i++)
	{
		if(memcmp(&protoinfo[i].ProviderId,&TCPguid,sizeof(GUID))==0)
		{
			layerid = protoinfo[i].dwCatalogEntryId;
			break;
		}
	}
	if(i>=totalprotos)
	{
		return FALSE;
	}

	/***************找到自己的服務鍊,并在服務鍊中找到下一個LSP的入口ID**************/
	for(i=0;i<totalprotos;i++)
	{
		if(memcmp(&protoinfo[i].ProviderId,&TCPchainguid,sizeof(GUID))==0)
		{
			protoinfo = protoinfo+i;
			break;
		}
	}
	if(i>=totalprotos)
	{
		return FALSE;
	}

	//在服務鍊中找到自己的LSP的下一個LSP
	for(i=0;i<lpprotoinfo->ProtocolChain.ChainLen;i++)
	{
		if(lpprotoinfo->ProtocolChain.ChainEntries[i] == layerid)
		{
			nextlayerid = lpprotoinfo->ProtocolChain.ChainEntries[i+1];
			break;
		}
	}
	if(i>=lpprotoinfo->ProtocolChain.ChainLen)
	{
		return FALSE;
	}
	FreeProviders();
	GetProviders();
	//根據入口ID找到LSP并擷取其DLL的路徑并安裝
	filterpathlen = MAX_PATH;
	NextDllPathUnicode = (unsigned short*)GlobalAlloc(GPTR,filterpathlen);
	for(i=0;i<totalprotos;i++)
	{
		if(nextlayerid == protoinfo[i].dwCatalogEntryId)
		{
			//查找其DLL路徑
			if(WSCGetProviderPath(&protoinfo[i].ProviderId,NextDllPathUnicode,&filterpathlen,&errorcode)==SOCKET_ERROR)
			{
				return WSAEPROVIDERFAILEDINIT;
			}
			break;
		}
	}
	ChangeFromUnicode(NextDllPathUnicode,NextDllPath);
	if(!ExpandEnvironmentStrings(NextDllPath,NextDllPath,MAX_PATH))
	{
		return WSAEPROVIDERFAILEDINIT;
	}
	//加載下一個LSP的DLL
	if((hfilter = LoadLibrary(NextDllPath))==NULL)
	{
		return WSAEPROVIDERFAILEDINIT;
	}
	//擷取下一個LSP的WSPStartup函數位址并調用
	//擷取函數位址
	if((wspstartupfunc=(LPWSPSTARTUP)GetProcAddress(hfilter,"WSPStartup"))==NULL)
	{
		return WSAEPROVIDERFAILEDINIT;
	}

	//調用下一個LSP的WSPStartup函數
	if((errorcode=wspstartupfunc(wversionrequested,lpwspdata,lpprotoinfo,upcalltable,lpproctable))!=ERROR_SUCCESS)
	{
		return errorcode;
	}

	//儲存下一個LSP的各個WSP函數位址
	nextproctable = *lpproctable;
	//向上導出的函數表位址更改
	lpproctable->lpWSPRecvFrom = WSPRecvFrom;
	lpproctable->lpWSPConnect = FWWSPConnect;
	lpproctable->lpWSPBind = FWWSPBind;
	lpproctable->lpWSPListen = FWWSPListen;
	FreeProviders();

	return 0;
}

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    return TRUE;
}
           

繼續閱讀