/***************************************************************************** * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see * ***************************************************************************** * * Sockcheck.c By BigDawg dawg@nuthin.nu - [ http://www.rootshell.com/ ] * Use: put a list of ips (one per line) in ips.in then run sockcheck. * The list of unsecure socks servers will be saved to ips.out * Compile: gcc sockcheck.c -o sockcheck * * [20:01] put my name in the source ;) * * I'd like to say thanks to all who have helped me throughout the past years. * ***************************************************************************** * Notes from Mr.HinkyDink 8/24/2007 * * There were a few things I didn't like about the original. * * I'd rather be able to put the IP & port on the command line * and script the list than hassle with this infile/outfile crap. * * For example... * * for ADDR in $( #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define _GNU_SOURCE #define DEFAULTWAIT (unsigned short)10 #define HTTPlen 8192 #define TMPlen 1024 #define GETlen 512 #define VIAMAX 64 typedef struct Sreq { char vers; char command; unsigned short port; char addr[4]; char name[16]; } Sreq; typedef struct S5req { char vers; char command; char rsv; char atyp; char addr[4]; // IPv4 addresses only : ( unsigned short port; } S5req; typedef struct S5resp { char vers; char rep; char rsv; char atyp; char baddr[4]; unsigned short bport; } S5resp; char *S5error[10]={ "GRANTED", "general SOCKS server failure", "connection not allowed by ruleset", "network unreachable", "host unreachable", "connection refused", "TTL expired", "command not supported", "address type not supported", "unassigned" }; int sockcheck(char *host, unsigned short port, char *dhost, unsigned short dport); static int sockfd2; static int aflag, killsock; void sigalrm_handler3(int sig) { if( killsock ) { killsock=0; close(sockfd2); } aflag++; } // memmem is part of the GNU C library // Copyright (C) 1991,92,93,94,96,97,98,2000 Free Software Foundation, Inc. void * memmem(const void *block, size_t blen, const void *pat, size_t plen) { const unsigned char *bp, *pp, *endp; if (plen == 0) return NULL; if (blen < plen) return NULL; bp = block; pp = pat; endp = bp + (blen - plen) + 1; while (bp < endp) { if ((*bp == *pp) && (memcmp(bp, pp, plen) == 0)) return (void *)bp; bp++; } return NULL; } // end of memmem void findVIA( char *a, char *via ) { while( (*a!='\r') ) { if(*a==',') break; *via++ = *a++; } *via=0; } int main(int argc, char **argv) { char sockip[32]; char destip[32]; short sockport; short destport; char *p; sockport=destport=0; destip[0]='\0'; if( argc<2 || argc>3 ) { printf("\n=============================\n"); printf("sockcheck 0.4 by Mr.HinkyDink\n"); printf(" based on sockcheck 0.3\n"); printf(" by BigDawg\n"); printf("=============================\n\n"); printf("Useage:\n"); printf(" sockcheck SOCKSSERVER<:port> >\n\n"); printf("Default SOCKS port = 1080\n"); printf("Default TARGET port = 80\n"); printf("Default TARGET = www.google.com\n"); return 1; } strcpy( sockip, argv[1] ); if( (p=strchr(sockip,':'))==NULL) sockport=1080; else { sockport=(unsigned short)atoi((const char*)p+1); *p='\0'; } sockport=sockport==0?1080:sockport; if ( argv[2]==NULL ) { return sockcheck( sockip, sockport, "www.google.com\0", 80 ); } else { strcpy( destip, argv[2] ); if( (p=strchr(destip,':'))==NULL ) destport=80; else { destport=(unsigned short)atoi((const char*)p+1); *p='\0'; } destport=destport==0?80:destport; return sockcheck( sockip, sockport, destip, destport ); } } int sockcheck(char *host, unsigned short port, char *dhost, unsigned short dport) { int d,e,f,retcode,idx,pos; struct Sreq S; struct S5req S5; struct S5resp S5r; char tmpstr2[TMPlen]; char HTTP_buffer[HTTPlen]; char HTTP[GETlen]="GET / HTTP/1.1\xd\xaHost: \0"; char GETcheck[]="(12202)"; // not prone to language issues char VIAcheck[]="Via:"; char S5ask[3] = "\x5\x1\0"; char S5tell[2] = "\0\0"; fd_set gateset; struct timeval tv; struct hostent *he; struct sockaddr_in sin; unsigned short sockwait; char *env; char conDios[VIAMAX]="UNKNOWN\0"; void *p; if( dport==80 ){ strncat(HTTP, dhost, GETlen-strlen(HTTP)); strncat(HTTP, "\xd\xa\xd\xa\0", GETlen-strlen(HTTP)); } aflag=killsock=0; if ( (env=getenv("SOCKWAIT"))==NULL) sockwait=DEFAULTWAIT; else sockwait=(unsigned short)atoi((const char*)env); sockwait=sockwait?sockwait:DEFAULTWAIT; sockfd2 = socket(AF_INET, SOCK_STREAM, 0); sin.sin_family = AF_INET; sin.sin_port = htons(port); sin.sin_addr.s_addr = inet_addr(host); if(sin.sin_addr.s_addr == INADDR_NONE) { he = gethostbyname(host); if(!he) { close(sockfd2); printf("DNS error - can't resolve \"%s\"!\n", host); return 0; } memcpy(&sin.sin_addr, he->h_addr, he->h_length); } signal(SIGALRM, (void*)sigalrm_handler3); alarm(sockwait); killsock=1; // SIGALRM closes sockfd2 e = connect(sockfd2, (struct sockaddr *)&sin, sizeof(sin)); if ( aflag ) { printf("%s:%u - connect killed by SIGALRM", host, port); if (sockwait==DEFAULTWAIT) printf("\n"); else printf(" (SOCKWAIT = %d sec.)\n", sockwait); return 0; } if (e < 0) { printf("%s:%u - %s\n", host, port, strerror(errno)); //perror("connect"); close(sockfd2); return 1; } alarm(sockwait); FD_ZERO(&gateset); FD_SET(sockfd2, &gateset); tv.tv_sec = 10; tv.tv_usec = 0; d = select(sockfd2+1, NULL, &gateset, NULL, &tv); if(d == 0 || aflag!=0 ) // seems to be dead code here, never dies on select { printf("%s:%d - %s\n", host, port, strerror(errno)); close(sockfd2); return 1; } memset( &S, 0, sizeof(struct Sreq)); memset( &S5, 0, sizeof(struct S5req)); memset( &S5r, 0, sizeof(struct S5resp)); S.vers=4; S5.vers=5; S.command=S5.command=1; S.port=S5.port=htons(dport); S5.rsv=0; S5.atyp=1; if ( (he = gethostbyname(dhost))==NULL ) { printf("Can't resolve destination host \"%s\"\n", dhost); close( sockfd2 ); return 1; } memcpy( &S.addr, he->h_addr, he->h_length ); memcpy( &S5.addr, he->h_addr, he->h_length ); strcpy(S.name,"BathHouseJohn\0"); // YOUR NAME HERE memset( tmpstr2, 0, 1024); send(sockfd2, &S, sizeof(struct Sreq), 0); tv.tv_sec = 10; tv.tv_usec = 0; f = select(sockfd2+2, &gateset, NULL, NULL, &tv); if(f>=0) { alarm(sockwait); killsock=1; // SIGALRM closes sockfd2 idx=pos=0; read(sockfd2, tmpstr2, TMPlen); if( aflag ) { printf("%s:%u - Read killed by SIGALRM (connect successful)\n", host, port); return 1; } if ( tmpstr2[0]==0x00 ) { switch (tmpstr2[1]) { case 0x5a: // check for ISA server - toss out a GET request if (dport==80){ memset( HTTP_buffer, 0, HTTPlen); e=send(sockfd2, &HTTP, strlen(HTTP), 0); idx=pos=0; do { idx=read(sockfd2, HTTP_buffer+pos, HTTPlen-pos); if ( idx<0 ) break; pos+=idx; } while(idx); if (e<0) { printf("%s:%u - %s (after access granted)\n", host, port, strerror(errno)); retcode=1; break; } p=memmem((const void*)HTTP_buffer,(size_t)HTTPlen,(const void*)GETcheck, (size_t)strlen(GETcheck)); if ( p==NULL ){ printf("%s:%u - ****GRANTED anonymous SOCKSv4 request****\n",host,port ); retcode=0; } else { p=memmem((const void*)HTTP_buffer,(size_t)HTTPlen,(const void*)VIAcheck, (size_t)strlen(VIAcheck)); if(p) findVIA(p+8,conDios); printf("%s:%u - ISA 2000 server \"%s\" denied http request (other ports may work)\n",host,port,conDios ); retcode=1; } } else { printf("%s:%u - ****GRANTED anonymous SOCKSv4 request to port %d****\n",host,port,dport ); retcode=0; } break; // A note on ISA Server: // ===================== // You really have to go out of your way to expose // an ISA 2004/2006 server to the Internet. I was surprised // to find as many as I did. The problem with http & ISA // SOCKS support is you can't run the Web (http) proxy at the // same time. It eats up all the "Web" ports. However, you // can use SOCKS for any other TCP ports the ISA server allows // unauthenticated access to. These could be substantial // since if an ISA admin is stupid enough to expose the // server to the Internet, he has very likely also created an // "any port anywhere" rule. // -- Mr.HinkyDink case 0x5b: printf("%s:%u - returned explicit FAIL/DENY\n",host,port); retcode=1; break; case 0x5c: printf("%s:%u - requires identd (not anonymous).\n",host,port); retcode=2; break; case 0x5d: printf("%s:%u - returned SUX2BU (bad user ID).\n",host,port); retcode=3; break; default: if ( errno ) printf("%s:%d - %s after SOCKS request.\n",host,port,strerror(errno)); else printf("%s:%u - Got JUNK (0x00,0x%0.2X,0x%0.2X).\n", host, port,(unsigned char)tmpstr2[1],(unsigned char)tmpstr2[2]); retcode=4; break; } close(sockfd2); return retcode; } else { if ( tmpstr2[0]==0x05 && tmpstr2[1]==0x01 && tmpstr2[2]==0x00 && tmpstr2[3]==0x01 ) { close(sockfd2); // server will have FIN'd us by now // can't use same connection, so make it new // no SIGALRM stuff because been there, done that, and I'm lazy // SOCKS 5 packets previously stuffed just in case sockfd2 = socket(AF_INET, SOCK_STREAM, 0); connect(sockfd2, (struct sockaddr *)&sin, sizeof(sin)); FD_ZERO(&gateset); FD_SET(sockfd2, &gateset); tv.tv_sec = 10; tv.tv_usec = 0; select(sockfd2+1, NULL, &gateset, NULL, &tv); send(sockfd2, &S5ask, 3, 0); // SOCKS 5 greeting read(sockfd2, &S5tell, 2 ); // SOCKS 5 response if (S5tell[1]==0) { send(sockfd2, &S5, sizeof(struct S5req), 0); read(sockfd2, &S5r, sizeof(struct S5resp) ); if ( S5r.rep > 9 ) S5r.rep=9; printf("%s:%d - SOCKS v5 server response \"%s\"\n",host,port,S5error[S5r.rep]); } else // dead code??? printf("%s:%d - SOCKS v5 server requires authentication\"%s\"\n",host,port); close(sockfd2); return 1; } else printf("%s:%d - Unknown SOCKS version or CRAP (0x%0.2X,0x%0.2X,0x%0.2X) or ERROR 0x%0.2X (%s).\n",host,port,(unsigned char)tmpstr2[0],(unsigned char)tmpstr2[1],(unsigned char)tmpstr2[2], errno, strerror(errno)); close(sockfd2); return 1; } } // fall through printf("%s:%d - Bizarre outcome with errno = 0x%0.2X (%s).\n",host,port,errno,strerror(errno)); close(sockfd2); return 0; }