/* * yass - Yet Another Socks Scanner * (C)oded 2000 - s0y0k@ircnet * * yass is a backgroundable, MONO process UNIX OR WIN32 socks scanner * Responding SOCKS hosts are connected to a LOCAL LISTEN PORT to really * check SOCKS integrity (not only checking responding 1080 port) * MULTIPLE Scan domains queue are allowed via CONFIG FILE * (for help: type: yass) * */ #include #include #include #include #include #include #include #ifndef WIN32 #include #include #include #include #include #include #include #define CLOSESOCKET close #define _stricmp strcasecmp #else #include #include #define CLOSESOCKET closesocket #define _stricmp stricmp #endif /***************************************************************************************/ #define ESTABLISHED 1 #define INPROGRESS 0 int TIMEOUT = 10; int SCANPORT = 1080; #ifndef WIN32 int MAXALLOCSOCKS = 50; #else int MAXALLOCSOCKS = 25; #endif /***************************************************************************************/ typedef unsigned int IPTYPE; typedef struct { int sock; int state; time_t timeTick; struct sockaddr_in addr; } SCANSOCKS; typedef struct { IPTYPE ipStart; IPTYPE ipEnd; } IPPAIRS; typedef struct { SCANSOCKS* psocks; int nCurrentPairs; int nPairs; IPPAIRS* pipPairs; char szOutput[256]; IPTYPE myIP; int listenPort; int listenSock; int bQuickMode; } WORKINGSTRUCT; #ifndef errno extern int errno; #endif IPTYPE GetMyIp() { struct hostent *hp; char s[121]; IPTYPE ip; struct in_addr *in; char* p; p = getenv("MYIP"); if (p) hp = gethostbyname(p); else { p = getenv("HOSTNAME"); if (p != NULL) hp = gethostbyname(p); else { gethostname(s, 120); hp = gethostbyname(s); } } if (hp == NULL) { printf("ERROR: Hostname self-lookup failed. set MYIP with the host ip (like MYIP=10.20.30.40\n"); return -1; } in = (struct in_addr *) (hp->h_addr_list[0]); ip = (IPTYPE) (in->s_addr); return ip; } void SetAsync(int sock) { #ifndef WIN32 fcntl(sock, F_SETFL, (fcntl(sock, F_GETFL) | O_NDELAY)); #else { u_long non_block = 1; ioctlsocket (sock, FIONBIO, &non_block); } #endif } int CreateListenSock(WORKINGSTRUCT* p) { int sock = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in name; int size; if (sock < 0) return 0; SetAsync(sock); memset(&name, 0, sizeof(struct sockaddr_in)); name.sin_family = AF_INET; name.sin_addr.s_addr = INADDR_ANY; if (bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0) { CLOSESOCKET(sock); return 0; } if (listen(sock, 1) < 0) { CLOSESOCKET(sock); return 0; } /* Get port where's sock listen */ size = sizeof(struct sockaddr); memset(&name, 0, sizeof(struct sockaddr_in)); getsockname(sock, (struct sockaddr*) &name, &size); p->listenSock = sock; p->listenPort = ntohs (name.sin_port); return 1; } void InitSock(WORKINGSTRUCT* pws, SCANSOCKS* pnt) { unsigned char szGateInit[16]; unsigned char* p = (unsigned char *) &pws->myIP; szGateInit[0] = 4; szGateInit[1] = 1; szGateInit[2] = (pws->listenPort >> 8) & 0xFF; szGateInit[3] = pws->listenPort & 0xFF; szGateInit[4] = p[0]; szGateInit[5] = p[1]; szGateInit[6] = p[2]; szGateInit[7] = p[3]; szGateInit[8] = 0; #ifndef WIN32 errno=0; write(pnt->sock, szGateInit, 9); #else send(pnt->sock, szGateInit, 9, 0); #endif pnt->timeTick = time(NULL); } void ClearSocks(SCANSOCKS* pnt) { if (pnt->sock) CLOSESOCKET(pnt->sock); memset(pnt, 0, sizeof(SCANSOCKS)); } void FreeAll(WORKINGSTRUCT* pws) { int i; if (pws->psocks) { for (i = 0; i < MAXALLOCSOCKS; i++) { SCANSOCKS* pnt = &pws->psocks[i]; ClearSocks(pnt); } } if (pws->listenSock) CLOSESOCKET(pws->listenSock); if (pws->pipPairs) free(pws->pipPairs); if (pws->psocks) free(pws->psocks); } void CreateNewSocks(WORKINGSTRUCT* pws) { int i; if (pws->pipPairs == NULL || pws->nCurrentPairs >= pws->nPairs) return; for (i = 0; i < MAXALLOCSOCKS; i++) { SCANSOCKS* pnt = &pws->psocks[i]; IPPAIRS* pip = &pws->pipPairs[pws->nCurrentPairs]; IPTYPE aip = pip->ipStart; unsigned char* pipStart; struct sockaddr_in addr; int sock; /* Is Domain scanned ? */ if (memcmp(&pip->ipStart, &pip->ipEnd, sizeof(IPTYPE)) > 0) { pws->nCurrentPairs++; if (pws->nCurrentPairs >= pws->nPairs) return; continue; } if (pnt->sock) continue; /* Increment ip */ pipStart = (unsigned char*) &pip->ipStart; if ((++pipStart[3]) == 0 || pipStart[3] == 255) { if ((++pipStart[3]) == 0) pipStart[3]++; if ((++pipStart[2]) == 0) if ((++pipStart[1]) == 0) pipStart[0]++; } sock = socket(AF_INET, SOCK_STREAM, 0); /* Big failure */ if (sock < 1) return; SetAsync(sock); memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = INADDR_ANY; // Bind socket if (bind(sock, (struct sockaddr*) &addr, sizeof(struct sockaddr_in)) < 0) { CLOSESOCKET(sock); return; } addr.sin_family = AF_INET; addr.sin_addr.s_addr = aip; addr.sin_port = htons(SCANPORT); // Connect to socks server errno = 0; if (connect(sock, (struct sockaddr*) &addr, sizeof(struct sockaddr_in))) { #ifndef WIN32 if (errno != EINPROGRESS && errno != EWOULDBLOCK) #else int nErr = WSAGetLastError(); if (nErr != WSAEINPROGRESS && nErr != WSAEWOULDBLOCK) #endif { CLOSESOCKET(sock); continue; } } pnt->sock = sock; pnt->timeTick = time(NULL); pnt->addr.sin_addr.s_addr = aip; #ifdef _DEBUG printf("Trying %s\n", inet_ntoa(pnt->addr.sin_addr)); #endif } } void LogHost(WORKINGSTRUCT* p, struct sockaddr_in* from) { FILE* fp; char sz[256]; sprintf(sz, "%s\n", inet_ntoa(from->sin_addr)); fp = fopen(p->szOutput, "a"); fprintf(fp, sz); fflush(fp); fclose(fp); } void CheckIncoming(WORKINGSTRUCT* p) { struct sockaddr_in from; int sock; #ifdef WIN32 int addrlen = sizeof(struct sockaddr); #else unsigned int addrlen = sizeof(struct sockaddr); #endif while (1) { sock = accept(p->listenSock, (struct sockaddr *) &from, &addrlen); if (sock > 0) { LogHost(p, &from); CLOSESOCKET(sock); continue; } break; } } void process_server(WORKINGSTRUCT* pws) { int i; while (1) { fd_set rd, wr; struct timeval timeout; time_t timenow; SCANSOCKS* p; int bContinue = 0; timeout.tv_usec = 0; timeout.tv_sec = 1; FD_ZERO(&rd); FD_ZERO(&wr); /* Create Socks as soon as slots are available */ CreateNewSocks(pws); for (i = 0; i < MAXALLOCSOCKS; i++) { p = &pws->psocks[i]; if (p->sock) { FD_SET(p->sock,&rd); if(p->state == INPROGRESS) FD_SET(p->sock,&wr); bContinue++; } } if (!bContinue) break; errno=0; /* See if socks connect to me */ CheckIncoming(pws); #ifdef FD_SETSIZE select(FD_SETSIZE, &rd, &wr, 0, &timeout); #else select(getdtablesize(), (fd_set *) &rd,(fd_set *) &wr, (fd_set *) 0, &timeout); #endif if(errno == EINTR) continue; timenow = time(NULL); for (i = 0; i < MAXALLOCSOCKS; i++) { p = &pws->psocks[i]; if (!p->sock) continue; errno=0; if (p->state == INPROGRESS) { if (FD_ISSET(p->sock, &wr)) { if (pws->bQuickMode) { LogHost(pws, &p->addr); ClearSocks(p); } else { InitSock(pws, p); p->state = ESTABLISHED; } continue; } } if ((timenow - p->timeTick) > TIMEOUT) { ClearSocks(p); continue; } if (FD_ISSET(p->sock, &rd)) { char b[32]; #ifndef WIN32 int nRead = read(p->sock, b, 32); #else int nRead = recv(p->sock, b, 32, 0); #endif if (nRead < 1) { #ifndef WIN32 if (errno == EINPROGRESS || errno == EWOULDBLOCK) continue; #else int nErr = WSAGetLastError(); if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK) continue; #endif ClearSocks(p); } } } } } char* rmspace (char * s) { char *p; if (*s == '\0') return s; #define whitespace(c) ( ((c)==32) || ((c)==9) || ((c)==13) || ((c)==10) ) /* wipe end of string */ for (p = s + strlen(s) - 1; ((whitespace(*p)) && (p >= s)); p--); if (p != s + strlen(s) - 1) *(p + 1) = 0; for (p = s; ((whitespace(*p)) && (*p)); p++); if (p != s) strcpy(s, p); return s; } int AddPairs(WORKINGSTRUCT* p, char* pIpRange) { char* psep = strchr(pIpRange, '-'); if (psep) { IPPAIRS ipp; *psep++ = '\0'; ipp.ipStart = inet_addr(pIpRange); ipp.ipEnd = inet_addr(psep); if (ipp.ipStart == -1 || ipp.ipEnd == -1) { printf("ERROR: bad ip: %s - %s\n", pIpRange, psep); return 0; } if (p->nPairs) p->pipPairs = realloc(p->pipPairs, sizeof(IPPAIRS) * (p->nPairs + 1)); else p->pipPairs = malloc(sizeof(IPPAIRS)); memcpy(&p->pipPairs[p->nPairs], &ipp, sizeof(IPPAIRS)); p->nPairs++; return 1; } return 0; } int ReadConfig(WORKINGSTRUCT* p, char* pConfigFile) { FILE* fp = fopen(pConfigFile, "r"); char sz[512]; if (!fp) { perror(pConfigFile); return 0; } while (!feof(fp)) { char* psep; if (!fgets(sz, sizeof(sz) - 1, fp)) break; rmspace(sz); psep = strchr(sz, '='); if (!psep) continue; *psep++ = '\0'; if (_stricmp(sz, "TIMEOUT") == 0 && atoi(psep) > 5) { TIMEOUT = atoi(psep); printf("TimeOut set to: %d secs\n", TIMEOUT); } else if (_stricmp(sz, "MAXSOCKETS") == 0 && atoi(psep) > 5) { MAXALLOCSOCKS = atoi(psep); printf("Number of simultaneaous open sockets: %d\n", MAXALLOCSOCKS); } else if (_stricmp(sz, "OUTPUT") == 0 && strlen(psep) > 0) { strncpy(p->szOutput, psep, 255); p->szOutput[255] = '\0'; printf("Output file: %s\n", p->szOutput); } else if (_stricmp(sz, "MYIP") == 0 && strchr(psep, '.') != NULL) { p->myIP = inet_addr(psep); printf("Using Local IP: %s\n", psep); } else if (_stricmp(sz, "SCAN") == 0) { printf("Adding Scan Domain: %s\n", psep); if (!AddPairs(p, psep)) return 0; } else if (_stricmp(sz, "PORT") == 0) { SCANPORT = atoi(psep); printf("Scanning Port: %d\n", SCANPORT); } else if (_stricmp(sz, "QUICKMODE") == 0) { p->bQuickMode = atoi(psep); printf("Using Quick Mode: %s\n", (p->bQuickMode) ? "YES" : "NO"); } } fclose(fp); return 1; } int DoAllInits(WORKINGSTRUCT* work, int argc, char** argv) { struct in_addr addr; FILE* fp; if (argc < 2) { printf("USAGE: yass [-q] \n"); printf(" -q : Check ONLY if port is open\n\n"); printf("or : yass \n", argv[0]); printf("\nConfig File Syntax:\n-------------------\nOUTPUT= (mandatory)\n"); printf("SCAN= (mandatory) nb: multiple SCAN lines are allowed\n"); printf("\nOptionals Config File Parameters:\n---------------------------------\n"); printf("TIMEOUT= (default: %d)\n", TIMEOUT); printf("PORT= (default: %d)\n", SCANPORT); printf("MAXSOCKETS= (unix default: 50, win32: 25)\n"); printf("MYIP= (my ip if self DNS lookup fail)\n"); printf("QUICKMODE=<0|1> Check ONLY if port is open if set to 1 (Default: 0)\n\n"); return 2; } else if (argc == 2) { if (!ReadConfig(work, argv[1])) return 2; } else { char* pIpRange; char* pFileName; int np = 1; if (strcmp(argv[np], "-q") == 0) { work->bQuickMode = 1; np++; } pIpRange = argv[np++]; pFileName = argv[np]; if (!AddPairs(work, pIpRange)) return 3; strncpy(work->szOutput, pFileName, 255); work->szOutput[255] = '\0'; } if (*work->szOutput == '\0') { printf("ERROR: Missing output file!\n"); return 2; } if (work->nPairs == 0) { printf("ERROR: NO domain to scan!\n"); return 2; } /* Test file open */ fp = fopen(work->szOutput, "a"); if (fp == NULL) { perror(work->szOutput); return 3; } fclose(fp); /* Get my self ip */ if (work->myIP == 0) work->myIP = GetMyIp(); if (work->myIP == -1) return 2; addr.s_addr = work->myIP; printf("\nMy ip is: %s\n", inet_ntoa(addr)); if (!CreateListenSock(work)) { printf("ERROR: Cannot install listen sock\n", argv[0]); return 2; } printf("Listening incoming SOCKS on port %d\n", work->listenPort); work->psocks = malloc(MAXALLOCSOCKS * sizeof(SCANSOCKS)); memset(work->psocks, 0, MAXALLOCSOCKS * sizeof(SCANSOCKS)); return 0; } void main(int argc,char *argv[]) { WORKINGSTRUCT work; int nRes; #ifdef WIN32 WSADATA wsa; WSAStartup(MAKEWORD(1, 0), &wsa); #else int nid; struct sigaction sv; sigemptyset(&sv.sa_mask); sv.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sv, NULL); #endif /* --- COMMON INITS --- */ memset(&work, 0, sizeof(WORKINGSTRUCT)); nRes = DoAllInits(&work, argc, argv); if (nRes) { printf("Failed.\n"); FreeAll(&work); exit(nRes); } #ifndef WIN32 nid = fork(); if (nid == -1) { printf("CANNOT FORK PROCESS."); exit(0); } if (nid != 0) { printf("Launched into the background (pid: %d)\n\n", nid); exit(0); } #endif process_server(&work); FreeAll(&work); #ifdef WIN32 WSACleanup(); #endif }