利用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的代理工具相关推荐
- python数据预测_利用Python编写一个数据预测工具
利用Python编写一个数据预测工具 发布时间:2020-11-07 17:12:20 来源:亿速云 阅读:96 这篇文章运用简单易懂的例子给大家介绍利用Python编写一个数据预测工具,内容非常详细 ...
- 内网渗透 | FRP代理工具详解
FRP工具的使用 FRP官方文档:https://gofrp.org/docs 文章目录 **一.FRP工具的介绍** **1.为什么需要内网穿透** **2.FRP介绍** **3.为什么使用FRP ...
- 端口转发与代理工具 内网代理 内网反弹代理
目录 一.LCX 二.nc 反弹 三.socks代理工具 四.frp 内网穿透利器 五.ngrok 内网穿透 理论上,任何接入互联网的计算机都是可访问的,但是如果目标主机处于内网,而我们又想和该目标主 ...
- 用ChatGPT处理word表格数据:直接采用ChatGPt和利用ChatGPT编写python脚本两种方法
目录 摘要 0. 测试数据生成 1. 直接使用ChatGPT进行处理. 2 使用ChatGPT生成python脚本进行处理 3对比分析 4 结束语 摘要 为测试ChatGP在word文档表格的处理能力 ...
- 接口测试准备一、 网路基础 常用代理工具 charles使用 Android手机代理抓包
移动互联网公司技术架构 接口测试的必要性 1.行业成熟方案 2.更早份发现问题 3.更快的质量反馈 接口测试不能替代UI测试 1.接口测试有很多优点,但是保证的好似后端的质量,不能解决移动端的额质量 ...
- python编写图形化界面的工具,python做出软件的界面
python能写界面吗 作为Pyhon开发者,你迟早都会碰到图形用户界面(GUI)应用开发任务,这时候我们就需要一些界面库来帮助我们快速搭建界面,python的界面库很多,我认识的并不多,这里只列出几 ...
- 多级代理工具Stowaway
多级代理工具Stowaway Stowaway是一个利用go语言编写.专为渗透测试工作者制作的多级代理工具 项目地址https://github.com/ph4ntonn/Stowaway 特性 管理 ...
- 爬虫实战(一)—利用requests、mongo、redis代理池爬取英雄联盟opgg实时英雄数据
概述 可关注微信订阅号 loak 查看实际效果. 代码已托管github,地址为:https://github.com/luozhengszj/LOLGokSpider 包括了项目的所有代码. 此篇文 ...
- 5、内网渗透之端口转发与代理工具总结
理论上,任何接入互联网的计算机都是可访问的,但是如果目标主机处于内网,而我们又想和该目标主机进行通信的话,就需要借助一些端口转发工具来达到我们的目的 注:文中提到的所有工具下载地址 https://g ...
- 代理工具Charles使用
代理工具Charles使用 分类: MAC 2014-03-27 20:41 7810人阅读 评论(2) 收藏 举报 手机开发 一.跟踪HTTPS 1.下载官方的证书ssl.zip证书,解压成*.cr ...
最新文章
- P3321 [SDOI2015]序列统计(离散对数下NTT,乘法换加法)
- python 打印数组变量_使用Python将数组的元素导出到变量中(unpacking)
- 利用Bandwidth Splitter限制带宽
- 谷歌抽屉_Google(最终)会杀死导航抽屉吗?
- fopen php 乱码,如何解决php fgets读取文件乱码的问题
- LDR 、ADR介绍
- 网络通信协议八之UDP协议详解
- 中国医科大学计算机应用基础本科在线作业,中国医科大学《计算机应用基础(本科)》在线作业.docx...
- 5.9UDP客户端服务器-基于OK6410
- 最贵服务器多少钱_十次方分享:租服务器一般花费多少钱一年?
- Qt 获取控件位置坐标,屏幕坐标,相对父窗体坐标
- Android进阶之路 - keyStore、jks签名证书相互转换
- LeetCode——868. 二进制间距
- 程序员与代码之间的搞笑日常,笑的人肚子痛!
- Thymeleaf设置固定值属性
- win10环境编译支持xp的libcurl+openssl踩过的坑
- cgroup架构及控制文件介绍
- Java在Web端微信公众号授权登录
- 浪潮IPBS9505S短接线刷固件(附教程)
- 【Java】练习题库 单选题