├── .gitattributes ├── .gitignore ├── 3scan.c └── README /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # ========================= 18 | # Operating System Files 19 | # ========================= 20 | 21 | # OSX 22 | # ========================= 23 | 24 | .DS_Store 25 | .AppleDouble 26 | .LSOverride 27 | 28 | # Icon must end with two \r 29 | Icon 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | *.exe 45 | -------------------------------------------------------------------------------- /3scan.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3Scan - fast HTTP/SOCKS4/SOCKS5 proxy detector. 3 | 4 | You can do anything you want with this software. 5 | (c) 2002 by 3APA3A. 6 | */ 7 | 8 | 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #ifdef _WIN32 20 | #include 21 | #include 22 | #include 23 | #define NIL ((DWORD)0l) 24 | #define RETURNTYPE DWORD WINAPI 25 | #define SHUT_RDWR SD_BOTH 26 | #else 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #define NIL ((void *)0l) 38 | #define RETURNTYPE void * 39 | #endif 40 | 41 | #ifdef __CYGWIN__ 42 | #include 43 | #define daemonize() FreeConsole() 44 | #define SLEEPTIME 1000 45 | #undef _WIN32 46 | #elif _WIN32 47 | #ifdef errno 48 | #undef errno 49 | #endif 50 | #define errno WSAGetLastError() 51 | #define EAGAIN WSAEWOULDBLOCK 52 | #define SLEEPTIME 1 53 | #define close closesocket 54 | #define usleep Sleep 55 | #define pthread_self GetCurrentThreadId 56 | #define getpid GetCurrentProcessId 57 | #define pthread_t DWORD 58 | #define daemonize() FreeConsole() 59 | #else 60 | #include 61 | #define daemonize() daemon(0,0) 62 | #define SLEEPTIME 1000 63 | #endif 64 | 65 | int verbose = 1; 66 | int result = 0; 67 | int threadcount = 0; 68 | int to = 25000; 69 | 70 | int sockgetchar(int sock, int timeosec, int timeousec){ 71 | unsigned char buf; 72 | int res; 73 | fd_set fds; 74 | struct timeval tv = {timeosec,timeousec}; 75 | 76 | FD_ZERO(&fds); 77 | FD_SET(sock, &fds); 78 | if ((res = select (sock+1, &fds, NULL, NULL, &tv))!=1) { 79 | return EOF; 80 | } 81 | if ((res = recv(sock, &buf, 1, 0))!=1) { 82 | return EOF; 83 | } 84 | 85 | /* 86 | fprintf(stderr, " -%d- ", (int)buf); 87 | fflush(stderr); 88 | */ 89 | return((int)buf); 90 | } 91 | 92 | int sockgetline(int sock, char * buf, int bufsize, int delim, int timeout){ 93 | int c; 94 | int i=0, tos, tou; 95 | 96 | if(!bufsize) return 0; 97 | c = sockgetchar(sock, timeout, 0); 98 | if (c == EOF) { 99 | return 0; 100 | } 101 | buf[i++] = c; 102 | tos = (timeout>>4); 103 | tou = ((timeout * 1000) >> 4)%1000; 104 | while(i < bufsize && (c = sockgetchar(sock, tos, tou)) != EOF) { 105 | buf[i++] = c; 106 | if(delim != EOF && c == delim) break; 107 | } 108 | return i; 109 | } 110 | 111 | #define PROXY 1 112 | #define SOCKS4 2 113 | #define SOCKS5 4 114 | #define CONNECT 8 115 | #define WINPROXY 16 116 | #define FTP 32 117 | #define TELNET 64 118 | 119 | struct clientparam { 120 | struct sockaddr_in sins; 121 | struct sockaddr_in sinc; 122 | char * webhost; 123 | struct in_addr webip; 124 | char * url; 125 | char *keyword; 126 | int dosmtp; 127 | }; 128 | 129 | char * dosmtp(struct clientparam* param, int sock, char * module){ 130 | char buf[1024]; 131 | int res; 132 | 133 | if((res = sockgetline(sock,buf,1020,'\r',(1 + (to>>10)))) < 3) { 134 | return "something, not SMTP server (reply is too short)"; 135 | } 136 | buf[res] = 0; 137 | if(verbose > 2)fprintf(stderr, "%s received: %s\n", module, buf); 138 | if(buf[0] != '2' || buf[1] != '2' || buf[2] != '0') { 139 | return "bad SMTP response"; 140 | } 141 | if(param->keyword) { 142 | if(!strstr(buf, param->keyword)) return "No keyword found in server response"; 143 | } 144 | return NULL; 145 | } 146 | 147 | char * dohttp(struct clientparam* param, int sock, char * module){ 148 | char buf[1024]; 149 | int res; 150 | 151 | if (*module == 'H') sprintf(buf, "GET http://%.100s%s%.500s HTTP/1.0\r\nHost: %s\r\n%s\r\n\r\n", param->webhost, param->dosmtp? ":25" : "", param->url, param->webhost, param->dosmtp? "quit" : "Pragma: no-cache"); 152 | else sprintf(buf, "GET %.500s HTTP/1.0\r\nHost: %s\r\n%s\r\n\r\n", param->url, param->webhost, param->dosmtp? "quit" : "Pragma: no-cache"); 153 | if(verbose > 2)fprintf(stderr, "%s sending:\n%s", module, buf); 154 | if(send(sock, buf, strlen(buf), 0) != strlen(buf)) { 155 | return "data not accepted"; 156 | }; 157 | if(param->dosmtp) { 158 | return dosmtp(param, sock, module); 159 | } 160 | if((sockgetline(sock,buf,12,'\r',(1 + (to>>10)))) < 12) { 161 | return "something, not HTTP server (reply is too short)"; 162 | } 163 | buf[12] = 0; 164 | if(verbose > 2)fprintf(stderr, "%s received: %s\n", module, buf); 165 | if(buf[9] != '2') { 166 | return "failed to retrieve requested URL"; 167 | } 168 | if(param->keyword) { 169 | while((res = sockgetline(sock,buf,1023,'\n',(1 + (to>>10)))) > 0){ 170 | buf[res] = 0; 171 | if(strstr(buf, param->keyword)) break; 172 | } 173 | if(res <= 0) { 174 | return "No keyword found in server response"; 175 | } 176 | } 177 | return NULL; 178 | } 179 | 180 | RETURNTYPE doproxy(void * data){ 181 | int sock = -1; 182 | char * string = ""; 183 | 184 | if ((sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 185 | perror("socket"); 186 | string = "error"; 187 | goto CLEANRET1; 188 | } 189 | if (bind(sock, (struct sockaddr *)&((struct clientparam*)data)->sinc,sizeof(struct sockaddr_in)) < 0) { 190 | perror("bind"); 191 | string = "error"; 192 | goto CLEANRET1; 193 | } 194 | if(verbose > 2)fprintf(stderr, "Http connecting %s:%hu\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port)); 195 | if(connect(sock,(struct sockaddr *)&((struct clientparam*)data)->sins,sizeof(struct sockaddr_in))) { 196 | string = "closed"; 197 | goto CLEANRET1; 198 | } 199 | string = dohttp((struct clientparam*) data, sock, "HTTP"); 200 | if (string) goto CLEANRET1; 201 | string = "works OK for us"; 202 | if (verbose == 1) fprintf(stderr, "%s:%hu/HTTP\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port)); 203 | result |= PROXY; 204 | CLEANRET1: 205 | if (verbose > 1) fprintf(stderr, "%s:%hu/HTTP %s\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port), string); 206 | if(sock != -1){ 207 | shutdown(sock, SHUT_RDWR); 208 | close(sock); 209 | } 210 | threadcount--; 211 | return NIL; 212 | } 213 | 214 | RETURNTYPE dosocks4(void *data){ 215 | int sock = -1; 216 | char buf[1024]; 217 | char request[] = {4, 1, 0, 80}; 218 | char * string = ""; 219 | int res; 220 | 221 | if(((struct clientparam*)data)->dosmtp) request[3] = 25; 222 | if ((sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 223 | perror("socket"); 224 | string = "error"; 225 | goto CLEANRET2; 226 | } 227 | if (bind(sock, (struct sockaddr *)&((struct clientparam*)data)->sinc,sizeof(struct sockaddr_in)) < 0) { 228 | perror("bind"); 229 | string = "error"; 230 | goto CLEANRET2; 231 | } 232 | if(verbose > 2)fprintf(stderr, "SOCKS4 connecting %s:%hu\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port)); 233 | if(connect(sock,(struct sockaddr *)&((struct clientparam*)data)->sins,sizeof(struct sockaddr_in))) { 234 | string = "closed"; 235 | goto CLEANRET2; 236 | } 237 | 238 | send(sock, request, sizeof(request), 0); 239 | send(sock, (void *)&((struct clientparam*)data)->webip.s_addr, 4, 0); 240 | send(sock, "3APA3A", 7, 0); 241 | if((res = sockgetline(sock,buf,8,EOF,(1 + (to>>10)))) < 8){ 242 | string = "something, not socks4 (reply is too short)"; 243 | goto CLEANRET2; 244 | } 245 | if(buf[1] != 90) { 246 | string = "failed to establish connection"; 247 | goto CLEANRET2; 248 | } 249 | string = ((struct clientparam*)data)->dosmtp? 250 | dosmtp((struct clientparam*) data, sock, "SOCKS4"): 251 | dohttp((struct clientparam*) data, sock, "SOCKS4"); 252 | if (string) goto CLEANRET2; 253 | string = "works OK for us"; 254 | if (verbose == 1)fprintf(stderr, "%s:%hu/SOCKS4\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port)); 255 | result |= SOCKS4; 256 | CLEANRET2: 257 | if (verbose > 1)fprintf(stderr, "%s:%hu/SOCKS4 %s\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port), string); 258 | if(sock != -1) close(sock); 259 | threadcount--; 260 | return NIL; 261 | } 262 | 263 | RETURNTYPE dosocks5(void * data){ 264 | int sock = -1; 265 | char buf[1024]; 266 | char request[] = {5, 1, 0}; 267 | char request2[] = {5, 1, 0, 1}; 268 | struct linger lg; 269 | char * string = ""; 270 | 271 | lg.l_onoff = 1; 272 | lg.l_linger = 10; 273 | if ((sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 274 | perror("socket"); 275 | string = "error"; 276 | goto CLEANRET3; 277 | } 278 | if (bind(sock, (struct sockaddr *)&((struct clientparam*)data)->sinc,sizeof(struct sockaddr_in)) < 0) { 279 | perror("bind"); 280 | string = "error"; 281 | goto CLEANRET3; 282 | } 283 | setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg)); 284 | setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, NULL, 0); 285 | if(verbose > 2)fprintf(stderr, "Socks5 connecting %s:%hu\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port)); 286 | if(connect(sock,(struct sockaddr *)&((struct clientparam*)data)->sins,sizeof(struct sockaddr_in))) { 287 | string = "closed"; 288 | goto CLEANRET3; 289 | } 290 | 291 | send(sock, request, sizeof(request), 0); 292 | if((sockgetline(sock,buf,2,EOF,(1 + (to>>10)))) < 2){ 293 | string = "something, not socks5 (reply is too short)"; 294 | goto CLEANRET3; 295 | } 296 | if(buf[0] != 5) { 297 | string = "something, not socks5 (version doesn't match)"; 298 | goto CLEANRET3; 299 | } 300 | if(buf[1] != 0) { 301 | string = "authentication required"; 302 | goto CLEANRET3; 303 | } 304 | send(sock, request2, sizeof(request2), 0); 305 | send(sock, (void *)&(((struct clientparam*)data)->webip.s_addr), 4, 0); 306 | send(sock, ((struct clientparam*)data)->dosmtp? "\0\31" : "\0\120", 2, 0); 307 | if((sockgetline(sock,buf,10,EOF,(1 + (to>>10)))) < 10){ 308 | string = "something, not socks5 (reply is too short)"; 309 | goto CLEANRET3; 310 | } 311 | if(buf[0] != 5) { 312 | string = "something, not socks5 (version doesn't match)"; 313 | goto CLEANRET3; 314 | } 315 | if(buf[1] != 0) { 316 | string = "failed to establish connection"; 317 | goto CLEANRET3; 318 | } 319 | string = ((struct clientparam*)data)->dosmtp? 320 | dosmtp((struct clientparam*) data, sock, "SOCKS5"): 321 | dohttp((struct clientparam*) data, sock, "SOCKS5"); 322 | if (string) goto CLEANRET3; 323 | string = "works OK for us"; 324 | if (verbose == 1)fprintf(stderr, "%s:%hu/SOCKS5\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port)); 325 | result |= SOCKS5; 326 | CLEANRET3: 327 | if (verbose > 1)fprintf(stderr, "%s:%hu/SOCKS5 %s\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port), string); 328 | if(sock != -1)close(sock); 329 | threadcount--; 330 | return NIL; 331 | } 332 | 333 | 334 | 335 | RETURNTYPE doconnect(void * data){ 336 | int sock = -1; 337 | char buf[1024]; 338 | char * string = ""; 339 | int res; 340 | 341 | if ((sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 342 | perror("socket"); 343 | string = "error"; 344 | goto CLEANRET4; 345 | } 346 | if (bind(sock, (struct sockaddr *)&((struct clientparam*)data)->sinc,sizeof(struct sockaddr_in)) < 0) { 347 | perror("bind"); 348 | string = "error"; 349 | goto CLEANRET4; 350 | } 351 | if(verbose > 2)fprintf(stderr, "Http CONNECT connecting %s:%hu\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port)); 352 | if(connect(sock,(struct sockaddr *)&((struct clientparam*)data)->sins,sizeof(struct sockaddr_in))) { 353 | string = "closed"; 354 | goto CLEANRET4; 355 | } 356 | 357 | 358 | sprintf(buf, "CONNECT %.100s:%d HTTP/1.0\r\n\r\n", ((struct clientparam*)data)->webhost, ((struct clientparam*)data)->dosmtp? 25:80); 359 | if(verbose > 2)fprintf(stderr, "Http CONNECT sending:\n%s", buf); 360 | if(send(sock, buf, strlen(buf), 0) != strlen(buf)) { 361 | string = "data not accepted"; 362 | goto CLEANRET4; 363 | }; 364 | if((sockgetline(sock,buf,12,'\r',(1 + (to>>10)))) < 12) { 365 | string = "something, not http proxy (reply is too short)"; 366 | goto CLEANRET4; 367 | } 368 | buf[12] = 0; 369 | if(verbose > 2)fprintf(stderr, "Http CONNECT received: %s\n", buf); 370 | if(buf[9] != '2') { 371 | string = "failed to retrieve requested URL"; 372 | goto CLEANRET4; 373 | } 374 | while((res = sockgetline(sock,buf,1023,'\n',(1 + (to>>10)))) > 2){ 375 | buf[res] = 0; 376 | if(verbose > 2)fprintf(stderr, "Http CONNECT received: %s\n", buf); 377 | }; 378 | 379 | string = ((struct clientparam*)data)->dosmtp? 380 | dosmtp((struct clientparam*) data, sock, "CONNECT"): 381 | dohttp((struct clientparam*) data, sock, "CONNECT"); 382 | if (string) goto CLEANRET4; 383 | string = "works OK for us"; 384 | if (verbose == 1) fprintf(stderr, "%s:%hu/CONNECT\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port)); 385 | result |= CONNECT; 386 | CLEANRET4: 387 | if (verbose > 1) fprintf(stderr, "%s:%hu/CONNECT %s\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port), string); 388 | if(sock != -1)close(sock); 389 | threadcount--; 390 | return NIL; 391 | } 392 | 393 | RETURNTYPE dotrojan(void * data){ 394 | int sock = -1; 395 | char buf[1024]; 396 | char * string = ""; 397 | char sig[] = {0x01, 0x0D, 0x00, 0x01}; 398 | int i; 399 | 400 | if ((sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 401 | perror("socket"); 402 | string = "error"; 403 | goto CLEANRET5; 404 | } 405 | if (bind(sock, (struct sockaddr *)&((struct clientparam*)data)->sinc,sizeof(struct sockaddr_in)) < 0) { 406 | perror("bind"); 407 | string = "error"; 408 | goto CLEANRET5; 409 | } 410 | if(verbose > 2)fprintf(stderr, "WINPROXY connecting %s:%hu\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port)); 411 | if(connect(sock,(struct sockaddr *)&((struct clientparam*)data)->sins,sizeof(struct sockaddr_in))) { 412 | string = "closed"; 413 | goto CLEANRET5; 414 | } 415 | 416 | if(sockgetline(sock,buf,5,EOF,(1 + (to>>10))) < 5 || sockgetline(sock,buf+5,10,0,(1 + (to>>10))) < 5) { 417 | string = "something, not WINPROXY (reply is too short)"; 418 | goto CLEANRET5; 419 | } 420 | buf[15] = 0; 421 | if(verbose > 2)fprintf(stderr, "WINPROXY received: [0x%02x0x%02x0x%02x0x%02x0x%02x]%s\n", (unsigned)buf[0], (unsigned)buf[1], (unsigned)buf[2], (unsigned)buf[3], (unsigned)buf[4], buf+5); 422 | if(memcmp(buf+1, sig, 4)) { 423 | string = "something, not WINPROXY (signature doesn't match)"; 424 | goto CLEANRET5; 425 | } 426 | for (i = 5; buf[i]; i++) { 427 | if(buf[i] < '0' || buf[i] > '9') { 428 | string = "something, not WINPROXY (no numbers)"; 429 | goto CLEANRET5; 430 | } 431 | } 432 | string = "works OK for us"; 433 | if (verbose == 1) fprintf(stderr, "%s:%hu/WINPROXY\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port)); 434 | result |= WINPROXY; 435 | CLEANRET5: 436 | if (verbose > 1) fprintf(stderr, "%s:%hu/WINPROXY %s\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port), string); 437 | if(sock != -1)close(sock); 438 | threadcount--; 439 | return NIL; 440 | } 441 | 442 | 443 | RETURNTYPE doftp(void *data){ 444 | int sock = -1; 445 | char buf[1024]; 446 | char * string = ""; 447 | int res; 448 | 449 | if(!((struct clientparam*)data)->dosmtp) return NIL; 450 | if ((sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 451 | perror("socket"); 452 | string = "error"; 453 | goto CLEANRET6; 454 | } 455 | if (bind(sock, (struct sockaddr *)&((struct clientparam*)data)->sinc,sizeof(struct sockaddr_in)) < 0) { 456 | perror("bind"); 457 | string = "error"; 458 | goto CLEANRET6; 459 | } 460 | if(verbose > 2)fprintf(stderr, "FTP connecting %s:%hu\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port)); 461 | if(connect(sock,(struct sockaddr *)&((struct clientparam*)data)->sins,sizeof(struct sockaddr_in))) { 462 | string = "closed"; 463 | goto CLEANRET6; 464 | } 465 | res = sockgetline(sock,buf,1023,'\n',(1 + (to>>10))); 466 | buf[res] = 0; 467 | if(verbose > 2)fprintf(stderr, "FTP received: %s", buf); 468 | if(res < 4) { 469 | string = "something, not FTP proxy (no banner)"; 470 | goto CLEANRET6; 471 | } 472 | if(buf[0] != '2' || buf[1] != '2' || buf[2] != '0'){ 473 | string = "something, not FTP proxy (wrong banner)"; 474 | goto CLEANRET6; 475 | } 476 | sprintf(buf, "USER zaraza@%.100s:%d\r\n", ((struct clientparam*)data)->webhost, 25); 477 | if(verbose > 2)fprintf(stderr, "FTP sending:%s", buf); 478 | if(send(sock, buf, strlen(buf), 0) != strlen(buf)) { 479 | string = "data not accepted"; 480 | goto CLEANRET6; 481 | }; 482 | res = sockgetline(sock,buf,1023,'\n',(1 + (to>>10))); 483 | buf[res] = 0; 484 | if(verbose > 2)fprintf(stderr, "FTP received: %s", buf); 485 | if(res < 4 || buf[0] < '0' || buf[1] < '0' || buf[2] < '0' || buf[0] > '9' || buf[1] > '9' || buf[2] > '9') { 486 | string = "something, not FTP proxy (no banner)"; 487 | goto CLEANRET6; 488 | } 489 | string = dosmtp((struct clientparam*) data, sock, "FTP"); 490 | if (string) goto CLEANRET6; 491 | string = "works OK for us"; 492 | 493 | if (verbose == 1) fprintf(stderr, "%s:%hu/FTP %s\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port), string); 494 | result |= FTP; 495 | 496 | CLEANRET6: 497 | if (verbose > 1) fprintf(stderr, "%s:%hu/FTP %s\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port), string); 498 | if(sock != -1)close(sock); 499 | threadcount--; 500 | return NIL; 501 | } 502 | 503 | RETURNTYPE dotelnet(void *data){ 504 | int sock = -1; 505 | char buf[1024]; 506 | char * string = ""; 507 | int res; 508 | 509 | if ((sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 510 | perror("socket"); 511 | string = "error"; 512 | goto CLEANRET7; 513 | } 514 | if (bind(sock, (struct sockaddr *)&((struct clientparam*)data)->sinc,sizeof(struct sockaddr_in)) < 0) { 515 | perror("bind"); 516 | string = "error"; 517 | goto CLEANRET7; 518 | } 519 | if(verbose > 2)fprintf(stderr, "TELNET connecting %s:%hu\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port)); 520 | if(connect(sock,(struct sockaddr *)&((struct clientparam*)data)->sins,sizeof(struct sockaddr_in))) { 521 | string = "closed"; 522 | goto CLEANRET7; 523 | } 524 | res = sockgetline(sock,buf,1023,'\n',(1 + (to>>10))); 525 | buf[res] = 0; 526 | if(verbose > 2)fprintf(stderr, "FTP received: %s", buf); 527 | if(res < 2) { 528 | string = "something, not TELNET proxy (no banner)"; 529 | goto CLEANRET7; 530 | } 531 | if(strstr(buf, "poon")) { 532 | sprintf(buf, "%.100s %d\r\n", ((struct clientparam*)data)->webhost, ((struct clientparam*)data)->dosmtp? 25:80); 533 | } 534 | else if(strstr(buf, "gw") || strstr(buf, "telnet")) { 535 | sprintf(buf, "telnet %.100s %d\r\n", ((struct clientparam*)data)->webhost, ((struct clientparam*)data)->dosmtp? 25:80); 536 | } 537 | else if(strstr(buf, "CCP")) { 538 | sprintf(buf, "open %.100s %d\r\n", ((struct clientparam*)data)->webhost, ((struct clientparam*)data)->dosmtp? 25:80); 539 | } 540 | else { 541 | sprintf(buf, "%.100s:%d\r\n", ((struct clientparam*)data)->webhost, ((struct clientparam*)data)->dosmtp? 25:80); 542 | } 543 | string = ((struct clientparam*)data)->dosmtp? 544 | dosmtp((struct clientparam*) data, sock, "CONNECT"): 545 | dohttp((struct clientparam*) data, sock, "CONNECT"); 546 | if (string) goto CLEANRET7; 547 | string = "works OK for us"; 548 | 549 | if (verbose == 1) fprintf(stderr, "%s:%hu/FTP %s\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port), string); 550 | result |= FTP; 551 | 552 | CLEANRET7: 553 | if (verbose > 1) fprintf(stderr, "%s:%hu/FTP %s\n", inet_ntoa(((struct clientparam*)data)->sins.sin_addr), ntohs(((struct clientparam*)data)->sins.sin_port), string); 554 | if(sock != -1)close(sock); 555 | threadcount--; 556 | return NIL; 557 | } 558 | 559 | 560 | int main(int argc, char* argv[]){ 561 | int test, deftest = 0; 562 | struct in_addr ia; 563 | struct in_addr ias; 564 | struct clientparam *newparam; 565 | pthread_t thread; 566 | char * portlist; 567 | struct hostent* hp; 568 | int smtp = 0; 569 | char *s; 570 | 571 | #ifdef _WIN32 572 | WSADATA wd; 573 | WSAStartup(MAKEWORD( 1, 1 ), &wd); 574 | #endif 575 | 576 | if(argc < 6) { 577 | fprintf(stderr, "3Scan - fast HTTP/SOCKS4/SOCKS5 detector\n" 578 | "Usage: %s ip[/srcip] portlist option webhost url [keyword] [timeout]\n" 579 | "\tip - IP address to test\n" 580 | "\tsrcip - source IP address to\n" 581 | "\tportlist - comma delimited list of ports. May contain additional tests:\n" 582 | "\t s - Socks 4/5 test for this port\n" 583 | "\t p - HTTP/CONNECT proxy test for this port\n" 584 | "\t f - FTP proxy test for this port\n" 585 | "\t t - TELNET proxy test for this port\n" 586 | "\toption:\n" 587 | "\t p - scan for HTTP proxy on all ports\n" 588 | "\t c - scan for CONNECT proxy on all ports\n" 589 | "\t f - scan for FTP proxy on all ports\n" 590 | "\t t - scan for TELNET proxy on all ports\n" 591 | "\t 4 - scan for Socks v4 proxy on all ports\n" 592 | "\t 5 - scan for Socks v5 proxy on all ports\n" 593 | "\t w - scan for WINPROXY\n" 594 | "\t v - be verbose\n" 595 | "\t V - be Very Verbose\n" 596 | "\t s - be silent (exit code is non-zero if proxy detected)\n" 597 | "\t S - check SMTP instead of HTTP\n" 598 | "\twebhost - IP address for testing web server to try access via proxy\n" 599 | "\turl - URL to request on testing Web server\n" 600 | "\t We will try to access http://webhosturl via proxy\n" 601 | "\tkeyword - keyword to look for in requested page. If keyword not found\n" 602 | "\t proxy will not be reported\n" 603 | "\ttimeout - timeout in milliseconds\n" 604 | "example: %s localhost 1080s,3128p,8080p 4v www.myserver.com /test.html\n" 605 | "will test all 3 ports for Socks 4, additionally 3128 and 8080 will be tested\n" 606 | "for HTTP proxy, 1080 for both Socks 4 and 5, tests will be verbose.\n" 607 | "http://www.myserver.com/test.html should exist.\n" 608 | "\n(c) 2002 by 3APA3A, http://www.security.nnov.ru\n" 609 | ,argc?argv[0]:"?",argc?argv[0]:"?"); 610 | return 100; 611 | } 612 | if(argc > 7) to = atoi(argv[7]); 613 | if(strchr(argv[3], 'p')) deftest |= PROXY; 614 | if(strchr(argv[3], 'w')) deftest |= WINPROXY; 615 | if(strchr(argv[3], 'f')) deftest |= FTP; 616 | if(strchr(argv[3], 't')) deftest |= FTP; 617 | if(strchr(argv[3], 'c')) deftest |= CONNECT; 618 | if(strchr(argv[3], '4')) deftest |= SOCKS4; 619 | if(strchr(argv[3], '5')) deftest |= SOCKS5; 620 | if(strchr(argv[3], 'v')) verbose = 2; 621 | if(strchr(argv[3], 'V')) verbose = 3; 622 | if(strchr(argv[3], 's')) verbose = 0; 623 | if(strchr(argv[3], 'S')) smtp = 1; 624 | ias.s_addr = 0; 625 | if((s = strchr(argv[1], '/'))) { 626 | *s = 0; 627 | } 628 | 629 | hp = gethostbyname(argv[1]); 630 | if (!hp) { 631 | perror("gethostbyname()"); 632 | return 102; 633 | } 634 | ia.s_addr = *(unsigned long *)hp->h_addr; 635 | 636 | for (portlist = strtok(argv[2], ","); portlist || (deftest & WINPROXY); portlist = strtok(NULL, ",")) { 637 | newparam = malloc(sizeof(struct clientparam)); 638 | 639 | if(!newparam) { 640 | fprintf(stderr, "Memory allocation failed"); 641 | return 0; 642 | } 643 | memset(newparam, 0, sizeof(struct clientparam)); 644 | if(s){ 645 | hp = gethostbyname(s+1); 646 | newparam->sinc.sin_addr.s_addr = *(unsigned long *)hp->h_addr; 647 | } 648 | test = deftest; 649 | newparam->sins.sin_addr.s_addr = ia.s_addr; 650 | newparam->sins.sin_family = AF_INET; 651 | newparam->sinc.sin_family = AF_INET; 652 | newparam->webhost = argv[4]; 653 | newparam->url = argv[5]; 654 | newparam->keyword = (argc > 6)?argv[6] : 0; 655 | newparam->dosmtp = smtp; 656 | hp = gethostbyname(argv[4]); 657 | if (!hp) { 658 | perror("gethostbyname() error resolving target"); 659 | return 0; 660 | } 661 | newparam->webip.s_addr = *(unsigned long *)hp->h_addr; 662 | if(!portlist) { 663 | newparam->sins.sin_port = htons(608); 664 | threadcount++; 665 | #ifdef _WIN32 666 | CreateThread((LPSECURITY_ATTRIBUTES )NULL, 16384, dotrojan, (void *) newparam, (DWORD)0, &thread); 667 | #else 668 | pthread_create(&thread, NULL, dotrojan, (void *)newparam); 669 | #endif 670 | break; 671 | } 672 | if(strchr(portlist, 'p')) test |= (CONNECT | PROXY); 673 | if(strchr(portlist, 's')) test |= (SOCKS4|SOCKS5); 674 | if(strchr(portlist, 'f')) test |= FTP; 675 | if(strchr(portlist, 't')) test |= TELNET; 676 | newparam->sins.sin_port = htons(atoi(portlist)); 677 | if (test & PROXY) { 678 | threadcount++; 679 | #ifdef _WIN32 680 | CreateThread((LPSECURITY_ATTRIBUTES )NULL, 16384, doproxy, (void *) newparam, (DWORD)0, &thread); 681 | #else 682 | pthread_create(&thread, NULL, doproxy, (void *)newparam); 683 | #endif 684 | } 685 | if (test & CONNECT) { 686 | threadcount++; 687 | #ifdef _WIN32 688 | CreateThread((LPSECURITY_ATTRIBUTES )NULL, 16384, doconnect, (void *) newparam, (DWORD)0, &thread); 689 | #else 690 | pthread_create(&thread, NULL, doconnect, (void *)newparam); 691 | #endif 692 | } 693 | if (test & SOCKS4) { 694 | threadcount++; 695 | #ifdef _WIN32 696 | CreateThread((LPSECURITY_ATTRIBUTES )NULL, 16384, dosocks4, (void *) newparam, (DWORD)0, &thread); 697 | #else 698 | pthread_create(&thread, NULL, dosocks4, (void *)newparam); 699 | #endif 700 | } 701 | if (test & SOCKS5) { 702 | threadcount++; 703 | #ifdef _WIN32 704 | CreateThread((LPSECURITY_ATTRIBUTES )NULL, 16384, dosocks5, (void *) newparam, (DWORD)0, &thread); 705 | #else 706 | pthread_create(&thread, NULL, dosocks5, (void *)newparam); 707 | #endif 708 | } 709 | if (test & FTP) { 710 | threadcount++; 711 | #ifdef _WIN32 712 | CreateThread((LPSECURITY_ATTRIBUTES )NULL, 16384, doftp, (void *) newparam, (DWORD)0, &thread); 713 | #else 714 | pthread_create(&thread, NULL, doftp, (void *)newparam); 715 | #endif 716 | } 717 | if (test & TELNET) { 718 | threadcount++; 719 | #ifdef _WIN32 720 | CreateThread((LPSECURITY_ATTRIBUTES )NULL, 16384, dotelnet, (void *) newparam, (DWORD)0, &thread); 721 | #else 722 | pthread_create(&thread, NULL, dotelnet, (void *)newparam); 723 | #endif 724 | } 725 | } 726 | for ( ; to > 0; to-=16){ 727 | if(!threadcount)break; 728 | usleep((SLEEPTIME<<4)); 729 | } 730 | return result; 731 | } 732 | 733 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 3Scan - fast HTTP/SOCKS4/SOCKS5 detector 2 | 3 | Compile under *nix: 4 | gcc -o3scan 3scan.c 5 | 6 | Compile under Windows: 7 | gcc -o3scan 3scan.c -lws2_32 8 | or 9 | cl 3scan.c ws2_32.lib 10 | 11 | Usage: 3scan.exe ip[/srcip] portlist option webhost url [keyword] [timeout] 12 | ip - IP address to test 13 | srcip - source IP address to use 14 | portlist - comma delimited list of ports. May contain additional tests: 15 | s - Socks 4/5 test for this port 16 | p - HTTP/CONNECT proxy test for this port 17 | f - FTP proxy test for this port 18 | t - TELNET proxy test for this port 19 | option: 20 | p - scan for HTTP proxy on all ports 21 | c - scan for CONNECT proxy on all ports 22 | f - scan for FTP proxy on all ports 23 | t - scan for TELNET proxy on all ports 24 | 4 - scan for Socks v4 proxy on all ports 25 | 5 - scan for Socks v5 proxy on all ports 26 | w - scan for WINPROXY 27 | v - be verbose 28 | V - be Very Verbose 29 | s - be silent (exit code is non-zero if proxy detected) 30 | S - check SMTP instead of HTTP 31 | webhost - IP address for testing web server to try access via proxy 32 | url - URL to request on testing Web server 33 | We will try to access http://webhosturl via proxy 34 | keyword - keyword to look for in requested page. If keyword not found 35 | proxy will not be reported 36 | timeout - timeout in milliseconds 37 | example: 3scan.exe localhost 1080s,3128p,8080p 4v www.myserver.com /test.html 38 | will test all 3 ports for Socks 4, additionally 3128 and 8080 will be tested 39 | for HTTP proxy, 1080 for both Socks 4 and 5, tests will be verbose. 40 | http://www.myserver.com/test.html should exist. 41 | 42 | (c) 2002 by 3APA3A, http://www.security.nnov.ru 43 | --------------------------------------------------------------------------------