轉自:http://blog.csdn.net/ze_tsin/article/details/6376831
SPI的出現其實就是微軟爲了方便程序員對網絡API的各種HOOK,從而省去一些麻煩,然而相對的也會增加不少問題。對於SPI中的LSP這種分層的結構,可以很好的使用強盜手法將自己當作老大放在最上層,但是,如果有其他程序也使用同樣的手法,那麼就會產生衝突了。
好吧進入正題。。。
一、LSP的安裝,先拋開socks代理不說
1、構造自己的LSP,並安裝之;
2、遍歷已有 服務提供者,找到剛安裝的LSP入口ID;
3、構造自己的協議鏈,並安裝之;
4、對所有協議鏈進行排序,並將我們的協議鏈放到最上面。
二、LSP的編寫
主要操作都在WSPStartup中,其他WSP函數就是對原函數的HOOK,詳情看下面代碼。
MSDN有完整LSP代碼的下載:
ftp://ftp.microsoft.com/bussys/WinSock/winsock2/layered.zip
同時,網上也有一些源代碼,與MSDN代碼相比,基本一樣,只是在LSP安裝的第一步有所不同,MSDN代碼是手工構造LSP,而網上許多代碼都是通過拷貝系統已有LSP進行對自己的LSP構造。
下面代碼來自網上:
INST_LSP.Cpp
- #define UNICODE
- #define _UNICODE
- #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);
- }
- BOOL InstallProvider(WCHAR *pwszPathName)
- {
- WCHAR wszLSPName[] = L"ZetsinLSP";
- LPWSAPROTOCOL_INFOW pProtoInfo;
- int nProtocols;
- WSAPROTOCOL_INFOW OriginalProtocolInfo[3];
- DWORD dwOrigCatalogId[3];
- int nArrayCount = 0;
- DWORD dwLayeredCatalogId; // 我們分層協議的目錄ID號
- int nError;
- // 找到我們的下層協議,將信息放入數組中
- // 枚舉所有服務程序提供者
- pProtoInfo = GetProvider(&nProtocols);
- BOOL bFindUdp = FALSE;
- BOOL bFindTcp = FALSE;
- BOOL bFindRaw = FALSE;
- for(int i=0; i<nProtocols; i++)
- {
- if(pProtoInfo[i].iAddressFamily == AF_INET)
- {
- if(!bFindUdp && pProtoInfo[i].iProtocol == IPPROTO_UDP)
- {
- memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
- OriginalProtocolInfo[nArrayCount].dwServiceFlags1 =
- OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
- dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
- bFindUdp = TRUE;
- }
- if(!bFindTcp && pProtoInfo[i].iProtocol == IPPROTO_TCP)
- {
- memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
- OriginalProtocolInfo[nArrayCount].dwServiceFlags1 =
- OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
- dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
- bFindTcp = TRUE;
- }
- if(!bFindRaw && pProtoInfo[i].iProtocol == IPPROTO_IP)
- {
- memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
- OriginalProtocolInfo[nArrayCount].dwServiceFlags1 =
- OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
- dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
- bFindRaw = TRUE;
- }
- }
- }
- // 安裝我們的分層協議,獲取一個dwLayeredCatalogId
- // 隨便找一個下層協議的結構複製過來即可
- WSAPROTOCOL_INFOW LayeredProtocolInfo;
- memcpy(&LayeredProtocolInfo, &OriginalProtocolInfo[0], sizeof(WSAPROTOCOL_INFOW));
- // 修改協議名稱,類型,設置PFL_HIDDEN標誌
- wcscpy_s(LayeredProtocolInfo.szProtocol, wszLSPName);
- LayeredProtocolInfo.ProtocolChain.ChainLen = LAYERED_PROTOCOL; // 0;
- LayeredProtocolInfo.dwProviderFlags |= PFL_HIDDEN;
- // 安裝
- if(::WSCInstallProvider(&ProviderGuid,
- pwszPathName, &LayeredProtocolInfo, 1, &nError) == SOCKET_ERROR)
- {
- printf("%d", nError);
- return FALSE;
- }
- // 重新枚舉協議,獲取分層協議的目錄ID號
- FreeProvider(pProtoInfo);
- pProtoInfo = GetProvider(&nProtocols);
- for(int i=0; i<nProtocols; i++)
- {
- if(memcmp(&pProtoInfo[i].ProviderId, &ProviderGuid, sizeof(ProviderGuid)) == 0)
- {
- dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId;
- break;
- }
- }
- // 安裝協議鏈
- // 修改協議名稱,類型
- WCHAR wszChainName[WSAPROTOCOL_LEN + 1];
- for(int i=0; i<nArrayCount; i++)
- {
- swprintf(wszChainName, L"%ws over %ws", wszLSPName, OriginalProtocolInfo[i].szProtocol);
- wcscpy_s(OriginalProtocolInfo[i].szProtocol, wszChainName);
- if(OriginalProtocolInfo[i].ProtocolChain.ChainLen == 1)
- {
- OriginalProtocolInfo[i].ProtocolChain.ChainEntries[1] = dwOrigCatalogId[i];
- }
- else
- {
- for(int j = OriginalProtocolInfo[i].ProtocolChain.ChainLen; j>0; j--)
- {
- OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j]
- = OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j-1];
- }
- }
- OriginalProtocolInfo[i].ProtocolChain.ChainLen ++;
- OriginalProtocolInfo[i].ProtocolChain.ChainEntries[0] = dwLayeredCatalogId;
- }
- // 獲取一個Guid,安裝之
- GUID ProviderChainGuid;
- if(::UuidCreate(&ProviderChainGuid) == RPC_S_OK)
- {
- if(::WSCInstallProvider(&ProviderChainGuid,
- pwszPathName, OriginalProtocolInfo, nArrayCount, &nError) == SOCKET_ERROR)
- {
- return FALSE;
- }
- }
- else
- return FALSE;
- // 重新排序Winsock目錄,將我們的協議鏈提前
- // 重新枚舉安裝的協議
- FreeProvider(pProtoInfo);
- pProtoInfo = GetProvider(&nProtocols);
- PDWORD dwIds = (PDWORD)malloc(sizeof(DWORD) * nProtocols);
- int nIndex = 0;
- // 添加我們的協議鏈
- for(int i=0; i<nProtocols; i++)
- {
- if((pProtoInfo[i].ProtocolChain.ChainLen > 1) &&
- (pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId))
- dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;
- }
- // 添加其它協議
- for(int i=0; i<nProtocols; i++)
- {
- if((pProtoInfo[i].ProtocolChain.ChainLen <= 1) ||
- (pProtoInfo[i].ProtocolChain.ChainEntries[0] != dwLayeredCatalogId))
- dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;
- }
- // 重新排序Winsock目錄
- if((nError = ::WSCWriteProviderOrder(dwIds, nIndex)) != ERROR_SUCCESS)
- {
- return FALSE;
- }
- FreeProvider(pProtoInfo);
- return TRUE;
- }
- BOOL RemoveProvider()
- {
- LPWSAPROTOCOL_INFOW pProtoInfo;
- int nProtocols;
- DWORD dwLayeredCatalogId;
- // 根據Guid取得分層協議的目錄ID號
- pProtoInfo = GetProvider(&nProtocols);
- int nError;
- int i;
- for(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);
- }
- else return FALSE;
- return TRUE;
- }
- void main(int argc, char *argv[])
- {
- char *ptr;
- //if(argc==2)
- {
- ptr = argv[1];
- while (*ptr)
- *ptr++ = tolower(*ptr);
- int test;
- scanf("%d", &test);
- if(test == 1)
- //if(strcmp(argv[1], "-install")==0)
- {
- TCHAR szPathName[256];
- TCHAR* p;
- if(::GetFullPathName(L"LSP.dll", 256, szPathName, &p) != 0)
- {
- if(InstallProvider(szPathName))
- {
- printf(" Install successully. /n");
- return;
- }
- }
- printf(" Install failed. /n");
- return;
- }
- else
- //else if(strcmp(argv[1],"-remove")==0)
- {
- if(RemoveProvider())
- printf(" Deinstall successully. /n");
- else
- printf(" Deinstall failed. /n");
- return;
- }
- }
- printf(" Usage: Instlsp [ -install │ -remove ] /n");
- }
LSP.Cpp
- #define UNICODE
- #define _UNICODE
- #include <ws2spi.h>
- #include <errno.h>
- #include <fstream>
- #pragma comment(lib,"Ws2_32.lib")
- GUID filterguid = {0xd3c21122, 0x85e1, 0x48f3,
- {0x9a,0xb6,0x23,0xd9,0x0c,0x73,0x07,0xef}};
- LPWSAPROTOCOL_INFOW ProtoInfo=NULL;
- WSPPROC_TABLE NextProcTable;
- DWORD ProtoInfoSize=0;
- int TotalProtos=0;
- // 輸出函數
- int PutDbgStr(LPCTSTR lpFmt, ...)
- {
- TCHAR Msg[1024];
- int len=wvsprintf(Msg,lpFmt,va_list(1+&lpFmt));
- OutputDebugString(Msg);
- return len;
- }
- // 獲取各種值
- BOOL GetLSP()
- {
- int errorcode;
- ProtoInfo=NULL;
- ProtoInfoSize=0;
- TotalProtos=0;
- if(WSCEnumProtocols(NULL,ProtoInfo,&ProtoInfoSize,&errorcode)==SOCKET_ERROR)
- {
- if(errorcode!=WSAENOBUFS)
- {
- PutDbgStr(L"First WSCEnumProtocols Error!");
- return FALSE;
- }
- }
- if((ProtoInfo=(LPWSAPROTOCOL_INFOW)GlobalAlloc(GPTR,ProtoInfoSize))==NULL)
- {
- PutDbgStr(L"GlobalAlloc Error!");
- return FALSE;
- }
- if((TotalProtos=WSCEnumProtocols(NULL,ProtoInfo,&ProtoInfoSize,&errorcode))==SOCKET_ERROR)
- {
- PutDbgStr(L"Second WSCEnumProtocols Error!");
- return FALSE;
- }
- return TRUE;
- }
- // 釋放內存
- void FreeLSP()
- {
- GlobalFree(ProtoInfo);
- }
- // DLL入口函數
- BOOL WINAPI DllMain(HINSTANCE hmodule,
- DWORD reason,
- LPVOID lpreserved)
- {
- TCHAR processname[MAX_PATH];
- if(reason==DLL_PROCESS_ATTACH)
- {
- GetModuleFileName(NULL,processname,MAX_PATH);
- PutDbgStr(L"%s Loading IPFilter ...", processname);
- }
- return TRUE;
- }
- /********************************* 改寫WSP函數,只有WSPConnect被改寫成調用socksProxy函數,其它的直接調用下層WSP函數 ****************************************/
- //WSPConnect
- int WSPAPI WSPConnect(
- SOCKET s,
- const struct sockaddr *name,
- int namelen,
- LPWSABUF lpCallerData,
- LPWSABUF lpCalleeData,
- LPQOS lpSQOS,
- LPQOS lpGQOS,
- LPINT lpErrno)
- {
- return NextProcTable.lpWSPConnect(s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, lpErrno);
- }
- }
- //WSPSocket
- SOCKET WINAPI WSPSocket(
- __in int af,
- __in int type,
- __in int protocol,
- __in LPWSAPROTOCOL_INFO lpProtocolInfo,
- __in GROUP g,
- DWORD dwFlags,
- __out LPINT lpErrno
- )
- {
- PutDbgStr(L"WSPSocket");
- return NextProcTable.lpWSPSocket(af, type, protocol, lpProtocolInfo, g, dwFlags, lpErrno);
- }
- //WSPBind
- int WINAPI WSPBind(
- __in SOCKET s,
- __in const struct sockaddr *name,
- __in int namelen,
- __out LPINT lpErrno
- )
- {
- PutDbgStr(L"WSPBind");
- return NextProcTable.lpWSPBind(s, name, namelen, lpErrno);
- }
- //WSPSend
- int WINAPI WSPSend(
- __in SOCKET s,
- __in LPWSABUF lpBuffers,
- __in DWORD dwBufferCount,
- __out LPDWORD lpNumberOfBytesSent,
- __in DWORD dwFlags,
- __in LPWSAOVERLAPPED lpOverlapped,
- __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
- __in LPWSATHREADID lpThreadId,
- __out LPINT lpErrno
- )
- {
- PutDbgStr(L"WSPSend");
- return NextProcTable.lpWSPSend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
- }
- //WSPSendTo
- int WINAPI WSPSendTo(
- __in SOCKET s,
- __in LPWSABUF lpBuffers,
- __in DWORD dwBufferCount,
- __out LPDWORD lpNumberOfBytesSent,
- __in DWORD dwFlags,
- __in const struct sockaddr *lpTo,
- __in int iTolen,
- __in LPWSAOVERLAPPED lpOverlapped,
- __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
- __in LPWSATHREADID lpThreadId,
- __out LPINT lpErrno
- )
- {
- PutDbgStr(L"WSPSendTo");
- return NextProcTable.lpWSPSendTo(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo, iTolen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
- }
- //WSPRecv
- int WINAPI WSPRecv(
- __in SOCKET s,
- __inout LPWSABUF lpBuffers,
- __in DWORD dwBufferCount,
- __out LPDWORD lpNumberOfBytesRecvd,
- __inout LPDWORD lpFlags,
- __in LPWSAOVERLAPPED lpOverlapped,
- __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
- __in LPWSATHREADID lpThreadId,
- __out LPINT lpErrno
- )
- {
- PutDbgStr(L"WSPRecv");
- return NextProcTable.lpWSPRecv(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
- }
- //WSPRecvFrom
- int WINAPI WSPRecvFrom(
- __in SOCKET s,
- __inout LPWSABUF lpBuffers,
- __in DWORD dwBufferCount,
- __out LPDWORD lpNumberOfBytesRecvd,
- __inout LPDWORD lpFlags,
- __out struct sockaddr *lpFrom,
- __inout LPINT lpFromlen,
- __in LPWSAOVERLAPPED lpOverlapped,
- __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
- __in LPWSATHREADID lpThreadId,
- __inout LPINT lpErrno
- )
- {
- PutDbgStr(L"WSPRecvFrom");
- return NextProcTable.lpWSPRecvFrom(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
- }
- //WSPStartup
- int WSPAPI WSPStartup(
- WORD wversionrequested,
- LPWSPDATA lpwspdata,
- LPWSAPROTOCOL_INFOW lpProtoInfo,
- WSPUPCALLTABLE upcalltable,
- LPWSPPROC_TABLE lpproctable
- )
- {
- PutDbgStr(L"IPFilter WSPStartup ...");
- int i;
- int errorcode;
- int filterpathlen;
- DWORD layerid=0;
- DWORD nextlayerid=0;
- TCHAR *filterpath;
- HINSTANCE hfilter;
- LPWSPSTARTUP wspstartupfunc=NULL;
- if(lpProtoInfo->ProtocolChain.ChainLen<=1)
- {
- PutDbgStr(L"ChainLen<=1");
- return FALSE;
- }
- GetLSP();
- for(i=0;i<TotalProtos;i++)
- {
- if(memcmp(&ProtoInfo[i].ProviderId,&filterguid,sizeof(GUID))==0)
- {
- layerid=ProtoInfo[i].dwCatalogEntryId;
- break;
- }
- }
- for(i=0;i<lpProtoInfo->ProtocolChain.ChainLen;i++)
- {
- if(lpProtoInfo->ProtocolChain.ChainEntries[i]==layerid)
- {
- nextlayerid=lpProtoInfo->ProtocolChain.ChainEntries[i+1];
- break;
- }
- }
- filterpathlen=MAX_PATH;
- filterpath=(TCHAR*)GlobalAlloc(GPTR,filterpathlen);
- for(i=0;i<TotalProtos;i++)
- {
- if(nextlayerid==ProtoInfo[i].dwCatalogEntryId)
- {
- if(WSCGetProviderPath(&ProtoInfo[i].ProviderId,filterpath,&filterpathlen,&errorcode)==SOCKET_ERROR)
- {
- PutDbgStr(L"WSCGetProviderPath Error!");
- return WSAEPROVIDERFAILEDINIT;
- }
- break;
- }
- }
- if(!ExpandEnvironmentStrings(filterpath,filterpath,MAX_PATH))
- {
- PutDbgStr(L"ExpandEnvironmentStrings Error!");
- return WSAEPROVIDERFAILEDINIT;
- }
- if((hfilter=LoadLibrary(filterpath))==NULL)
- {
- PutDbgStr(L"LoadLibrary Error!");
- return WSAEPROVIDERFAILEDINIT;
- }
- if((wspstartupfunc=(LPWSPSTARTUP)GetProcAddress(hfilter,"WSPStartup"))==NULL)
- {
- PutDbgStr(L"GetProcessAddress Error!");
- return WSAEPROVIDERFAILEDINIT;
- }
- if((errorcode=wspstartupfunc(wversionrequested,lpwspdata,lpProtoInfo,upcalltable,lpproctable))!=ERROR_SUCCESS)
- {
- PutDbgStr(L"wspstartupfunc Error!");
- return errorcode;
- }
- NextProcTable=*lpproctable;// 保存原來的入口函數表
- //改寫函數
- lpproctable->lpWSPSendTo = WSPSendTo;
- lpproctable->lpWSPSend = WSPSend;
- lpproctable->lpWSPBind = WSPBind;
- lpproctable->lpWSPConnect = WSPConnect;
- lpproctable->lpWSPRecv = WSPRecv;
- lpproctable->lpWSPRecvFrom = WSPRecvFrom;
- lpproctable->lpWSPSocket = WSPSocket;
- FreeLSP();
- return 0;
- }
關於SOCKS V5代理,下回修改文章再貼上。
2011-04-30 20:57:02
要說SOCKS V5代理,其實非常簡單,細讀一遍RFC1928文檔就OK了,文檔地址如下:
http://www.ietf.org/rfc/rfc1928.txt
如果需要遠程解析域名,則將上述文檔中第四點的 ATYP 置爲 /X03
最後將前面所寫的LSP與SOCKS V5代理結合,TCP的話只要攔截WSPCONNECT函數,UDP因爲不是面向連接的所以只要攔截WSPSENDTO即可,具體代碼如下:
- // 連接socks5代理
- int socksProxy(SOCKET s, const struct sockaddr *name, int namelen)
- {
- int rc = 0;
- // 這裏應該先保存下socket的阻塞/非阻塞類型,在最後面跟據這裏的值將它還原,但是不知道怎樣獲取此類型
- // 修改socket爲阻塞類型
- if(rc = WSAEventSelect(s, 0, NULL))//這一個可以不用執行
- {
- PutDbgStr(L"Error %d : WSAEventSelect Failure!", WSAGetLastError());
- }
- else
- {
- PutDbgStr(L"Message : WSAEventSelect successfully!");
- }
- unsigned long nonBlock = 0;
- if(rc = ioctlsocket(s, FIONBIO, &nonBlock))// 這個真正修改爲阻塞類型
- {
- PutDbgStr(L"Error %d : Set Blocking Failure!", WSAGetLastError());
- }
- else
- {
- PutDbgStr(L"Message : Set Blocking successfully!");
- }
- //連接代理服務器
- sockaddr_in serveraddr;
- memset(&serveraddr, 0, sizeof(serveraddr));
- serveraddr.sin_family = AF_INET;
- serveraddr.sin_addr.S_un.S_addr = inet_addr("76.120.160.122"); //代理服務器地址,從無憂代理網獲取的,質量還行,不過只能用幾天,發現連不上的話重新獲取吧
- serveraddr.sin_port = htons(27977); // 端口號
- WSABUF DataBuf;
- char buffer[4];
- memset(buffer, 0, sizeof(buffer));
- DataBuf.len = 4;
- DataBuf.buf = buffer;
- int err = 0;
- if((rc = NextProcTable.lpWSPConnect(s, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr), &DataBuf, NULL, NULL, NULL, &err)) != 0)
- {
- PutDbgStr(L"Error %d : attempting to connect to SOCKS server!", err);
- return rc;
- }
- else
- {
- PutDbgStr(L"Message : Connect to SOCKS server successfully!");
- }
- //發送請求來協商版本和認證方法
- //VER NMETHODS METHODS
- //1 1 1 to 255
- char verstring[257];
- verstring[0] = 0x05; //VER (1 Byte)
- verstring[1] = 0x01; //NMETHODS (1 Byte)
- verstring[2] = 0x00; //METHODS (allow 1 - 255 bytes, current 1 byte)
- if((rc = send(s, verstring, 3, 0)) < 0)
- {
- PutDbgStr(L"Error %d : attempting to send SOCKS method negotiation!", WSAGetLastError());
- return rc;
- }
- else
- {
- PutDbgStr(L"Message : send SOCKS method negotiation successfully!");
- }
- //接收代理服務器返回信息
- //VER METHOD
- //1 1
- /*當前定義的方法有:
- · X’00’ 不需要認證
- · X’01’ GSSAPI
- · X’02’ 用戶名/密碼
- · X’03’ -- X’7F’ 由IANA分配
- · X’80’ -- X’FE’ 爲私人方法所保留的
- · X’FF’ 沒有可以接受的方法*/
- if((rc = recv(s, verstring, 257, 0)) < 0)
- {
- PutDbgStr(L"Error %d : attempting to receive SOCKS method negotiation reply!", WSAGetLastError());
- return rc;
- }
- else
- {
- PutDbgStr(L"Message : receive SOCKS method negotiation reply successfully!");
- }
- if(rc < 2)//返回2字節
- {
- PutDbgStr(L"Error : Short reply from SOCKS server!");
- rc = ECONNREFUSED;
- return rc;
- }
- else
- {
- PutDbgStr(L"Message : reply from SOCKS server larger than 2");
- }
- // 代理服務器選擇方法
- // 判斷我們的方法是否可行
- if(verstring[1] == '/xff')
- {
- PutDbgStr(L"Error : SOCKS server refused authentication methods!");
- rc = ECONNREFUSED;
- return rc;
- }
- else if(verstring[1] == '/x02')// 方法2 : 用戶名/密碼
- {
- //另外處理
- PutDbgStr(L"Error : SOCKS server need username/password!");
- }
- else if(verstring[1] == '/x00')// 方法0: 不需要認證
- {
- //發送SOCKS請求
- //VER CMD RSV ATYP DST.ADDR DST.PROT
- //1 1 X'00' 1 Variable 2
- /* VER 協議版本: X’05’
- · CMD
- · CONNECT:X’01’
- · BIND:X’02’
- · UDP ASSOCIATE:X’03’
- · RSV 保留
- · ATYP 後面的地址類型
- · IPV4:X’01’
- · 域名:X’03’
- · IPV6:X’04’'
- · DST.ADDR 目的地址
- · DST.PORT 以網絡字節順序出現的端口號
- SOCKS服務器會根據源地址和目的地址來分析請求,然後根據請求類型返回一個或多個應答。*/
- struct sockaddr_in sin;
- sin = *(const struct sockaddr_in *)name;
- char buf[10];
- buf[0] = '/x05'; // 版本 SOCKS5
- buf[1] = '/x01'; // 連接請求
- buf[2] = '/x00'; // 保留字段
- buf[3] = '/x01'; // IPV4
- memcpy(&buf[4], &sin.sin_addr.S_un.S_addr, 4);
- memcpy(&buf[8], &sin.sin_port, 2);
- //發送
- if((rc = send(s, buf, 10, 0)) < 0)
- {
- PutDbgStr(L"Error %d : attempting to send SOCKS connect command!", WSAGetLastError());
- return rc;
- }
- else
- {
- PutDbgStr(L"Message : send SOCKS connect command successfully!");
- }
- //應答
- //VER REP RSV ATYP BND.ADDR BND.PORT
- //1 1 X'00' 1 Variable 2
- /*VER 協議版本: X’05’
- · REP 應答字段:
- · X’00’ 成功
- · X’01’ 普通的SOCKS服務器請求失敗
- · X’02’ 現有的規則不允許的連接
- · X’03’ 網絡不可達
- · X’04’ 主機不可達
- · X’05’ 連接被拒
- · X’06’ TTL超時
- · X’07’ 不支持的命令
- · X’08’ 不支持的地址類型
- · X’09’ – X’FF’ 未定義
- · RSV 保留
- · ATYP 後面的地址類型
- · IPV4:X’01’
- · 域名:X’03’
- · IPV6:X’04’
- · BND.ADDR 服務器綁定的地址
- · BND.PORT 以網絡字節順序表示的服務器綁定的段口
- 標識爲RSV的字段必須設爲X’00’。*/
- if((rc = recv(s, buf, 10, 0)) < 0) // 用了天翼的網絡之後,這裏就接收不到返回信息了,不解
- {
- PutDbgStr(L"Error %d : attempting to receive SOCKS connection reply!", WSAGetLastError());
- rc = ECONNREFUSED;
- return rc;
- }
- else
- {
- PutDbgStr(L"Message : receive SOCKS connection reply successfully!");
- }
- if(rc < 10)
- {
- PutDbgStr(L"Message : Short reply from SOCKS server!");
- return rc;
- }
- else
- {
- PutDbgStr(L"Message : reply from SOCKS larger than 10!");
- }
- //連接不成功
- if(buf[0] != '/x05')
- {
- PutDbgStr(L"Message : Socks V5 not supported!");
- return ECONNABORTED;
- }
- else
- {
- PutDbgStr(L"Message : Socks V5 is supported!");
- }
- if(buf[1] != '/x00')
- {
- PutDbgStr(L"Message : SOCKS connect failed!");
- switch((int)buf[1])
- {
- case 1:
- PutDbgStr(L"General SOCKS server failure!");
- return ECONNABORTED;
- case 2:
- PutDbgStr(L"Connection denied by rule!");
- return ECONNABORTED;
- case 3:
- PutDbgStr(L"Network unreachable!");
- return ENETUNREACH;
- case 4:
- PutDbgStr(L"Host unreachable!");
- return EHOSTUNREACH;
- case 5:
- PutDbgStr(L"Connection refused!");
- return ECONNREFUSED;
- case 6:
- PutDbgStr(L"TTL Expired!");
- return ETIMEDOUT;
- case 7:
- PutDbgStr(L"Command not supported!");
- return ECONNABORTED;
- case 8:
- PutDbgStr(L"Address type not supported!");
- return ECONNABORTED;
- default:
- PutDbgStr(L"Unknown error!");
- return ECONNABORTED;
- }
- }
- else
- {
- PutDbgStr(L"Message : SOCKS connect Success!");
- }
- }
- else
- {
- PutDbgStr(L"Error : Method not supported!");
- }
- //修改socket爲非阻塞類型
- nonBlock = 1;
- if(rc = ioctlsocket(s, FIONBIO, &nonBlock))
- {
- PutDbgStr(L"Error %d : Set Non-Blocking Failure!", WSAGetLastError());
- return rc;
- }
- else
- {
- PutDbgStr(L"Message : Set Non-Blocking Successful!");
- }
- PutDbgStr(L"Message : Success!");
- return 0;
- }
- //WSPConnect
- int WSPAPI WSPConnect(
- SOCKET s,
- const struct sockaddr *name,
- int namelen,
- LPWSABUF lpCallerData,
- LPWSABUF lpCalleeData,
- LPQOS lpSQOS,
- LPQOS lpGQOS,
- LPINT lpErrno)
- {
- PutDbgStr(L"WSPConnect");
- struct sockaddr_in sin;
- sin=*(const struct sockaddr_in *)name;
- if(strcmp(inet_ntoa(sin.sin_addr), "127.0.0.1") == 0)
- {
- return NextProcTable.lpWSPConnect(s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, lpErrno);
- }
- return socksProxy(s, name, namelen);
- }
- //WSPSendTo
- int WINAPI WSPSendTo(
- __in SOCKET s,
- __in LPWSABUF lpBuffers,
- __in DWORD dwBufferCount,
- __out LPDWORD lpNumberOfBytesSent,
- __in DWORD dwFlags,
- __in const struct sockaddr *lpTo,
- __in int iTolen,
- __in LPWSAOVERLAPPED lpOverlapped,
- __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
- __in LPWSATHREADID lpThreadId,
- __out LPINT lpErrno
- )
- {
- PutDbgStr(L"WSPSendTo");
- struct sockaddr_in sin;
- sin=*(const struct sockaddr_in *)name;
- if(strcmp(inet_ntoa(sin.sin_addr), "127.0.0.1") == 0)
- {
- return NextProcTable.lpWSPSendTo(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo, iTolen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
- }
- return socksProxy(s, lpTo, iTolen);
- }
2011-05-02 18:25:39