利用SPI编写类似sockscap的代理工具
来源:互联网 发布:朝鲜有多穷 知乎 编辑:程序博客网 时间:2024/06/06 02:47
转自: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代理,下回修改文章再贴上。
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
- 利用SPI编写类似sockscap的代理工具
- 利用SPI编写类似sockscap的代理工具
- 利用SPI编写类似sockscap的代理工具
- 利用SPI编写类似sockscap的代理工具
- 分享一个好用的添加网络代理的工具SocksCap
- SocksCap代理使用教程
- SOCKSCAP的使用方法
- sockscap
- 利用.NET生成数据库表的创建脚本,类似SqlServer编写表的CREATE语句
- 利用table元素,编写 类似163邮箱 checkbox的效果【实例】
- 如何利用Win7的“数学输入面板”工具编写数学公式
- 利用正则表达式编写的代码统计工具
- WMI 应用——用 VBScript 编写类似 ipconfig 的工具
- WMI 应用——用 VBScript 编写类似 ipconfig 的工具
- SPI防火墙设计之DLL的编写
- 基于spi总线驱动程序的编写
- 基于spi总线驱动程序的编写
- tunna类似redush的工具
- 华容道自动求解 java版
- 【翻译自mos文章】解释 datafile name中的MISSING关键字
- 【OpenCV_C++】学习杂记
- 指数型母函数
- Oracle 11g安装指南
- 利用SPI编写类似sockscap的代理工具
- HDU 3068 最长回文(初遇manacher)
- POJ 1258 Agri-Net
- 在oracle database中,一个datafile 可以被drop的条件
- 欢迎使用CSDN-markdown编辑器
- 【Jason's_ACM_解题报告】Division
- HDU 1874 畅通工程续
- 在归档模式下,恢复一个被offline drop的datafile的方法
- 【Jason's_ACM_解题报告】Maximum Product