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