/* Jackal - Stealth/FireWall scanner. With the use of halfopen ports and sending SYNC (sometimes additional flags like FIN) one can scan behind a firewall. And it shouldnt let the site feel we're scanning by not doing a 3-way-handshake we hope to avoid any tcp-logging. Credits: Halflife, Jeff (Phiji) Fay, Abdullah Marafie. Alpha Tester: Walter Kopecky. Results: Some firewalls did allow SYN | FIN to pass through. No Site has been able to log the connections though.. during alpha testing. ShadowS shadows@kuwait.net Copyleft (hack it i realy dont care). */ #include #include #include #include #include #include #include #include #include #include int timeout = 0; int counter = 0; void usage(char *name) { printf("usage:%s [-h target_ip] [-i your_ip] [-t timeout] [-s start-port] [-e end-port] [-f FIN] [-a ACK]\n",name); exit(-1); } void handler(int whateva) { alarm(0); timeout = 1; } /* Checksum Gen */ unsigned short in_cksum(unsigned short *ptr, int nbytes) { register long sum; /* assumes long == 32 bits */ u_short oddbyte; register u_short answer; /* assumes u_short == 16 bits */ /* * Our algorithm is simple, using a 32-bit accumulator (sum), * we add sequential 16-bit words to it, and at the end, fold back * all the carry bits from the top 16 bits into the lower 16 bits. */ sum = 0; while (nbytes > 1) { sum += *ptr++; nbytes -= 2; } /* mop up an odd byte, if necessary */ if (nbytes == 1) { oddbyte = 0; /* make sure top half is zero */ *((u_char *) &oddbyte) = *(u_char *)ptr; /* one byte only */ sum += oddbyte; } /* * Add back carry outs from top 16 bits to low 16 bits. */ sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* ones-complement, then truncate to 16 bits */ return(answer); } /* Generates the tcp header and packet */ struct tcphdr packetgen(int fin,int ack,unsigned int src_addr,unsigned int dst_addr, int port) { /* we create both a tcpheader and a ipheader to calculate checksum */ struct tcphdr packet; struct ipheader { unsigned int source_address; unsigned int dest_address; unsigned char placeholder; unsigned char protocol; unsigned short tcp_length; struct tcphdr tcp; } pseudo_header; counter++; /* Fill the headers with the options and data */ packet.source = getpid() + counter; packet.dest = htons(port); packet.seq = getpid() + counter; packet.ack_seq = 0; packet.res1 = 0; packet.doff = 5; packet.fin = fin; packet.syn = 1; packet.rst = 0; packet.psh = 0; packet.ack = ack; packet.urg = 0; packet.window = htons(512); packet.check = 0; packet.urg_ptr = 0; /* We need this for the checksum */ pseudo_header.source_address = src_addr; pseudo_header.dest_address = dst_addr; pseudo_header.placeholder = 0; pseudo_header.protocol = IPPROTO_TCP; pseudo_header.tcp_length = htons(20); bcopy(&packet, &pseudo_header.tcp, 20); /* Get the checksum and viowlla tcphdr is done :) */ packet.check = in_cksum((unsigned short *)&pseudo_header, 32); return packet; } int scan(struct tcphdr packet,int port,unsigned int dst_addr) { struct sockaddr_in remote; int len; /* The header we'll receive the info in */ struct rect { struct iphdr ip; struct tcphdr tcp; unsigned char blah[65535]; } recv_tcp; int sockd; /* Now we fill the sock struct */ remote.sin_family = AF_INET; remote.sin_port = htons(port); remote.sin_addr.s_addr = dst_addr; len=sizeof(remote); signal(SIGALRM, handler); sockd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); if(sockd < 0) { perror("Socket"); exit(1); } /* Blast the packet into ablivion! */ sendto(sockd, &packet, 20, 0, (struct sockaddr *)&remote, len); timeout = 0; alarm(10); while(1) { /* Now we sit and read */ read(sockd, (struct recv_tcp *)&recv_tcp, 65535); if(timeout == 1) { close(sockd); timeout=0; return -1; } if(recv_tcp.tcp.dest == (getpid() + counter)) { alarm(0); close(sockd); /* It shouldnt be 1 */ if(recv_tcp.tcp.rst == 1) return 0; else return 1; } } } main(int argc, char **argv) { int c; int start = 0; int end = 0; int fin = 0; int ack = 0; int port = 0; int retval; struct tcphdr packet; int host = 0; int target = 0; char source[100]; char destination[100]; if(getuid() != 0) { printf("Need root to run this I'm afraid .\n"); exit(-2); } if(argc < 2) usage(argv[0]); while ((c = getopt (argc, argv, "s:e:h:i:af")) != EOF) { switch (c) { case 's': start = atoi(optarg); break; case 'e': end = atoi(optarg); break; case 'a': ack = 1; break; case 'f': fin = 1; break; case 'h': strcpy(destination,optarg); target = 1; break; case 'i': strcpy(source,optarg); host = 1; break; case 't': timeout = atoi(optarg); break; default: usage(argv[0]); } } if((host == 0) || (target == 0)) usage(argv[0]); if(start == 0) port = start; if(end == 0) end = 1024; for(;port < (end + 1);port++) { packet = packetgen(fin,ack,inet_addr(source),inet_addr(destination),port); if( (retval = scan(packet,port,inet_addr(source))) == 1) printf("Port:%i is open.\n",port); } exit(0); }