转自:http://www.cnblogs.com/tanweizlf/archive/2012/06/24/2559733.html
http://bbs.125.la/forum.php?mod=viewthread&tid=13770094&highlight=lsp
利用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; } } 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代理,下回修改文章再贴上。
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 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); }
zetsin@gmail.com
2011-05-02 18:25:39