http://blog.chinaunix.net/uid/16979052.html
全部博文(286)
分类: LINUX
2013-03-11 08:18:24
目录
Winsock 2 SPI 工作在 API 之下 Driver 之上,属于应用层的范畴。利用这项技术可以截获所有的基于 Socket 的网络通信。比如:IE、OUTLOOK 等常见的应用程序都是使用Socket进行通信。
索引关键字:Winsock,SPI
工作在应用层,以DLL的形式存在,编程、调试方便。
可以直接在Windows 98/ME/NT/2000/XP上通用,Windows 95 只需安装上Winsock 2 for 95,也可以正常运行。
效率高,由于工作在应用层,CPU占用率低。
封包还没有按照低层协议进行切片,所以比较完整,很容易做内容过滤。
做防色情之类的软件,不用根据具体的浏览器进行分别编程,既简单又安全。
不用Socket的网络通信无法拦截,比如:使用NetBios的网上邻居,和使用ICMP协议的Ping。
微软对SPI设计的问题,导致如果安装顺序出错很容易造成网络瘫痪。这意味着如果同时安装几个使用SPI技术的软件,而且有使用非标准安装方式的软件,很容易有的被绕过或者不能正常网络通信。所以建议编写SPI程序一定要用标准的安装方式。
例子采用windows XP平台,使用Mingw GCC 3.4.4(也可使用MSVC)
Filter.def |
LIBRARY FILTER.DLL EXPORTS WSPStartup; |
Filter.h |
#ifndef FILTER_HEADER_INCLUDE__28OQ3FJ928FJAS_09Q83FJ_0988 #define FILTER_HEADER_INCLUDE__28OQ3FJ928FJAS_09Q83FJ_0988
#define UNICODE #define _UNICODE
#include
#include
typedef int (CALLBACK* LPRECV)(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPINT lpErrno); typedef int (CALLBACK* LPRECVFROM)(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct sockaddr FAR * lpFrom, LPINT lpFromlen, LPINT lpErrno); typedef int (CALLBACK* LPSEND)(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, LPINT lpErrno); typedef int (CALLBACK* LPSENDTO)(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, const struct sockaddr FAR * lpTo, int iTolen, LPINT lpErrno); typedef int (CALLBACK* LPCONNECT)(SOCKET s, struct sockaddr* name, int namelen); typedef int (CALLBACK* LPCONNECTED)(WSPPROC_TABLE NextProcTable, SOCKET s, struct sockaddr* name, const struct sockaddr FAR * orgname, int namelen);
GUID FilterGuid = { /* e62a1395-94cc-4bea-ad9a-b9d6c5bd2ea7 */ 0xe62a1395, 0x94cc, 0x4bea, {0xad, 0x9a, 0xb9, 0xd6, 0xc5, 0xbd, 0x2e, 0xa7} };
#define RecvFuncName "Recv" #define RecvFromFuncName "RecvFrom" #define SendFuncName "Send" #define SendToFuncName "SendTo" #define ConnectFuncName "Connect" #define ConnectedFuncName "Connected"
#define CONFIGURATION_KEY L"SOFTWARE\\WinSock2\\JohnYin Layered Provider" #define CFG_KEY_NAME L"CONFIG" #endif |
Filter.cpp |
#define UNICODE #define _UNICODE
#include "Filter.h"
#include
TCHAR PlugName[MAX_PATH] __attribute__((section ("Shared"), shared)) = L"Log.dll"; int Counter __attribute__((section ("Shared"), shared)) = 0;
#ifdef __cplusplus extern "C" { #endif int WSPAPI WSPRecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno); 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); int WSPAPI WSPSend(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno); int WSPAPI WSPSendTo(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); int WSPAPI WSPConnect(SOCKET s, const struct sockaddr FAR * name, int namelen, LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS, LPQOS lpGQOS, LPINT lpErrno); int WSPAPI WSPStartup(WORD wVersionRequested, LPWSPDATA lpWSPData, LPWSAPROTOCOL_INFOW lpProtocolInfo, WSPUPCALLTABLE UpcallTable, LPWSPPROC_TABLE lpProcTable); #ifdef __cplusplus } #endif
LPWSAPROTOCOL_INFOW protoinfo; WSPPROC_TABLE NextProcTable;
LPRECV CBRecv = NULL; LPRECVFROM CBRecvFrom = NULL; LPSEND CBSend = NULL; LPSENDTO CBSendTo = NULL; LPCONNECT CBConnect = NULL; LPCONNECTED CBConnected = NULL;
void LogBin(const TCHAR* fn, const char* buf, size_t len) { HANDLE m_hLogFile = ::CreateFile(fn, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, HANDLE(NULL)); if (m_hLogFile == INVALID_HANDLE_VALUE) return; SetFilePointer(m_hLogFile, 0, 0, SEEK_END); unsigned long ret; WriteFile (m_hLogFile, buf, len, &ret, NULL); CloseHandle(m_hLogFile); } void Error(const char* msg) { LogBin(L"C:\\log.txt", msg, strlen(msg)); } void LoadPlugIn() { HKEY hkey; LONG lresult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, CONFIGURATION_KEY, 0, KEY_ALL_ACCESS, &hkey); if (ERROR_SUCCESS != lresult) return;
DWORD dwtype, sl = MAX_PATH; lresult = RegQueryValueEx(hkey, CFG_KEY_NAME, NULL, &dwtype, (LPBYTE)PlugName, &sl); if (ERROR_SUCCESS == lresult) { HINSTANCE hfilter; if((hfilter=LoadLibrary(PlugName))!=NULL) { CBRecv = (LPRECV)GetProcAddress(hfilter,RecvFuncName); CBRecvFrom = (LPRECVFROM)GetProcAddress(hfilter,RecvFromFuncName); CBSend = (LPSEND)GetProcAddress(hfilter,SendFuncName); CBSendTo = (LPSENDTO)GetProcAddress(hfilter,SendToFuncName); CBConnect = (LPCONNECT)GetProcAddress(hfilter,ConnectFuncName); CBConnected = (LPCONNECTED)GetProcAddress(hfilter,ConnectedFuncName); } } RegCloseKey(hkey); } BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: break; case DLL_THREAD_ATTACH: LoadPlugIn(); break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return TRUE; } int GetFilter() { protoinfo = NULL; DWORD protoinfosize = 0; int errorcode; if(WSCEnumProtocols(NULL, protoinfo, &protoinfosize, &errorcode)==SOCKET_ERROR) { if(errorcode!=WSAENOBUFS) return SOCKET_ERROR; } if((protoinfo=(LPWSAPROTOCOL_INFOW)GlobalAlloc(GPTR,protoinfosize))==NULL) return SOCKET_ERROR; return WSCEnumProtocols(NULL,protoinfo,&protoinfosize,&errorcode); } void FreeFilter() { GlobalFree(protoinfo); } int WSPAPI WSPStartup(WORD wVersionRequested, LPWSPDATA lpWSPData, LPWSAPROTOCOL_INFOW lpProtocolInfo, WSPUPCALLTABLE UpcallTable, LPWSPPROC_TABLE lpProcTable) { LoadPlugIn(); int errorcode; if(lpProtocolInfo->ProtocolChain.ChainLen<=1) { Error("[WSPStartup]ProtocolChain Length <= 1\n"); return WSAECONNABORTED; } int totalprotos = GetFilter(); if (totalprotos == SOCKET_ERROR) { Error("[WSPStartup]GetFilter return false\n"); return WSAECONNABORTED; }
int i; DWORD layerid = 0; DWORD nextlayerid = 0;
for(i=0;
i { if(memcmp(&protoinfo[i].ProviderId,&FilterGuid,sizeof(GUID))==0) { layerid=protoinfo[i].dwCatalogEntryId; break; } }
for(i=0;i { if(lpProtocolInfo->ProtocolChain.ChainEntries[i]==layerid) { nextlayerid=lpProtocolInfo->ProtocolChain.ChainEntries[i+1]; break; } }
int filterpathlen=MAX_PATH; TCHAR* filterpath=(TCHAR*)GlobalAlloc(GPTR,filterpathlen);
for(i=0;i { if(nextlayerid==protoinfo[i].dwCatalogEntryId) { if(WSCGetProviderPath(&protoinfo[i].ProviderId,filterpath,&filterpathlen,&errorcode)==SOCKET_ERROR) { Error("[WSPStartup]WSCGetProviderPath return false\n"); return WSAEPROVIDERFAILEDINIT; } break; } }
if(!ExpandEnvironmentStrings(filterpath, filterpath, MAX_PATH)) { Error("[WSPStartup]ExpandEnvironmentStrings return false\n"); return WSAEPROVIDERFAILEDINIT; } HINSTANCE hfilter; if((hfilter=LoadLibrary(filterpath))==NULL) { Error("[WSPStartup]LoadLibrary return false\n"); return WSAEPROVIDERFAILEDINIT; } LPWSPSTARTUP WSPStartupFunc = NULL; if((WSPStartupFunc=(LPWSPSTARTUP)GetProcAddress(hfilter,"WSPStartup"))==NULL) { Error("[WSPStartup]GetProcAddress return false\n"); return WSAEPROVIDERFAILEDINIT; } if((errorcode=WSPStartupFunc(wVersionRequested,lpWSPData,lpProtocolInfo,UpcallTable,lpProcTable))!=ERROR_SUCCESS) { Error("[WSPStartup]WSPStartupFunc return false\n"); return errorcode; } NextProcTable=*lpProcTable; lpProcTable->lpWSPSend = WSPSend; lpProcTable->lpWSPSendTo = WSPSendTo; lpProcTable->lpWSPRecv = WSPRecv; lpProcTable->lpWSPRecvFrom = WSPRecvFrom; lpProcTable->lpWSPConnect = WSPConnect;
FreeFilter(); // Set the version info lpWSPData->wVersion = MAKEWORD(2,2); lpWSPData->wHighVersion = MAKEWORD(2,2);
return NO_ERROR; } int WSPAPI WSPSend(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno) { int retVal = NO_ERROR; if(lpOverlapped) Error("WSPSend Overlapped NO SUPPORT now !!!!!!!!!!!!!!!!!!!!!!!\n"); if(CBSend) retVal = CBSend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpErrno); if(retVal == NO_ERROR) retVal = NextProcTable.lpWSPSend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno); return retVal; } int WSPAPI WSPRecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno) { int retVal = NO_ERROR; if(lpOverlapped) Error("WSPRecv Overlapped NO SUPPORT now !!!!!!!!!!!!!!!!!!!!!!!\n"); retVal = NextProcTable.lpWSPRecv(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno); if((CBRecv)&&(retVal==NO_ERROR)) retVal = CBRecv(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpErrno); return retVal; } int WSPAPI WSPSendTo(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) { int retVal = NO_ERROR; if(lpOverlapped) Error("WSPSendTo Overlapped NO SUPPORT now !!!!!!!!!!!!!!!!!!!!!!!\n"); if(CBSendTo) retVal = CBSendTo(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo, iTolen, lpErrno); if(retVal == NO_ERROR) retVal = NextProcTable.lpWSPSendTo(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo, iTolen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno); return retVal; } 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) { int retVal = NO_ERROR; if(lpOverlapped) Error("WSPRecvFrom Overlapped NO SUPPORT now !!!!!!!!!!!!!!!!!!!!!!!\n"); retVal = NextProcTable.lpWSPRecvFrom(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno); if((CBRecvFrom)&&(retVal==NO_ERROR)) retVal = CBRecvFrom(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, lpErrno); return retVal; } int WSPAPI WSPConnect(SOCKET s, const struct sockaddr FAR * name, int namelen, LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS, LPQOS lpGQOS, LPINT lpErrno) { int retVal = NO_ERROR; struct sockaddr myname; memcpy(&myname, name, namelen); if(CBConnect) retVal = CBConnect(s, &myname, namelen); if(retVal == NO_ERROR) retVal = NextProcTable.lpWSPConnect(s, &myname, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, lpErrno); if((retVal == NO_ERROR)&&(CBConnected)) retVal = CBConnected(NextProcTable, s, &myname, name, namelen); return retVal; } |
Makefile |
#comment SRC=Filter.cpp
RC = version.rc
EXE=Filter.dll
CPPDIR=E:/Mingw LIBS = -L"$(CPPDIR)/lib" INCS = -I"$(CPPDIR)/include" -I"$(CPPDIR)/include/g++-3" -I"$(CPPDIR)/include"
RES=$(RC:.rc=.res) OBJ=$(SRC:.cpp=.o)
CC=g++ DLL=dllwrap.exe WINDRES = windres.exe RM=rm
# -gcoff let me to gen debug info for purify 4 windows DEBUG= #-gcoff CFLAGS=-Wall -O3 $(DEBUG) $(INCS) LDFLAGS=-S #-mwindows DLLFLAGS= --def Filter.def LIBFLAGS= -lws2_32 -ladvapi32
%.o: %.cpp $(CC) $(CFLAGS) -o $@ -c $<
%.res: %.rc $(WINDRES) -i $< -O coff --input-format=rc -o $@
# .PHONY ignores files named all .PHONY : all all: $(EXE) # $(EXE) is dependent on all of the files in $(OBJ) to exist
$(EXE): $(OBJ) $(RES) $(DLL) $(DLLFLAGS) --dllname $@ $(OBJ) $(RES) $(LIBFLAGS)
.PHONY : clean clean: -$(RM) $(OBJ) $(EXE) $(RES) # '-' causes errors not to exit the process
|
testplugin.cpp |
#include "Filter.h"
#include
#ifdef __cplusplus extern "C" { #endif int CALLBACK Connect(SOCKET s, struct sockaddr* name, int namelen); int CALLBACK Connected(WSPPROC_TABLE NextProcTable, SOCKET s, struct sockaddr* name, const struct sockaddr FAR * orgname, int namelen); int SPISockSend(LPWSPSEND lpWSPSend, SOCKET sock, char* Buf, int len); int SPISockRecv(LPWSPRECV lpWSPRecv, SOCKET sock, char* Buf, int len); #ifdef __cplusplus } #endif int CALLBACK Connect(SOCKET s, struct sockaddr* name, int namelen) { 。。。。。。。 return NO_ERROR; } int CALLBACK Connected(WSPPROC_TABLE NextProcTable, SOCKET s, struct sockaddr* name, const struct sockaddr FAR * orgname, int namelen) { 。。。。。。。 return NO_ERROR; }
int SPISockSend(LPWSPSEND lpWSPSend, SOCKET sock, char* Buf, int len) { 。。。。。。。 return lpNumberOfBytesSent; } int SPISockRecv(LPWSPRECV lpWSPRecv, SOCKET sock, char* Buf, int len) { 。。。。。。。 return lpNumberOfBytesRecv; } BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE;
|