日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

利用SPI编写类似sockscap的代理工具

發布時間:2023/12/14 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 利用SPI编写类似sockscap的代理工具 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

利用SPI編寫類似sockscap的代理工具

最近幫一個朋友實現sockscap的socks V5代理功能,sockscap貌似是通過API HOOK實現,一開始我便嘗試這種方式,遇到各種麻煩的問題,還是用SPI的LSP來試試吧。

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;}}elsereturn 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");elseprintf(" 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代理,下回修改文章再貼上。

zetsin@gmail.com

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 255char 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'; // 版本 SOCKS5buf[1] = '/x01'; // 連接請求buf[2] = '/x00'; // 保留字段buf[3] = '/x01'; // IPV4memcpy(&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); }

zetsin@gmail.com

2011-05-02 18:25:39

轉自:http://blog.csdn.net/ze_tsin/article/details/6376831

總結

以上是生活随笔為你收集整理的利用SPI编写类似sockscap的代理工具的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。