1 /*
2 
3 NST Simple HTTP Scanner v0.4
4 
5 ChangeLog: v0.1 - Initial realease
6            v0.2 - Security bugs fixed
7                 - Add some error handling
8                 - New feature: HTML report at the end of the scan
9                 - New feature: detection of directory listing
10                 - Default requests.txt improved
11            v0.3 - Security bugs fixed
12                 - New feature: options handling
13                 - New feature: added some headers detection
14                 - New feature: support for proxy servers (HTTP Tunneling)
15                 - Default requests.txt improved
16            v0.4 - Security bugs fixed
17                 - HTML Report improved
18                 - New feature: subdomains scanning
19                 - New feature: option -u for updates check
20                 - New feature: use of POSIX threads (the scanner is much more faster)
21                 - Default requests.txt improved
22 
23 Author: Paisterist
24 Date: 2006-09-16
25 
26 [N]eo [S]ecurity [T]eam - http://www.neosecurityteam.net
27 
28 [root@home shttpscanner]# gcc 0.4.c -o 0.4 -lpthread
29 [root@home shttpscanner]# ./0.4
30 [!] NST Simple HTTP Scanner v0.4 by Paisterist - 2006/07/30
31 [!] [N]eo [S]ecurity [T]eam - http://www.neosecurityteam.net
32 
33 [+] Usage: ./0.4 -h host -d path -p port
34 [+] Example: ./0.4 -h www.google.com -d / -p 80 -P 216.155.15.57:3128 -e
35 
36 [+] Options:
37 ------------
38         -h: hostname. Example: www.google.com
39         -p: port number to connect by (80 by default).
40         -d: path ("/ by default"). Example: /web/
41         -e: use it for evading the responses used for not found errors.
42         -P: proxy server and port. Example: 216.155.15.57:3128
43         -r: requests file (requests.txt by default)
44         -m: scanning mode. O (by default) for get requests, 1 for scanning subdomains and 2 for both of them
45         -s: subdomains file (subdomains.txt by default)
46         -t: number of threads (64 by default). Must be between 0 and 1000
47         -u: use this option alone to check for updates.
48 [root@home shttpscanner]#
49 
50 */
51 
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <time.h>
56 #include <pthread.h>
57 #ifdef WIN32
58 #pragma comment(lib, "ws2_32")
59 #include <winsock.h>
60 #else
61 #include <sys/types.h>
62 #include <sys/socket.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
65 #include <netdb.h>
66 #endif
67 
68 #define CURRENT_VERSION 0.4
69 #define HTML_CODE_SIZE 999999
70 #define RECEIVE_SIZE 9999
71 #define REQUEST_SIZE 1000
72 #define REQUESTS_FILE "/usr/local/share/shttpscanner/requests.txt"
73 #define SUBDOMAINS_FILE "/usr/local/share/shttpscanner/subdomains.txt"
74 #define MAX_REQUESTS 10000
75 #define URL_SIZE 100
76 #define THREADS 64
77 
78 int Usage(char *argv[]);
79 void Rights(void);
80 char* GetBanner(char *hostname, int port, char *c_host, int c_port, struct sockaddr_in *host, int opt);
81 char* Get404(char *hostname, int port, char *c_host, int c_port, struct sockaddr_in *host, char *dir);
82 char* Get404Subdomain(char *hostname, int port, struct sockaddr_in host, struct hostent *h);
83 int CheckPort(char *hostname, int port, struct sockaddr_in *host);
84 int DirectoryListing(char *dir, char *rec, char *hostname, char *banner);
85 void CRLF(char *string);
86 char* stripSlash(char *string);
87 char* stripWWW(char *string);
88 char* time_format(time_t *begin, time_t *end);
89 char* formatProxy(char *string, int ret);
90 int invalidData(char *string, int limit);
91 
92 void Report_Header(char *host, char *html);
93 int Report_Save(char *host, char *html);
94 int Report_Add(char *dir, char *response, char *html, char *extra, int type, int s_type);
95 int Report_Add_Details(int type, char *extra, char *html);
96 void Report_Start(char *html, int type);
97 
98 void FATAL_ERROR(char *message);
99 void *ThreadGETRoutine(void* r_data);
100 void *ThreadSubdomainRoutine(void* r_data);
101 
102 int CheckUpdate();
103 
104 int COLOR=0;
105 int n_requests=0, n_subdomains=0;
106 int n_total, n_total1;
107 int n, n1;
108 int rounds = 0;
109 
110 char *html;
111 
112 struct OPTIONS {
113        char O_C_HOST[50];
114        int O_C_PORT;
115        char O_PROXY_HOST[50];
116        int O_PROXY_PORT;
117        char O_HOST[50];
118        char O_PATH[50];
119        char O_REQUESTS[50];
120        char O_HTML[50];
121        int O_PORT;
122        int O_CHECK_UPDATE;
123        int O_EVADING;
124        int O_THREADS;
125        int S_MODE;
126        char O_SUBDOMAINS[50];
127 };
128 
129 struct request_data {
130        struct sockaddr_in host;
131        char* request;
132        char* subdomain;
133        char* error_response;
134        char* banner;
135 };
136 
137 struct OPTIONS o_handler;
138 struct request_data *r_data;
139 
140 pthread_t *threads;
141 
main(int argc,char * argv[])142 int main(int argc, char *argv[]) {
143     #ifdef WIN32
144     WSADATA ws;
145     SOCKET sock;
146     #else
147     int sock;
148     #endif
149 
150     time_t begin, begin1, begin2, end, end1, end2;
151     char *requests[MAX_REQUESTS], *p;
152     char *subdomains[MAX_REQUESTS];
153     char *banner;
154     char *error_response;
155     char *serror_response;
156     char *nulo = NULL;
157     int n_threads = 0;
158 
159     int error=0, count=0, i, lapso=0, arg_i;
160     int pos;
161 
162     double div;
163 
164     struct sockaddr_in host;
165     struct sockaddr_in remote;
166     struct hostent *h;
167 
168     FILE *fp;
169 
170     #ifdef WIN32
171     WSAStartup(MAKEWORD(2, 2), &ws);
172     #endif
173 
174     html = (char *) malloc(sizeof(char) * 999999);
175     error_response = (char *) malloc(sizeof(char) * 4);
176     serror_response = (char *) malloc(sizeof(char) * 4);
177 
178     time(&begin);
179     if (argc<2) {
180        Usage(argv);
181        return 0;
182     }
183 
184     o_handler.O_PORT = 80;
185     o_handler.O_EVADING = 0;
186     o_handler.O_CHECK_UPDATE = 0;
187 
188     for (arg_i = 1; arg_i < argc; arg_i++) {
189         switch (argv[arg_i][0]) {
190                case '-': {
191                     if (((int) argv[arg_i][1] >= 97 && (int) argv[arg_i][1] <= 122) || ((int) argv[arg_i][1] >= 65 && (int) argv[arg_i][1] <= 90)) {
192                        switch (argv[arg_i][1]) {
193                               case 'h': {
194                                    if (strlen(o_handler.O_HOST)>0) {
195                                       Usage(argv);
196                                       return 0;
197                                    }
198 
199                                    if (argv[arg_i + 1][0] == '-') {
200                                       Usage(argv);
201                                       return 0;
202                                    }
203                                    else {
204                                         strncpy(o_handler.O_HOST, argv[arg_i + 1], sizeof(o_handler.O_HOST));
205                                    }
206                               } break;
207                               case 'p': {
208                                         if (atoi(argv[arg_i + 1]) <=0 || atoi(argv[arg_i + 1]) >65535) FATAL_ERROR("[+] Invalid port number: it must be between 0 and 65535. Quiting...\n");
209                                         else {
210                                              o_handler.O_PORT = atoi(argv[arg_i + 1]);
211                                         }
212                               } break;
213                               case 'd': {
214                                    if (strlen(o_handler.O_PATH) > 0) {
215                                       Usage(argv);
216                                       return 0;
217                                    }
218 
219                                    if (strstr(argv[arg_i + 1], "/") != argv[arg_i + 1] || argv[arg_i + 1][strlen(argv[arg_i + 1])-1] != '/') {
220                                       printf("[!] Invalid directory path: it must contain slashes. Quiting...\n");
221                                       return 0;
222                                    }
223                                    else strncpy(o_handler.O_PATH, argv[arg_i + 1], sizeof(o_handler.O_PATH));
224                               } break;
225                               case 'r': {
226                                    if (strlen(o_handler.O_REQUESTS) > 0 || argv[arg_i + 1][0] == '-') {
227                                       Usage(argv);
228                                       return 0;
229                                    }
230 
231                                    strncpy(o_handler.O_REQUESTS, argv[arg_i + 1], sizeof(o_handler.O_REQUESTS));
232                               } break;
233                               case 'e': {
234                                    if (o_handler.O_EVADING != 0) {
235                                       Usage(argv);
236                                       return 0;
237                                    }
238 
239                                    o_handler.O_EVADING = 1;
240 
241                               } break;
242                               case 'P': {
243                                    if (strlen(o_handler.O_PROXY_HOST) > 0 || !strstr(argv[arg_i + 1], ":") || strlen(argv[arg_i + 1]) < 10) {
244                                       Usage(argv);
245                                       return 0;
246                                    }
247                                    if (formatProxy(argv[arg_i + 1], 0) != NULL && formatProxy(argv[arg_i + 1], 1) != NULL) {
248                                       strncpy(o_handler.O_PROXY_HOST, formatProxy(argv[arg_i + 1], 0), sizeof(o_handler.O_PROXY_HOST));
249                                       o_handler.O_PROXY_PORT = atoi(formatProxy(argv[arg_i + 1], 1));
250                                    }
251                                    else {
252                                         Usage(argv);
253                                         return 0;
254                                    }
255                               } break;
256                               case 'm': {
257                                    if (atoi(argv[arg_i +1]) >= 0 && atoi(argv[arg_i + 1]) <= 2 && argv[arg_i + 1] && !o_handler.S_MODE) {
258                                       o_handler.S_MODE = atoi(argv[arg_i + 1]);
259                                    }
260                                    else {
261                                         Usage(argv);
262                                         return 0;
263                                    }
264                               } break;
265                               case 's': {
266                                    if (strlen(o_handler.O_SUBDOMAINS) > 0 || argv[arg_i + 1][0] == '-') {
267                                       Usage(argv);
268                                       return 0;
269                                    }
270 
271                                    strncpy(o_handler.O_SUBDOMAINS, argv[arg_i + 1], sizeof(o_handler.O_SUBDOMAINS));
272                               } break;
273                               case 't': {
274                                    if (atoi(argv[arg_i + 1]) <= 0 || atoi(argv[arg_i + 1]) > 1000 || o_handler.O_THREADS) {
275                                       Usage(argv);
276                                       return 0;
277                                    }
278                                    o_handler.O_THREADS = atoi(argv[arg_i + 1]);
279                               } break;
280                               case 'u': {
281                                    if (o_handler.O_CHECK_UPDATE == 1) {
282                                       Usage(argv);
283                                       return 0;
284                                    }
285 
286                                    o_handler.O_CHECK_UPDATE = 1;
287                               } break;
288                               default: {
289                                        Usage(argv);
290                                        return 0;
291                               }
292                        }
293                     }
294                }
295         }
296     }
297 
298     if (o_handler.O_CHECK_UPDATE == 1) {
299        CheckUpdate();
300        return 0;
301     }
302 
303     if (!o_handler.O_HOST) Usage(argv);
304     if (strlen(o_handler.O_PATH) <= 0) strcpy(o_handler.O_PATH, "/");
305     if (strlen(o_handler.O_REQUESTS) <= 0) strcpy(o_handler.O_REQUESTS, REQUESTS_FILE);
306     if (strlen(o_handler.O_SUBDOMAINS) <= 0) strcpy(o_handler.O_SUBDOMAINS, SUBDOMAINS_FILE);
307     if ((h = gethostbyname(o_handler.O_HOST)) == NULL) FATAL_ERROR("[!] Fatal error: unrecognized host. Quiting...\n");
308     if (!o_handler.S_MODE) o_handler.S_MODE = 0;
309     if (!o_handler.O_THREADS) o_handler.O_THREADS = THREADS;
310 
311     threads = (pthread_t *) malloc(sizeof(pthread_t) * o_handler.O_THREADS);
312     r_data = (struct request_data *) malloc(sizeof(struct request_data) * o_handler.O_THREADS);
313 
314     if (strlen(o_handler.O_PROXY_HOST) > 0 && o_handler.O_PROXY_PORT > 0) {
315        if ((h = gethostbyname(o_handler.O_PROXY_HOST)) == NULL) FATAL_ERROR("[!] Fatal error: unrecognized proxy server. Quiting...\n");
316 
317        host.sin_family=AF_INET;
318        host.sin_port=htons((short) o_handler.O_PROXY_PORT);
319        host.sin_addr.s_addr=inet_addr(o_handler.O_PROXY_HOST);
320 
321        memcpy(&host.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
322 
323        strcpy(o_handler.O_C_HOST, o_handler.O_PROXY_HOST);
324        o_handler.O_C_PORT = o_handler.O_PROXY_PORT;
325     }
326     else {
327          strcpy(o_handler.O_C_HOST, o_handler.O_HOST);
328          o_handler.O_C_PORT = o_handler.O_PORT;
329     }
330 
331     host.sin_family=AF_INET;
332     host.sin_port=htons((short) o_handler.O_C_PORT);
333     host.sin_addr.s_addr=inet_addr(o_handler.O_C_HOST);
334 
335     memcpy(&host.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
336 
337     CheckPort(o_handler.O_C_HOST, o_handler.O_C_PORT, &host);
338 
339     Report_Header(o_handler.O_HOST, html);
340 
341     Report_Add_Details(0, o_handler.O_HOST, html);
342     banner = GetBanner(o_handler.O_HOST, o_handler.O_PORT, o_handler.O_C_HOST, o_handler.O_C_PORT, &host, 0);
343     GetBanner(o_handler.O_HOST, o_handler.O_PORT, o_handler.O_C_HOST, o_handler.O_C_PORT, &host, 1);
344 
345     if (banner) Report_Add_Details(1, banner, html);
346 
347     error_response = Get404(o_handler.O_HOST, o_handler.O_PORT, o_handler.O_C_HOST, o_handler.O_C_PORT, &host, o_handler.O_PATH);
348     serror_response = Get404Subdomain(o_handler.O_HOST, o_handler.O_PORT, host, h);
349 
350     Report_Add_Details(-1, error_response, html);
351     Report_Add_Details(5, serror_response, html);
352 
353     printf("\n");
354 
355     if (o_handler.S_MODE == 0 || o_handler.S_MODE == 2) {
356        time(&begin1);
357        fp=fopen(o_handler.O_REQUESTS, "r");
358 
359     if (!fp) {
360        printf("[!] Can't open %s for reading requests. Quiting...\n", o_handler.O_REQUESTS);
361        return 0;
362     }
363 
364     while (!feof(fp) && count<MAX_REQUESTS) {
365           requests[count] = (char *) malloc(sizeof(char) * 1000);
366           fgets(requests[count], 1000, fp);
367           CRLF(requests[count]);
368           if (strlen(requests[count])>0 && *requests[count] == '/') count++;
369           else requests[count] = (char *) NULL;
370     }
371 
372 
373     if (count == 0) {
374        printf("[!] No requests found at %s. Quiting...\n", o_handler.O_REQUESTS);
375        return 0;
376     }
377 
378     n = n_total = count;
379 
380     printf("[+] Starting GET scaning with %d requests...\n\n", count);
381 
382     count = 0;
383     n_threads = 0;
384 
385     Report_Start(html, 0);
386 
387     while (requests[count]) {
388           if (n_threads == o_handler.O_THREADS) {
389              rounds++;
390              n_threads = 0;
391              pthread_join(threads[n_threads], NULL);
392           }
393 
394           r_data[n_threads].request = requests[count];
395           r_data[n_threads].host = host;
396           r_data[n_threads].error_response = error_response;
397           r_data[n_threads].banner = banner;
398           r_data[n_threads].subdomain = NULL;
399 
400           if (n_threads > 0 && rounds > 0)
401              pthread_join(threads[n_threads], NULL);
402 
403           if (pthread_create(&threads[n_threads], NULL, &ThreadGETRoutine, (void *) &r_data[n_threads]) == -1)
404              FATAL_ERROR("[!] Can't create thread. Quiting...\n");
405 
406           count++;
407           n_threads++;
408     }
409 
410     count = 0;
411     n_threads--;
412 
413     if (rounds == 0) n_threads = 0;
414     while (n_threads < o_handler.O_THREADS) {
415           pthread_join(threads[n_threads], NULL);
416           n_threads++;
417     }
418 
419     rounds = 0;
420     n_threads = 0;
421     n_requests = 0;
422 
423     time(&end1);
424     }
425 
426     if (o_handler.S_MODE == 1 || o_handler.S_MODE == 2) {
427        time(&begin2);
428        count=0;
429        strcpy(o_handler.O_HOST, stripWWW(o_handler.O_HOST));
430        fp=fopen(o_handler.O_SUBDOMAINS, "r");
431 
432        if (!fp) {
433           printf("[!] Can't open %s for reading subdomains. Quiting...\n", o_handler.O_SUBDOMAINS);
434           return 0;
435        }
436 
437        while (!feof(fp) && count<MAX_REQUESTS) {
438           subdomains[count] = (char *) malloc(sizeof(char) * 1000);
439           fgets(subdomains[count], 1000, fp);
440           CRLF(subdomains[count]);
441           if (strlen(subdomains[count])>0) count++;
442           else subdomains[count] = (char *) NULL;
443        }
444 
445 
446        if (count == 0) {
447           printf("[!] No subdomains found at %s. Quiting...\n", o_handler.O_SUBDOMAINS);
448           return 0;
449        }
450 
451        n1 = n_total1 = count;
452 
453        if (o_handler.S_MODE == 2) printf("\n");
454        printf("[+] Starting subdomain scaning with %d entries...\n\n", count);
455 
456        count = 0;
457 
458        Report_Start(html, 1);
459 
460        while (subdomains[count]) {
461              if (n_threads == o_handler.O_THREADS) {
462                 rounds++;
463                 n_threads = 0;
464                 pthread_join(threads[n_threads], NULL);
465              }
466 
467              if (n_threads > 0 && rounds > 0)
468                 pthread_join(threads[n_threads], NULL);
469 
470              r_data[n_threads].request = NULL;
471              r_data[n_threads].host = host;
472              r_data[n_threads].error_response = serror_response;
473              r_data[n_threads].banner = banner;
474              r_data[n_threads].subdomain = subdomains[count];
475 
476              if (pthread_create(&threads[n_threads], NULL, &ThreadSubdomainRoutine, (void *) &r_data[n_threads]) == -1) {
477                 FATAL_ERROR("[!] Can't create thread. Quiting...\n");
478              }
479 
480              n_threads++;
481              count++;
482       }
483 
484       count = 0;
485       n_threads--;
486       if (rounds == 0) n_threads = 0;
487 
488       while (n_threads < n_total1) {
489           pthread_join(threads[n_threads],NULL);
490           n_threads++;
491       }
492 
493       time(&end2);
494     }
495 
496     time(&end);
497     printf("\n");
498     if (o_handler.S_MODE == 0 || o_handler.S_MODE == 2)
499        printf("[+] %d GET requests done, %d were successfull on %s. Leaving...\n", n_total, n, time_format(&begin1, &end1));
500 
501     if (o_handler.S_MODE == 1 || o_handler.S_MODE ==2)
502        printf("[+] %d subdomain requests done, %d were successfull on %s. Leaving...\n", n_total1, n1, time_format(&begin2, &end2));
503 
504     printf("[+] Scan took %s.\n", time_format(&begin, &end));
505     #ifdef WIN32
506     WSACleanup();
507     #endif
508     Report_Save(o_handler.O_HOST, html);
509     return 0;
510 }
511 
Usage(char * argv[])512 int Usage(char *argv[]) {
513      Rights();
514      printf("[+] Usage: %s -h host -d path -p port\n"
515             "[+] Example: %s -h www.google.com -d / -p 80 -P 216.155.15.57:3128 -e\n\n"
516             "[+] Options:\n"
517             "------------\n"
518             "\t-h: hostname. Example: www.google.com\n"
519             "\t-p: port number to connect by (80 by default).\n"
520             "\t-d: path (\"/ by default\"). Example: /web/\n"
521             "\t-e: use it for evading the responses used for not found errors.\n"
522             "\t-P: proxy server and port. Example: 216.155.15.57:3128\n"
523             "\t-r: requests file (%s by default)\n"
524             "\t-m: scanning mode. O (by default) for get requests, 1 for scanning subdomains and 2 for both of them\n"
525             "\t-s: subdomains file (%s by default)\n"
526             "\t-t: number of threads (%d by default). Must be between 0 and 1000\n"
527             "\t-u: use this option alone to check for updates.\n", argv[0], argv[0], REQUESTS_FILE, SUBDOMAINS_FILE, THREADS);
528      return 0;
529 }
530 
Rights(void)531 void Rights(void) {
532      printf("[!] NST Simple HTTP Scanner v0.4 by Paisterist - 2006/07/30\n"
533             "[!] [N]eo [S]ecurity [T]eam - http://www.neosecurityteam.net\n\n");
534 }
535 
GetBanner(char * hostname,int port,char * c_host,int c_port,struct sockaddr_in * host,int opt)536 char* GetBanner(char *hostname, int port, char *c_host, int c_port, struct sockaddr_in *host, int opt) {
537       #ifdef WIN32
538       SOCKET sock;
539       #else
540       int sock;
541       #endif
542 
543       char buffer[300];
544       char rec[RECEIVE_SIZE];
545       char *server;
546       char powered[100];
547 
548       char *p;
549 
550       int i, error;
551 
552       server = (char *) malloc(sizeof(char) * 200);
553 
554       sock = socket(AF_INET, SOCK_STREAM, 0);
555 
556       if (!sock) {
557          printf("[!] Fatal error: failed to create the socket\n");
558          return NULL;
559       }
560 
561       error=connect(sock, (const struct sockaddr*) host, sizeof(*host));
562 
563       if (error != 0) {
564          printf("[!] Fatal error: Can't connect to %s by port %d\n", c_host, c_port);
565          return (char *) NULL;
566       }
567 
568       if (opt != 0) {
569          sprintf(buffer, "OPTIONS http://%s:%d/ HTTP/1.0\r\n"
570                         "User-agent: NST Bot Scanner\r\n"
571                         "Host: %s\r\n\r\n", hostname, port, hostname);
572 
573          send(sock, buffer, strlen(buffer), 0);
574          recv(sock, rec, sizeof(rec), 0);
575 
576          if (!(p = strstr(rec, "Allow: " ))) return (char *) NULL;
577             p += 7;
578             i = 0;
579 
580             while ((int) *p != 13 && i<200) {
581                   server[i] = *p;
582                   i++;
583                   p++;
584             }
585 
586             server[i] = '\0';
587 
588             printf("[+] HTTP allowed methods: %s.\n", server);
589             Report_Add_Details(4, server, html);
590 
591             #ifdef WIN32
592             closesocket(sock);
593             #else
594             shutdown(sock, SHUT_WR);
595             close(sock);
596             #endif
597 
598             return (char *) NULL;
599       }
600 
601       sprintf(buffer,"GET http://%s:%d/ HTTP/1.1\r\n"
602                      "Connection: close\r\n"
603                      "User-agent: NST Bot Scanner\r\n"
604                      "Host: %s\r\n\r\n", hostname, port, c_host);
605 
606       send(sock, buffer, strlen(buffer), 0);
607       recv(sock, rec, sizeof(rec), 0);
608 
609       if (!(p = strstr(rec, "Server: "))) {
610          return (char *) NULL;
611       }
612 
613       p += 8;
614       i = 0;
615 
616       while ((int) *p != 13 && i<200) {
617             server[i] = *p;
618             i++;
619             p++;
620       }
621 
622       server[i]  = '\0';
623       i = 0;
624 
625       printf("[+] Server header: %s. This header can be modified manually.\n", server);
626       // ERROR EN WINDOWS CON ARGENTINA.COM
627       if (p = strstr(rec, "X-Powered-By: ")) {
628          p += 14;
629          while ((int) *p != 13 && i<100) {
630                powered[i] = *p;
631                i++;
632                p++;
633          }
634 
635          powered[i] = '\0';
636          printf("[+] X-Powered-By header found: %s\n", powered);
637          Report_Add_Details(2, powered, html);
638          memset(powered, 0x00, strlen(powered));
639          i = 0;
640       }
641 
642       if (p = strstr(rec, "X-AspNet-Version: ")) {
643          p += 18;
644          while ((int) *p != 13 && i<100) {
645                powered[i] = *p;
646                i++;
647                p++;
648          }
649 
650          powered[i] = '\0';
651          printf("[+] X-AspNet-Version header found: %s\n", powered);
652          Report_Add_Details(3, powered, html);
653       }
654 
655       #ifdef WIN32
656       closesocket(sock);
657       #else
658       shutdown(sock, SHUT_WR);
659       close(sock);
660       #endif
661       return server;
662 }
663 
Get404(char * hostname,int port,char * c_host,int c_port,struct sockaddr_in * host,char * dir)664 char* Get404(char *hostname, int port, char *c_host, int c_port, struct sockaddr_in *host, char *dir) {
665       #ifdef WIN32
666       SOCKET sock;
667       #else
668       int sock;
669       #endif
670 
671       char buffer[150];
672       char *response;
673       char rec[RECEIVE_SIZE];
674 
675       int error;
676 
677       response = (char *) malloc(sizeof(char) * 4);
678       sock = socket(AF_INET, SOCK_STREAM, 0);
679 
680       if (!sock) FATAL_ERROR("[!] Fatal error: failed to create the socket\n");
681 
682       error=connect(sock, (const struct sockaddr*) host, sizeof(*host));
683 
684       if (error != 0) {
685                 printf("[!] Fatal error: Can't connect to %s by port %d", c_host, c_port);
686                 exit(-1);
687       }
688 
689       sprintf(buffer, "HEAD http://%s:%d%s404_NotFuND2.ex HTTP/1.1\r\n"
690                       "Proxy-Connection: close\r\n"
691                       "User-Agent: NST Bot Scanner\r\n"
692                       "Host: %s\r\n\r\n", hostname, port, dir, c_host);
693 
694       send(sock, buffer, strlen(buffer), 0);
695       recv(sock, rec, sizeof(rec), 0);
696 
697       sprintf(response, "%c%c%c", rec[9], rec[10], rec[11]);
698 
699       if (strcmp(response, "404") == 0) {
700          printf("[+] Server respond normally with 404 messages for not found errors.\n");
701       }
702       else printf("[+] Server uses %s messages for not found errors. That can make the scan less precise, use -e for evading.\n", response);
703 
704       #ifdef WIN32
705       closesocket(sock);
706       #else
707       shutdown(sock, SHUT_WR);
708       close(sock);
709       #endif
710 
711       return response;
712 }
713 
Get404Subdomain(char * hostname,int port,struct sockaddr_in host,struct hostent * h)714 char* Get404Subdomain(char *hostname, int port, struct sockaddr_in host, struct hostent *h) {
715       #ifdef WIN32
716       SOCKET sock;
717       #else
718       int sock;
719       #endif
720 
721       char buffer[150];
722       char *response;
723       char *subdomain;
724       char rec[RECEIVE_SIZE];
725 
726       int error;
727 
728       response = (char *) malloc(sizeof(char) * 4);
729       subdomain = (char *) malloc((sizeof(char) * strlen(hostname)) + 20);
730       sock = socket(AF_INET, SOCK_STREAM, 0);
731 
732       sprintf(subdomain, "n0tex4sistant.%s", stripWWW(hostname));
733 
734       if (!sock) FATAL_ERROR("[!] Fatal error: failed to create the socket\n");
735       host.sin_addr.s_addr=inet_addr(subdomain);
736 
737       if ((h = gethostbyname(subdomain)) != NULL)
738          memcpy(&host.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
739 
740       error=connect(sock, (const struct sockaddr*) &host, sizeof(host));
741 
742       if (error != 0) {
743                 printf("[+] Server uses normal response for non existant subdomains.\n");
744                 return (char *) NULL;
745       }
746 
747       sprintf(buffer, "HEAD http://%s:%d HTTP/1.1\r\n"
748                       "Proxy-Connection: close\r\n"
749                       "User-Agent: NST Bot Scanner\r\n"
750                       "Host: %s:%d\r\n\r\n", subdomain, port, subdomain, port);
751 
752       send(sock, buffer, strlen(buffer), 0);
753       recv(sock, rec, sizeof(rec), 0);
754 
755       sprintf(response, "%c%c%c", rec[9], rec[10], rec[11]);
756 
757       printf("[+] Server uses %s messages for not found subdomains. That can make the scan less precise.\n", response);
758 
759       #ifdef WIN32
760       closesocket(sock);
761       #else
762       shutdown(sock, SHUT_WR);
763       close(sock);
764       #endif
765 
766       return response;
767 }
768 
CheckPort(char * hostname,int port,struct sockaddr_in * host)769 int CheckPort(char *hostname, int port, struct sockaddr_in *host) {
770       #ifdef WIN32
771       SOCKET sock;
772       #else
773       int sock;
774       #endif
775 
776       int error;
777       int FATAL=0;
778 
779       char buffer[200];
780       char rec[5];
781 
782       sock = socket(AF_INET, SOCK_STREAM, 0);
783 
784       if (!sock) {
785          printf("[!] Fatal error: failed to create the socket\n");
786          return 0;
787       }
788 
789       error=connect(sock, (const struct sockaddr*) host, sizeof(*host));
790 
791       if (error != 0) {
792          printf("[!] Fatal error: Can't connect to %s by port %d. Quiting...\n", hostname, port);
793          FATAL=1;
794       }
795 
796       sprintf(buffer, "GET / HTTP/1.0\r\n"
797                      "User-agent: NST Bot Scanner\r\n"
798                      "Host: %s\r\n\r\n", hostname);
799 
800       send(sock, buffer, strlen(buffer), 0);
801       recv(sock, rec, sizeof(rec), 0);
802 
803       if (strlen(rec) == 0 || invalidData(rec, sizeof(rec)) == -1) {
804          printf("[!] Fatal error: Can't receive data from %s by port %d. Quiting...\n", hostname, port);
805          FATAL=1;
806       }
807       #ifdef WIN32
808       closesocket(sock);
809       #else
810       shutdown(sock, SHUT_WR);
811       close(sock);
812       #endif
813 
814       if (FATAL == 1) exit(0);
815       return 0;
816 }
817 
CRLF(char * string)818 void CRLF(char *string) {
819      int i=0;
820      for (i=0; i<strlen(string); i++) if ((int) string[i] == 13 || (int) string[i] == 10 || (int) string[i] == 32 || (int) string[i] == 9) string[i]=(char) NULL;
821 }
822 
stripSlash(char * string)823 char *stripSlash(char *string) {
824      int len = strlen(string);
825      int i;
826      char *new_string = (char *) malloc(sizeof(char) * len);
827 
828      if (string[0] != '/') return (char *) NULL;
829 
830      for (i = 1; i<len; i++) {
831          new_string[i-1] = string[i];
832      }
833 
834      new_string[i-1] = '\0';
835      return new_string;
836 }
837 
time_format(time_t * begin,time_t * end)838 char* time_format(time_t *begin, time_t *end) {
839       int lapso, m, s;
840       char *format;
841 
842       format =(char *) malloc(sizeof(char) * 50);
843       lapso = *end - *begin;
844 
845       if (lapso >= 60) {
846          m = lapso / 60;
847          s = lapso % 60;
848 
849          if (s == 0) sprintf(format, "%d minutes", m);
850          else sprintf(format, "%d minutes and %d seconds", m, s);
851       }
852       else sprintf(format, "%d seconds", lapso);
853       return format;
854 }
855 
DirectoryListing(char * dir,char * rec,char * hostname,char * banner)856 int DirectoryListing(char *dir, char *rec, char *hostname, char *banner) {
857     char *serverAt;
858 
859     serverAt = (char *) malloc (sizeof(char) * (strlen(hostname) + strlen(banner) + 20));
860 
861     strcpy(serverAt, banner);
862     strcat(serverAt, " Server at ");
863     strcat(serverAt, hostname);
864     if (dir[strlen(dir) - 1] != '/' || banner == NULL) return 0;
865     if (strstr(rec, "Index of") != NULL) return 1;
866     if (strstr(rec, serverAt) != NULL) return 1;
867 
868     return 0;
869 }
870 
Report_Header(char * host,char * html)871 void Report_Header(char *host, char *html) {
872     sprintf(html, "<html>\n"
873 "<head>\n"
874 "<title>Simple HTTP Scanner - Scan report for %s</title>\n"
875 "</head>\n"
876 "<body bgcolor=\"#FFFFFF\" text=\"#000000\">\n"
877 "<table align=\"center\" width=\"100%%\" cellspacing=\"0\">\n"
878 "<tr align=\"center\" bgcolor=\"#0000FF\">\n"
879 "<td style=\"color: #FFFFFF; font-size: 20px; font-weight: bold;\" colspan=\"3\">Scan report for %s</td>\n"
880 "</tr>\n"
881 "<tr align=\"center\" bgcolor=\"#0066FF\"><td colspan=\"3\" style=\"font-weight: bold; color: #FFFFFF;\">Server details</td></tr>\n", host, host);
882 }
883 
Report_Save(char * host,char * html)884 int Report_Save(char *host, char *html) {
885      FILE *fp;
886      char *filename;
887 
888      filename = (char *) malloc(sizeof(char) * ( strlen(host) + 15 ));
889      sprintf(filename, "report-%s.html", host);
890 
891      strcat(html, "</table><br /><br />\n"
892 "<table align=\"center\">\n"
893 "<tr align=\"center\">\n"
894 "<td style=\"font-size: 12px;\">Simple HTTP Scanner v0.4 by Paisterist<br />"
895 "Neo Security Team � 2004 - 2006 || <a href=\"http://www.neosecurityteam.net\">http://www.neosecurityteam.net</a></td>\n"
896 "</tr>\n"
897 "</table>\n"
898 "</body>\n"
899 "</html>\n");
900      fp = fopen(filename, "w");
901 
902      if (!fp) {
903         printf("[+] Unknown error: the report couldn't be written. Please check the directory permissions.\n");
904         return 0;
905      }
906      fwrite(html, sizeof(char), strlen(html), fp);
907 
908      fclose(fp);
909 
910      printf("[+] Report saved successfully at %s.\n\n", filename);
911      return 0;
912 }
913 
Report_Add(char * dir,char * response,char * html,char * extra,int type,int s_type)914 int Report_Add(char *dir, char *response, char *html, char *extra, int type, int s_type) {
915     char message[200];
916     char cat[1000];
917     char color[8];
918     char url[100];
919 
920     if (COLOR == 0) {
921        COLOR = 1;
922        strcpy(color, "#CCCCCC");
923     }
924     else {
925        COLOR = 0;
926        strcpy(color, "#FFFFFF");
927     }
928 
929     switch (type) {
930            case 0: sprintf(message, "Content-Location header was detected. The source has taken from %s.", extra); break;
931            case 1: sprintf(message, "Location header was detected. The web server redirects to %s.", extra); break;
932            case 2: sprintf(message, "The web server allows you to see the content of directories without a index document. Check it out."); break;
933            case 3: sprintf(message, "The requested document requires a web based authentication, there is a restricted area."); break;
934            case 4: sprintf(message, "The requested document is forbidden. Maybe there is some confidential or sensitive information in there."); break;
935            default: sprintf(message, "Normal response received, the document exists. You should take a look."); break;
936     }
937     if (s_type == 0) sprintf(url, "%s%s", o_handler.O_PATH, stripSlash(dir));
938     else sprintf(url, "http://%s", dir);
939 
940     sprintf(cat, "<tr bgcolor=\"%s\">\n"
941 "<td>%s</td>\n"
942 "<td>%s</td>\n"
943 "<td>%s</td>\n"
944 "</tr>\n", color, url, response, message);
945 
946     strncat(html, cat, sizeof(cat));
947     return 0;
948 }
949 
Report_Add_Details(int type,char * extra,char * html)950 int Report_Add_Details(int type, char *extra, char *html) {
951     char message[200];
952     char detail[30];
953     char color[8];
954     char *ret;
955 
956     if (COLOR == 0) {
957        COLOR = 1;
958        strcpy(color, "#CCCCCC");
959     }
960     else {
961        COLOR = 0;
962        strcpy(color, "#FFFFFF");
963     }
964 
965     switch (type) {
966            case 0: {
967                 sprintf(detail, "Hostname: ");
968                 strcpy(message, extra);
969            } break;
970            case 1: {
971                 sprintf(detail, "Server information: ");
972                 strcpy(message, extra);
973            } break;
974            case 2: {
975                 sprintf(detail, "X-Powered-By: ");
976                 strcpy(message, extra);
977            } break;
978            case 3: {
979                 sprintf(detail, "X-AspNet-Version: ");
980                 strcpy(message, extra);
981            } break;
982            case 4: {
983                 sprintf(detail, "HTTP allowed methods: ");
984                 strcpy(message, extra);
985            } break;
986            case 5: {
987                 sprintf(detail, "Not found subdomain errors: ");
988                 if (extra != NULL)
989                    sprintf(message, "The web server use %s messages for not found subdomains.", extra);
990                 else
991                      strcpy(message, "The web servers respond normally to not found subdomains.");
992            } break;
993            default: {
994                     sprintf(detail, "Not found errors: ");
995                     if (strcmp(extra, "404") != 0)
996                        sprintf(message, "The web server use %s messages for not found errors. This can make the scan less precise.", extra);
997                     else
998                          sprintf(message, "The web server use %s messages for not found errors. This is normal.", extra);
999            } break;
1000     }
1001 
1002     ret = (char *) malloc(sizeof(char) * ((strlen(message) + strlen(detail)) + 100));
1003     sprintf(ret, "<tr bgcolor=\"%s\">\n"
1004 "<td width=\"150\"><b>%s</b></td>\n"
1005 "<td colspan=\"2\">%s</td>\n"
1006 "</tr>\n", color, detail, message);
1007 
1008     strcat(html, ret);
1009 
1010     return 0;
1011 }
1012 
Report_Start(char * html,int type)1013 void Report_Start(char *html, int type) {
1014      COLOR = 0;
1015      char mode[30];
1016      char cat[210];
1017      char request[10];
1018 
1019      if (type == 0) {
1020         strcpy(mode, "GET scanning");
1021         strcpy(request, "Path");
1022      }
1023      else {
1024           strcpy(mode, "Subdomain scanning");
1025           strcpy(request, "Domain");
1026      }
1027 
1028      sprintf(cat, "<tr bgcolor=\"#0066FF\" style=\"color: #FFFFFF; text-align: center;\">\n"
1029                   "<td colspan=\"3\"><b>%s</b></td>\n"
1030                   "</tr>\n"
1031                   "<tr bgcolor=\"#0099FF\" style=\"color: #FFFFFF;\">\n"
1032                   "<td><b>%s</b></td>\n"
1033                   "<td><b>Response</b></td>\n"
1034                   "<td><b>Comments</b></td>\n"
1035                   "</tr>\n", mode, request);
1036 
1037      strcat(html, cat);
1038 
1039 }
1040 
FATAL_ERROR(char * message)1041 void FATAL_ERROR(char *message) {
1042      printf("%s", message);
1043      fflush(stdout);
1044      exit(-1);
1045 }
1046 
formatProxy(char * string,int ret)1047 char* formatProxy(char *string, int ret) {
1048       char *p;
1049       char *port = (char *) malloc(sizeof(char) * 6);
1050       char *host = (char *) malloc(sizeof(char) * strlen(string));
1051       int pos, count=0;
1052 
1053       if ((p = strstr(string, ":")) == NULL) return (char *) NULL;
1054 
1055 
1056       for (pos = 0; pos < (p - string); pos++) {
1057           host[pos] = string[pos];
1058       }
1059 
1060       host[pos]='\0';
1061 
1062       p++;
1063 
1064       while (*p != '\0' && count < 5) {
1065             port[count] = *p;
1066             count++;
1067             p++;
1068       }
1069 
1070       port[count] = '\0';
1071 
1072       if (atoi(port) <= 0 || atoi(port) >= 65536) {
1073          return (char *) NULL;
1074       }
1075 
1076       return ret == 1 ? port : host;
1077 }
1078 
invalidData(char * string,int limit)1079 int invalidData(char *string, int limit) {
1080     int i, len = strlen(string);
1081 
1082     for (i = 0; i < limit; i++)
1083         if ((int) string[i] < 32) return -1;
1084 
1085     return 0;
1086 }
1087 
stripWWW(char * string)1088 char* stripWWW(char *string) {
1089       int i;
1090       char *ret = (char *) malloc(sizeof(char) * strlen(string));
1091       if (strstr(string, "www.") == string) {
1092          for (i=4; i < strlen(string); i++) {
1093              ret[i-4] = string[i];
1094          }
1095          ret[i-4]='\0';
1096          return ret;
1097       }
1098 
1099       return string;
1100 }
1101 
ThreadGETRoutine(void * r_data)1102 void *ThreadGETRoutine(void* r_data) {
1103       #ifdef WIN32
1104       SOCKET sock;
1105       #else
1106       int sock;
1107       #endif
1108 
1109       struct request_data *data;
1110 
1111       char url[URL_SIZE];
1112       char response[3];
1113       char rec[RECEIVE_SIZE];
1114       char request[REQUEST_SIZE];
1115       char *request_s;
1116       char *error_response;
1117       char *banner;
1118       char *p;
1119 
1120       int error, size, i;
1121 
1122       float div, porcentaje;
1123 
1124       data = (struct request_data *) r_data;
1125 
1126       request_s = data->request;
1127       error_response = data->error_response;
1128       banner = data->banner;
1129 
1130          sock = socket(AF_INET, SOCK_STREAM, 0);
1131 
1132          if (!sock) {
1133             printf("[!] Fatal error: failed to create the socket. Quiting...\n");
1134             n--;
1135             return 0;
1136          }
1137 
1138          error = connect(sock, (const struct sockaddr*) &data->host, sizeof(data->host));
1139 
1140          if (error != 0) {
1141             printf("[!] Unknown error: Can't connect to %s by port %d. Quiting...\n", o_handler.O_C_HOST, o_handler.O_C_PORT);
1142             n--;
1143             return 0;
1144          }
1145 
1146          sprintf(request, "GET http://%s:%d%s%s HTTP/1.0\r\n"
1147                           "Connection: Keep-Alive\r\n"
1148                           "User-Agent: NST Bot Scanner\r\n"
1149                           "Host: %s\r\n\r\n", o_handler.O_HOST, o_handler.O_PORT, o_handler.O_PATH, stripSlash(request_s), o_handler.O_C_HOST);
1150 
1151          size=sizeof(struct sockaddr);
1152 
1153          send(sock, request, sizeof(request), 0);
1154          recv(sock, rec, sizeof(rec), 0);
1155 
1156          n_requests++;
1157          div = (float) (n_requests) / n_total;
1158          porcentaje = (float) (div * 100);
1159 
1160          sprintf(response, "%c%c%c", rec[9], rec[10], rec[11]);
1161          response[3] = '\0';
1162 
1163          if (strcmp(response, error_response) != 0 || (strcmp(response, error_response) == 0 && o_handler.O_EVADING == 0)) {
1164             if (strcmp("200", response) == 0) {
1165                if (p = strstr(rec, "Content-Location: ")) {
1166                   p += 18;
1167                   i = 0;
1168                   while (*p != (int) 13 && *p != 32 && i<URL_SIZE) {
1169                      url[i] = *p;
1170                      p++;
1171                      i++;
1172                   }
1173                   url[i] = '\0';
1174 
1175                   printf("%s 200 OK. Content-Location (source of the content): %s %.2f%%\n", request_s, url, porcentaje);
1176                   Report_Add(request_s, response, html, url, 0, 0);
1177                }
1178                else if (DirectoryListing(request_s, rec, o_handler.O_HOST, banner) == 1) {
1179                     printf("%s 200 OK. Directory listing enabled... this should be unsecure... %.2f%%\n", request_s, porcentaje);
1180                     Report_Add(request_s, response, html, url, 2, 0);
1181                }
1182                else {
1183                     printf("%s 200 OK. This can be interesting... %.2f%%\n", request_s, porcentaje);
1184                     Report_Add(request_s, response, html, url, 999, 0);
1185                }
1186             }
1187             else if (strcmp("401", response) == 0) {
1188                  printf("%s 401 Unauthorized. Restricted area, check it out. %.2f%%\n", request_s, porcentaje);
1189                  Report_Add(request_s, response, html, url, 3, 0);
1190             }
1191             else if (strcmp("403", response) == 0) {
1192                  printf("%s 403 Forbidden. Some good info? %.2f%%\n", request_s, porcentaje);
1193                  Report_Add(request_s, response, html, url, 4, 0);
1194             }
1195             else {
1196                  if (p = strstr(rec, "Location: ")) {
1197                     p += 10;
1198                     i = 0;
1199 
1200                     while ((int) *p != 13 && *p != 32 && i<URL_SIZE) {
1201                           url[i] = *p;
1202                           p++;
1203                           i++;
1204                     }
1205 
1206                     url[i] = '\0';
1207 
1208                     printf("%s %s - Redirects to %s. Try it... %.2f%%\n", request_s, response, url, porcentaje);
1209                     Report_Add(request_s, response, html, url, 1, 0);
1210                  }
1211                  else
1212                  n--;
1213             }
1214          } else
1215                n--;
1216 
1217          memset(rec, 0x00, strlen(rec));
1218          memset(response, 0x00, 3);
1219          memset(request_s, 0x00, strlen(request));
1220          memset(url, 0x00, URL_SIZE);
1221          #ifdef WIN32
1222          closesocket(sock);
1223          #else
1224          shutdown(sock, SHUT_WR);
1225          close(sock);
1226          #endif
1227 }
1228 
ThreadSubdomainRoutine(void * r_data)1229 void *ThreadSubdomainRoutine(void* r_data) {
1230       #ifdef WIN32
1231       SOCKET sock;
1232       #else
1233       int sock;
1234       #endif
1235 
1236       struct request_data *data;
1237       struct hostent *h;
1238 
1239       char url[URL_SIZE];
1240       char response[3];
1241       char rec[RECEIVE_SIZE];
1242       char request[REQUEST_SIZE];
1243       char *r_subdomain;
1244       char *serror_response;
1245       char *banner;
1246       char *p;
1247       char *subdomain = (char *) malloc(sizeof(char) * 1051);
1248 
1249       int error, size, i;
1250 
1251       float div, porcentaje;
1252 
1253       data = (struct request_data *) r_data;
1254 
1255       n_subdomains++;
1256       div = (float) (n_subdomains) / n_total;
1257       porcentaje = (float) (div * 100);
1258 
1259       r_subdomain = data->subdomain;
1260       serror_response = data->error_response;
1261       banner = data->banner;
1262 
1263       strcpy(subdomain, r_subdomain);
1264       strcat(subdomain, ".");
1265       strcat(subdomain, o_handler.O_HOST);
1266 
1267       if (serror_response == NULL) {
1268          serror_response = (char *) malloc(sizeof(char) * 4); // This way strcmp() don't crash
1269       }
1270 
1271       if (strcmp(o_handler.O_C_HOST, o_handler.O_PROXY_HOST) != 0) {
1272          strcpy(o_handler.O_C_HOST, subdomain);
1273          data->host.sin_addr.s_addr=inet_addr(o_handler.O_C_HOST);
1274 
1275          if ((h = gethostbyname(o_handler.O_C_HOST)) != NULL)
1276             memcpy(&data->host.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
1277       }
1278 
1279       sock = socket(AF_INET, SOCK_STREAM, 0);
1280 
1281       if (!sock) {
1282          printf("[!] Fatal error: failed to create the socket. Quiting...\n");
1283          n1--;
1284          return NULL;
1285       }
1286 
1287       error=connect(sock, (const struct sockaddr*) &data->host, sizeof(data->host));
1288 
1289       if (error == 0 && h != NULL) {
1290          sprintf(request, "GET http://%s/ HTTP/1.0\r\n"
1291                           "Connection: Keep-Alive\r\n"
1292                           "User-Agent: NST Bot Scanner\r\n"
1293                           "Host: %s\r\n\r\n", subdomain, o_handler.O_C_HOST);
1294 
1295          size=sizeof(struct sockaddr);
1296 
1297          send(sock, request, sizeof(request), 0);
1298          recv(sock, rec, sizeof(rec), 0);
1299 
1300          sprintf(response, "%c%c%c", rec[9], rec[10], rec[11]);
1301 
1302          if (strcmp(response, serror_response) != 0 || (strcmp(response, serror_response) == 0 && o_handler.O_EVADING == 0)) {
1303          if (strcmp("200", response) == 0) {
1304             if (p = strstr(rec, "Content-Location: ")) {
1305                p += 18;
1306                i = 0;
1307                while (*p != (int) 13 && i<URL_SIZE) {
1308                      url[i] = *p;
1309                      p++;
1310                      i++;
1311                }
1312                url[i]='\0';
1313 
1314                printf("http://%s/ 200 OK. Content-Location (source of the content): %s %.2f%%\n", subdomain, url, porcentaje);
1315                Report_Add(subdomain, response, html, url, 0, 1);
1316             }
1317             else if (DirectoryListing(subdomain, rec, o_handler.O_HOST, banner) == 1) {
1318                     printf("http://%s/ 200 OK. Directory listing enabled... this should be unsecure... %.2f%%\n", subdomain, porcentaje);
1319                     Report_Add(subdomain, response, html, url, 2, 1);
1320             }
1321             else {
1322                  printf("http://%s/ 200 OK. This can be interesting... %.2f%%\n", subdomain, porcentaje, n_subdomains);
1323                  Report_Add(subdomain, response, html, url, 999, 1);
1324             }
1325          }
1326          else if (strcmp("401", response) == 0) {
1327               printf("http://%s/ 401 Unauthorized. Restricted area, check it out. %.2f%%\n", subdomain, porcentaje);
1328               Report_Add(subdomain, response, html, url, 3, 1);
1329          }
1330          else if (strcmp("403", response) == 0) {
1331               printf("http://%s/ 403 Forbidden. Some good info? %.2f%%\n", subdomain, porcentaje);
1332               Report_Add(subdomain, response, html, url, 4, 1);
1333          }
1334          else {
1335               if (p = strstr(rec, "Location: ")) {
1336               p += 10;
1337               i = 0;
1338               while ((int) *p != 13 && i<URL_SIZE) {
1339                     url[i] = *p;
1340                     p++;
1341                     i++;
1342               }
1343               url[i]='\0';
1344 
1345               printf("http://%s/ %s - Redirects to %s. Try it... %.2f%%\n", subdomain, response, url, porcentaje);
1346               Report_Add(subdomain, response, html, url, 1, 1);
1347          }
1348          else
1349              n1--;
1350          }
1351     } //else
1352           //n_subdomains++;
1353 
1354          free(subdomain);
1355 
1356          #ifdef WIN32
1357          closesocket(sock);
1358          #else
1359          shutdown(sock, SHUT_WR);
1360          close(sock);
1361          #endif
1362          } else n1--;
1363 }
1364 
CheckUpdate()1365 int CheckUpdate() {
1366      #ifdef WIN32
1367      SOCKET sock;
1368      #else
1369      int sock;
1370      #endif
1371 
1372      int error, i=0, pos, t_count = 0;
1373 
1374      char buffer[500];
1375      char rec[1000];
1376      char *update;
1377      char response[4];
1378      char *version, *date, *url, *p, *p1;
1379 
1380      struct sockaddr_in host;
1381      struct hostent *h;
1382 
1383      if ((h = gethostbyname("shttpscanner.sourceforge.net")) == NULL) {
1384             printf("[!] Can't retrieve the updates: shttpscanner.sourceforge.net unrecognized host\n");
1385             return -1;
1386      }
1387 
1388      sock = socket(AF_INET, SOCK_STREAM, 0);
1389 
1390      if (!sock) {
1391         printf("[!] Can't create socket for retrieving updates.\n");
1392         return -1;
1393      }
1394 
1395      host.sin_family=AF_INET;
1396      host.sin_port=htons(80);
1397      host.sin_addr.s_addr=inet_addr("shttpscanner.sourceforge.net");
1398 
1399      memcpy(&host.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
1400 
1401      error = connect(sock, (const struct sockaddr*) &host, sizeof(struct sockaddr));
1402 
1403      if (error != 0) {
1404             printf("[!] Can't connect to shttpscanner.sourceforge.net by port 80 for retrieving updates.\n", o_handler.O_C_HOST, o_handler.O_C_PORT);
1405             return -1;
1406      }
1407 
1408      strcpy(buffer, "GET /updates.csv HTTP/1.1\r\n"
1409                     "User-agent: NST Bot Updater\r\n"
1410                     "Host: shttpscanner.sourceforge.net\r\n\r\n");
1411 
1412      send(sock, buffer, strlen(buffer), 0);
1413      recv(sock, rec, sizeof(rec), 0);
1414 
1415      sprintf(response, "%c%c%c", rec[9], rec[10], rec[11]);
1416 
1417      if (strcmp(response, "200") != 0) {
1418         printf("[!] Can't find updates.csv on shttpscanner.sourceforge.net\n");
1419         return -1;
1420      }
1421 
1422      i = strlen(rec);
1423 
1424      while (i >= 0) {
1425          if ((int) rec[i] == 10) {
1426             if (t_count == 0) t_count++;
1427             else {
1428                  pos = i + 1;
1429                  i = 0;
1430             }
1431          }
1432 
1433          i--;
1434      }
1435 
1436      update = (char *) malloc(sizeof(char) * (strlen(rec) - pos) + 3);
1437 
1438      //printf("%d", (strlen(rec) - pos));
1439      for (i = 0; rec[pos + i] != (char) NULL && (int) rec[pos + i] != 10; i++) update[i] = rec[pos + i];
1440      update[i] = '\0';
1441 
1442      p = strstr(update, ",");
1443      i = 0;
1444 
1445      version = (char *) malloc((sizeof(char) * (p - update)) + 10);
1446 
1447      while (i < (p - update)) {
1448            version[i] = update[i];
1449            i++;
1450      }
1451      version[i] = '\0';
1452      p++;
1453      i = 0;
1454      p1 = strstr(p, ",");
1455 
1456      date = (char *) malloc((sizeof(char) * (p1 - p)) + 10);
1457 
1458      while (i < (p1 - p)) {
1459            date[i] = update[i + (p - update)];
1460            i++;
1461      }
1462      date[i] = '\0';
1463 
1464      p1++;
1465 
1466      url = (char *) malloc((sizeof(char) * (strlen(update) - (p1 - update))) + 10);
1467      i = 0;
1468 
1469      while ((int) *p1 != 0 && (int) *p1 != 10) {
1470            url[i] = *p1;
1471            i++;
1472            p1++;
1473      }
1474 
1475      url[i] = '\0';
1476 
1477      if (atof(version) > CURRENT_VERSION)
1478         printf("[+] The %s version was released on %s. You can download it on %s.\n", version, date, url);
1479      else
1480           printf("[+] There isn't a new version of NST Simple HTTP Scanner available.\n");
1481 
1482      #ifdef WIN32
1483      closesocket(sock);
1484      #else
1485      shutdown(sock, SHUT_WR);
1486      close(sock);
1487      #endif
1488 
1489      return 0;
1490 }
1491