1 /****************************************************************************/
  2 /*   Creeper - a simple Syn Scanner                                         */
  3 /*   minimalistic port scanner for educational purposes                     */        
  4 /*   Copyright (C) 2007 ithilgore - ithilgore.ryu.L@gmail.com               */
  5 /*                                                                          */
  6 /*   This program is free software: you can redistribute it and/or modify   */
  7 /*   it under the terms of the GNU General Public License as published by   */
  8 /*   the Free Software Foundation, either version 3 of the License, or      */
  9 /*   (at your option) any later version.                                    */
 10 /*                                                                          */
 11 /*   This program is distributed in the hope that it will be useful,        */
 12 /*   but WITHOUT ANY WARRANTY; without even the implied warranty of         */
 13 /*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
 14 /*   GNU General Public License for more details.                           */
 15 /*                                                                          */
 16 /*   You should have received a copy of the GNU General Public License      */
 17 /*   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 18 /*                                                                          */
 19 /****************************************************************************/
 20
 21 /****************************************************************************/
 22 /*            Creeper                                                       */
 23 /*           version 1.2                                                    */
 24 /*          by ithilgore                                                    */
 25 /*       ithilgore.ryu.L@gmail.com                                          */
 26 /*                                                                          */
 27 /* compile with: gcc creeper.c -lpcap -o creeper                            */
 28 /* some compilers may also need -fpack-struct                               */
 29 /*                                                                          */
 30 /* Use of this code is for educational purposes only. I am not responsible  */
 31 /* for any illegal or criminal activities performed with this tool or       */
 32 /* any modifications of it.                                                 */
 33 /* This tool is free and open software. This means you can do anything you  */
 34 /* like with it with your own responsibility and with no warranty from me.  */
 35 /* to the source.                                                           */
 36 /*                                                                          */                      
 37 /* This tool has been tested so far and works sucessfully in:               */
 38 /* ----Slackware 11 with kernel 2.2.4.33                                    */
 39 /* ----Arch Linux (Core Dump) kernel 2.6.23                                 */
 40 /****************************************************************************/
 41
 42
 43 #include <stdio.h>
 44 #include <stdlib.h>
 45 #include <string.h>
 46 #include <errno.h>
 47 #include <netdb.h>
 48 #include <arpa/inet.h>
 49 #include <sys/types.h>
 50 #include <sys/socket.h>
 51 #include <unistd.h>
 52 #include <pcap.h>
 53 #include <signal.h>
 54
 55 #define BUFSIZE 65535 //maximum size of any datagram(16 bits the size of identifier)
 56 #define TRUE 1
 57 #define FALSE 0
 58 #define default_low  1
 59 #define default_high 1024
 60
 61
 62 /* change the timeout at will
 63  * it defines how long the scanner will wait for
 64  * an answer from the scanned host
 65  * careful though - testing shows < 4 is bad
 66  * it is just another factor between speed and accuracy
 67  */
 68 #define DEFAULT_S_TIMEOUT 5
 69
 70
 71 /* default snap length (maximum bytes per packet to capture) */
 72 #define SNAP_LEN 1518
 73
 74 /* ethernet headers are always exactly 14 bytes */
 75 #define SIZE_ETHERNET 14
 76
 77 /* Ethernet addresses are 6 bytes */
 78 #define ETHER_ADDR_LEN 6
 79
 80 /* USING TCPDUMP-like header structs */
 81
 82 /* Ethernet header */
 83 struct sniff_ethernet {
 84         u_char  ether_dhost[ETHER_ADDR_LEN];    /* destination host address */
 85         u_char  ether_shost[ETHER_ADDR_LEN];    /* source host address */
 86         u_short ether_type;                     /* IP? ARP? RARP? etc */
 87 };
 88
 89 /* IP header */
 90 struct sniff_ip {
 91         u_char  ip_vhl;                 /* version << 4 | header length >> 2 */
 92         u_char  ip_tos;                 /* type of service */
 93         u_short ip_len;                 /* total length */
 94         u_short ip_id;                  /* identification */
 95         u_short ip_off;                 /* fragment offset field */
 96         #define IP_RF 0x8000            /* reserved fragment flag */
 97         #define IP_DF 0x4000            /* dont fragment flag */
 98         #define IP_MF 0x2000            /* more fragments flag */
 99         #define IP_OFFMASK 0x1fff       /* mask for fragmenting bits */
100         u_char  ip_ttl;                 /* time to live */
101         u_char  ip_p;                   /* protocol */
102         u_short ip_sum;                 /* checksum */
103         struct  in_addr ip_src,ip_dst;  /* source and dest address */
104 };
105 #define IP_HL(ip)               (((ip)->ip_vhl) & 0x0f)
106 #define IP_V(ip)                (((ip)->ip_vhl) >> 4)
107
108 /* TCP header */
109 typedef u_int tcp_seq;
110
111 struct sniff_tcp {
112         u_short th_sport;               /* source port */
113         u_short th_dport;               /* destination port */
114         tcp_seq th_seq;                 /* sequence number */
115         tcp_seq th_ack;                 /* acknowledgement number */
116         u_char  th_offx2;               /* data offset, rsvd */
117 #define TH_OFF(th)      (((th)->th_offx2 & 0xf0) >> 4)
118         u_char  th_flags;
119         #define TH_FIN  0x01
120         #define TH_SYN  0x02
121         #define TH_RST  0x04
122         #define TH_PUSH 0x08
123         #define TH_ACK  0x10
124         #define TH_URG  0x20
125         #define TH_ECE  0x40
126         #define TH_CWR  0x80
127         #define TH_FLAGS        (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
128         u_short th_win;                 /* window */
129         u_short th_sum;                 /* checksum */
130         u_short th_urp;                 /* urgent pointer */
131 };
132
133 /* pseudo header used for tcp checksuming
134  * a not so well documented fact ... in public
135 */
136
137 struct pseudo_hdr {
138         u_int32_t src;
139         u_int32_t dst;
140         u_char mbz;
141         u_char proto;
142         u_int16_t len;
143 };
144
145 /* Global Variables */
146 int verbose_mode;
147 int stealth_mode;        /* Syn Scanning */
148 int s_timeout;           /* timeout seconds for Syn Scanning */
149 long int low_port = default_low;
150 long int high_port = default_high;
151 char *ipArg = NULL;
152 pcap_t *session;
153
154
155 /* Function Prototypes */
156
157 void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
158 void print_usage(const char *argv);
159 int check_Port(long *lport, long *hport, char *optar);
160 uint16_t checksum_comp(uint16_t *addr, int len);
161 pcap_t* EnginePreparing(char *vicIP, struct sockaddr_in **ipP, pcap_t *session);
162 struct hostent* host_resolve(void);
163 void Syn_Scanning(void);
164 void Connect_Scanning(void);
165 void sigfunc(int);
166
167 /* Function Prototypes end*/
168
169 /********************************MAIN PROGRAM********************************/
170
171
172
173 int main(int argc, char *argv[]) {
174
175         if ( argc == 1 ) {
176                 print_usage( argv[0] );
177                 exit(0);
178         }
179
180         int opt;
181         while ( (opt = getopt(argc , argv , "h:vp:S") ) != -1 ) {
182                 switch (opt)
183                 {
184                         case 'h':
185                                 ipArg = optarg;
186                                 break;
187                         case 'v':
188                                 verbose_mode = TRUE;
189                                 break;
190                         case 'p':
191                                 check_Port (&low_port, &high_port, optarg);
192                                 break;
193                         case 'S':
194                                 stealth_mode = TRUE;
195                                 break;
196                         case '?':
197                                 fprintf (stderr, "option inconsistency : -%c \n"
198                                         "see usage(no arguments)\n", optopt);
199                                 exit(EXIT_FAILURE);
200                 }
201         }
202
203         if (ipArg == NULL){
204                 fprintf(stderr, "No host given-see usage(no arguments)\n" );
205                 exit(EXIT_FAILURE);
206         }
207
208         if (!stealth_mode) {
209                 Connect_Scanning();
210         }
211         else {
212                 if (getuid() && geteuid()) {
213                         fprintf(stderr, "Need to be root to initiate Syn Scanning\n");
214                         exit(EXIT_FAILURE);
215                 }
216                 Syn_Scanning();
217         }
218         exit(EXIT_SUCCESS);
219         
220 }
221
222
223 void print_usage(const char *argv) {
224         fprintf(stdout,
225         "Port Scanner by ithilgore\n"
226         "usage: %s -h Host [OPTIONS]\n"
227         "Host -> IP or Name\n"
228         "OPTIONS include:\n"
229         "-v : verbose mode\n"
230         "-p : port range (eg. -p23 , -p0-1024)\n"
231         "-S : stealth mode on ( syn scanning )\n"
232         "more options to be included\n\n"
233         , argv);
234 }
235
236
237
238
239 int check_Port (long *lport, long *hport, char *optar) {
240
241         char *s1 = optar ;       //point to the char after 'p'
242         errno = 0;
243         *lport = strtol(s1, (char **)NULL, 10);
244  
245         if (errno != 0) {
246                 perror ("Port number problem \n");
247                 exit(0);
248         }
249
250         if (!(s1 = index(s1, '-'))) { //if no port range specified (no other '-' found)
251                 *hport = *lport;
252                 return 0;
253         } else {
254                 *hport = strtol(++s1, NULL, 10) ;
255                 if (errno != 0) {
256                         perror("Port number problem \n");
257                         exit(0);
258                 }
259                 if (low_port > high_port) {
260                         fprintf(stdout, "low_port is higher than high_port: swapping...\n");
261                         *lport ^= *hport;
262                         *hport ^= *lport;
263                         *lport ^= *hport;
264                 }
265         }
266
267 }
268
269
270 struct hostent* host_resolve(void) {
271         struct hostent *hostname;
272         extern char * ipArg;
273
274         if (!(hostname = gethostbyname(ipArg))) {
275                 fprintf (stderr, "Host name resolution failed for %s \n"
276                         "Try using the nslookup prog to find the IP address\n", ipArg);
277                 exit(EXIT_FAILURE);
278         }
279
280         if (verbose_mode) {
281                 fprintf(stdout, "Host Resolution results:\n"
282                                 "Name: %s\n"
283                                 "Aliases:", hostname->h_name);
284                 char **alias = hostname->h_aliases;
285                 while(*alias) {
286                         fprintf(stdout, "%s ", *alias);
287                         alias++;
288                 }      
289                 char **addrs = hostname->h_addr_list;
290                 fprintf(stdout, "\nIP address/es:\n");
291                 while(*addrs) {
292                         fprintf(stdout, " %s ", inet_ntoa(*(struct in_addr *)*addrs));
293                         addrs++;
294                 }
295                 printf("\n");
296         }
297         return hostname;
298
299 }
300
301
302 void Connect_Scanning(void) {
303
304         int sockfd;
305         char temp_addr[7];
306
307         struct sockaddr_in sockaddr;
308         struct servent *serv;
309         struct hostent * hostname;
310         hostname = (struct hostent *)host_resolve();
311
312         char **addr = hostname->h_addr_list;
313
314         /* transfer of dotted-decimal IP of first IP from resolving */
315
316         strcpy (temp_addr, inet_ntoa(*(struct in_addr *)*addr));
317
318         fprintf(stdout, "Initiating Connect() Scan against %s [%ld ports] \n",
319                         temp_addr,
320                         (high_port-low_port+1));
321
322         int i = 0;
323         for (i = low_port; i <= high_port; i++) {
324
325                 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
326                         perror("Socket error");
327                         exit(EXIT_FAILURE);
328                 }
329                 sockaddr.sin_family = AF_INET;
330                 sockaddr.sin_port = htons(i);
331                 inet_pton(AF_INET, temp_addr, &sockaddr.sin_addr);
332
333                 if (!connect(sockfd, (struct sockaddr*)& sockaddr, sizeof(sockaddr))) {
334                         serv = getservbyport(htons(i), "tcp");
335                         fprintf(stdout, "TCP port %d open , possible service: %s\n", i, serv->s_name);
336                 }
337
338                 close(sockfd);
339         }
340         fprintf(stdout, "Connect Scanning completed\n");
341 }
342
343
344 void sigfunc(int signum) {       /* signal handler */
345
346         pcap_breakloop(session);
347
348 }
349
350
351 void Syn_Scanning(void) {
352
353         s_timeout = DEFAULT_S_TIMEOUT;   /* global var for timeout */
354         int sockfd;
355         int timeout = 0;                 /* check if timeout with return from dispatch */
356         char temp_addr[16];
357
358         struct sockaddr_in sin;
359         struct servent *serv;
360         struct hostent *hostname;
361         struct sockaddr_in *ipP;        /* local ip storage */
362
363         hostname = (struct hostent *)host_resolve();
364
365         char **addr = hostname->h_addr_list;
366         strncpy(temp_addr, inet_ntoa(*(struct in_addr *)*addr), 16);
367
368         char datagram[4096];  // buffer for datagrams
369         struct sniff_ip *iph = (struct sniff_ip *)datagram;
370         /* tcp header begins right after the end of the ip header */ 
371         /* can it work in reverse ? Of course not */
372         struct sniff_tcp *tcph = (struct sniff_tcp *)(datagram + sizeof(struct sniff_ip));
373
374         struct sigaction act;
375         act.sa_handler = sigfunc;
376         sigemptyset(&act.sa_mask);
377         act.sa_flags = 0;               /* read man of libpcap -> SA_RESTART MUST BE OFF */
378
379         /* Prepare the Sniffing Engine */
380         session = (pcap_t *)EnginePreparing(temp_addr, &ipP, session);
381
382
383         fprintf(stdout, "Initiating Syn Scanning against %s [%ld ports] \n", temp_addr, (high_port-low_port+1));
384         int i = 0;
385         for (i = low_port; i <= high_port; i++) {
386
387                 if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) {
388                         perror("sock:");
389                         exit(EXIT_FAILURE);
390                 }
391                 
392                 sin.sin_family = AF_INET;
393
394                 inet_pton(AF_INET, temp_addr, &sin.sin_addr);
395
396                 memset(datagram, 0, 4096);                  /* zero out the buffer */
397                 iph->ip_vhl = 0x45;                          /* version=4,header_length=5 (no data) */
398                 iph->ip_tos = 0;                             /* type of service -not needed */
399                 iph->ip_len = sizeof (struct sniff_ip) + sizeof (struct sniff_tcp);    /* no payload */
400                 iph->ip_id = htonl(54321);                   /* simple id */
401                 iph->ip_off = 0;                             /* no fragmentation */
402                 iph->ip_ttl = 255;                           /* time to live - set max value */
403                 iph->ip_p = IPPROTO_TCP;                     /* 6 as a value - see /etc/protocols/ */
404                 iph->ip_src.s_addr = ipP->sin_addr.s_addr;   /*local device IP */
405                 iph->ip_dst.s_addr = sin.sin_addr.s_addr;    /* dest addr */
406                 iph->ip_sum =                                /* no need for ip sum actually */
407                 checksum_comp( (unsigned short *)iph,
408                                 sizeof(struct sniff_ip));
409
410                 tcph->th_sport = htons(1234);                /* arbitrary port */
411                 tcph->th_dport = htons(i);                   /* scanned dest port */
412                 tcph->th_seq = random();                     /* the random SYN sequence */
413                 tcph->th_ack = 0;                            /* no ACK needed */
414                 tcph->th_offx2 = 0x50;                       /* 50h (5 offset) ( 8 0s reserverd )*/
415                 tcph->th_flags = TH_SYN;                     /* initial connection request */
416                 tcph->th_win = (65535);                      /* maximum allowed window size */
417                 tcph->th_sum = 0;                            /* will compute later */
418                 tcph->th_urp = 0;                            /* no urgent pointer */
419
420                 /* pseudo header for tcp checksum */
421                 struct pseudo_hdr *phdr = (struct pseudo_hdr *) (datagram +
422                                 sizeof(struct sniff_ip) + sizeof(struct sniff_tcp));
423                 phdr->src = iph->ip_src.s_addr;
424                 phdr->dst = iph->ip_dst.s_addr;
425                 phdr->mbz = 0;
426                 phdr->proto = IPPROTO_TCP;
427                 phdr->len = ntohs(0x14);       /* in bytes the tcp segment length */
428                 /*- WhyTF is it network byte saved by default ????*/
429
430
431                 tcph->th_sum = htons(checksum_comp((unsigned short *)tcph,
432                                         sizeof(struct pseudo_hdr)+
433                                         sizeof(struct sniff_tcp)));
434
435                 int one = 1;
436                 const int *val = &one;
437                 if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
438                         fprintf(stderr, "Warning: Cannot set HDRINCL for port %d\n",i);
439                 
440
441                 if (sendto(sockfd, datagram, iph->ip_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
442                         fprintf(stderr, "Error sending datagram for port %d\n", i);
443                         break;
444                 }
445
446                 sigaction (SIGALRM, &act, 0);
447                 alarm(s_timeout);
448
449                 // give port as argument to callback function
450                 timeout = pcap_dispatch(session, -1, got_packet, (u_char *)i);
451                 alarm(0);             /* trigger off alarm for this loop */
452
453                 if (verbose_mode && timeout == -2) {
454                         fprintf(stdout, "timeout for port %d\n", i);
455                 }
456
457         }
458
459         fprintf(stdout, "SYN Scanning completed\n");
460 }
461
462
463 uint16_t checksum_comp (uint16_t *addr, int len) {   /*  compute TCP header checksum */
464         /*  with the usual algorithm a bit changed */
465         /*  for byte ordering problem resolving */
466         /*  see RFC 1071 for more info */
467         /* Compute Internet Checksum for "count" bytes
468          *         beginning at location "addr".
469          */
470         register long sum = 0;
471         int count = len;
472         uint16_t temp;
473
474         while (count > 1)  {
475                 temp = htons(*addr++);   // in this line:added -> htons
476                 sum += temp;
477                 count -= 2;
478         }
479
480         /*  Add left-over byte, if any */
481         if(count > 0)
482                 sum += *(unsigned char *)addr;
483
484         /*  Fold 32-bit sum to 16 bits */
485         while (sum >> 16)
486                 sum = (sum & 0xffff) + (sum >> 16);
487
488         uint16_t checksum = ~sum;
489         return checksum;
490 }
491
492
493
494 pcap_t* EnginePreparing (char * vicIP, struct sockaddr_in **ipP, pcap_t *session) {
495
496         char *dev;
497         char errbuf[PCAP_ERRBUF_SIZE];
498         bpf_u_int32 devip, netmask;
499         struct pcap_pkthdr header;
500         struct bpf_program filter;             /* compiled filter */
501         char filter_exp[30] = "src host ";      /* we filter the traffic to the victim */
502         pcap_if_t *alldev;
503
504         /* yes some numbers are HARDCODED as they should be */
505         /* guess why and then try exploiting it */
506
507         strncpy((char *)filter_exp+9, vicIP, 16);
508         fprintf(stdout, "filter exp: %s \n ", filter_exp);
509
510         if ((pcap_findalldevs(&alldev, errbuf)) == -1) {
511                 fprintf (stderr, "%s\n", errbuf);
512                 exit(EXIT_FAILURE);
513         }
514
515         struct pcap_addr *address = alldev->addresses;
516         address = address->next;                /*first address is U(F)O*/
517         struct sockaddr_in * ip;
518
519         while (address) {
520                 if (address->addr) {
521                         ip = (struct sockaddr_in *) address->addr;
522                         fprintf (stdout, "Local IP: %s \n", inet_ntoa(ip->sin_addr));
523                 }
524                 address = address->next;
525         }
526
527         *ipP = (struct sockaddr_in *)alldev->addresses->next->addr;  /* local ip to be used in the raw datagram */
528         /* choose the first you find -there was some problem when choosing the last
529          * ip since the last found might be 0.0.0.0 and thus chaos would occur */
530         dev = alldev->name;
531
532         /*if ( (dev = pcap_lookupdev(errbuf)) == NULL) {
533           printf ( "%s\n" , errbuf ) ;
534           printf ( "Using default eth0 \n");
535           dev = "eth0" ;
536           }*/
537
538         if (verbose_mode) {
539                 fprintf(stdout, "Using local IP: %s \n", inet_ntoa((*ipP)->sin_addr));
540                 fprintf(stdout, "Using local Device: %s\n", dev);
541         }
542
543         if ((session = pcap_open_live (dev, BUFSIZE, 0, 0, errbuf)) == NULL) {
544                 fprintf(stderr, "Could not open device %s: error: %s \n ", dev, errbuf);
545                 exit(EXIT_FAILURE);
546         }
547
548
549         if (pcap_compile(session, &filter, filter_exp, 0, 0) == -1) {
550                 fprintf(stderr, "Couldn't parse filter %s: %s \n ", filter_exp, pcap_geterr(session));
551                 exit(EXIT_FAILURE);
552         }
553
554         if (pcap_setfilter(session, &filter) == -1) {
555                 fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(session));
556                 exit(EXIT_FAILURE);
557         }
558
559         return session;
560 }
561
562
563
564
565 void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
566
567         const struct sniff_tcp *tcp;
568         const struct sniff_ip *ip;
569         const struct sniff_ethernet *ether;
570         struct servent *serv;
571
572         int size_ip;
573         int size_tcp;
574
575         ether = (struct sniff_ethernet*) (packet);
576         ip = (struct sniff_ip *) (packet + SIZE_ETHERNET);
577
578         size_ip = IP_HL(ip)*4;
579         if (size_ip < 20) {
580                 fprintf (stderr, "Invalid IP header length: %u bytes \n", size_ip);
581                 return;
582         }
583
584         if (ip->ip_p != IPPROTO_TCP) {
585                 fprintf (stderr, "Returned Packet is not TCP protocol \n");
586                 return;
587         }
588
589         tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
590         size_tcp = TH_OFF(tcp)*4;
591         if (size_tcp < 20) {
592                 fprintf (stderr, " * Invalid TCP header length: %u bytes\n", size_tcp);
593                 return;
594         }
595
596
597         /* the actual SYN scanning (heh) : we examine if the SYN flag is on at the receiving packet(port open) */
598
599         if (((tcp->th_flags & 0x02) == TH_SYN) && (tcp->th_flags & 0x10) == TH_ACK) {
600                 serv = getservbyport ( htons((int)args), "tcp" );
601                 fprintf (stdout, "TCP port %d open , possible service: %s\n", args, serv->s_name);
602                 // RST is sent by kernel automatically
603         }
604         else if ((tcp->th_flags & 0x04 ) == TH_RST && verbose_mode) {
605                 //fprintf (stdout, "TCP port %d closed\n", args ); too much info on screen
606
607         }
608         else if (verbose_mode) {
609                 //fprintf (stdout, "Port %d state unknown/filtered \n", args);
610         }
611 }
612
613