/* Atanas Dimitrov Homework #5 CS6900 Due: 09/24/04 */ #include #include #include #include #include #include #include #include #ifndef __USE_BSD #define __USE_BSD #endif #include #ifndef __FAVOR_BSD #define __FAVOR_BSD #endif #include #include #include #ifndef KERNEL #define KERNEL #endif #ifndef __APPLE_API_PRIVATE #define __APPLE_API_PRIVATE #endif #include #include #include #include #include #include #include #include #include #include //interface to sniff #define INTERFACE "en0" /* sniffing function returns sequence number in the sniffed packet which matches the filter */ int sniff(int fd, int sip, int dip, short sport, short dport) { int true = 1; int buflen, r; struct bpf_hdr *buf; struct ifreq ifreq; //sniffer program/code for the special device struct bpf_insn insns[] = { /* from thhis point on anything that doesn't match the src, dest, and ports will be dropped and not accounted for */ //go to byte 12 and see if this is IP BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 11), //go to byte 23 and see if this is TCP BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 23), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_TCP, 0, 9), //filter out source ip address BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 26), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, sip, 0, 7), //filter out destination ip address BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 30), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, dip, 0, 5), //filter out source port BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 34), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, sport, 0, 3), //filter out destination port BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 36), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, dport, 0, 1), //read the packet BPF_STMT(BPF_RET+BPF_K, (u_int)-1), //ignore the packet BPF_STMT(BPF_RET+BPF_K, 0), }; struct bpf_program bpf_program = { 14, (struct bpf_insn *) &insns }; struct timeval timeval; struct ip *iph; struct tcphdr *tcph; //store the interface in the required struct strcpy((char *) ifreq.ifr_name, INTERFACE); //set the interface associated with the file ioctl(fd, BIOCSETIF, &ifreq); //set the buffer length for reading from the file ioctl(fd, BIOCGBLEN, &buflen); //set to read immediately after the receipt of the packet ioctl(fd, BIOCIMMEDIATE, (u_int) &true); //set the timout for the remote response timeval.tv_sec = 1; timeval.tv_usec = 0; ioctl(fd, BIOCSRTIMEOUT, (struct timeval *) &timeval); //initialize the sniffer code to filter out traffic related to scanning ioctl(fd, BIOCSETF, (struct bpf_program *) &bpf_program); //get and store the values buf = (struct bpf_hdr *) malloc(buflen); bzero(buf, buflen); r = read(fd, buf, buflen); iph = (struct ip *) ((char *) buf + buf->bh_hdrlen + sizeof(struct ether_header)); tcph = (struct tcphdr *) ((char *) iph + sizeof(struct ip)); //return the sequence number of the captured packet if (r > 0) return ntohl(tcph->th_seq); return 0; } /* Function to send and receive packets returns open port numner or 0 if closed port, takes as a parameter port number. */ int poke(int port) { int sock, newisn, oldisn; int len, bpf; struct timeval tv1, tv2; struct timezone tz1, tz2; int i; int raw_sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP); char datagram[4096]; char cksum_tcpheader[1024]; struct ip *iph = (struct ip *) &datagram; struct tcphdr *tcph = (struct tcphdr *) &datagram+1; struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons (port); sin.sin_addr.s_addr = inet_addr ("192.168.0.2"); memset(datagram, 0x0, sizeof(datagram)); memset(cksum_tcpheader, 0, sizeof(cksum_tcpheader)); //IP header iph->ip_hl = 5; iph->ip_v = IPVERSION; iph->ip_tos = IPTOS_PREC_ROUTINE; iph->ip_len = htons(sizeof (struct ip) + sizeof (struct tcphdr)); iph->ip_id = htonl(11111); iph->ip_off = 0x0; iph->ip_ttl = MAXTTL; iph->ip_p = 6; iph->ip_sum = 0x0; iph->ip_src.s_addr = inet_addr ("192.168.10.1"); iph->ip_dst.s_addr = sin.sin_addr.s_addr; //TCP Header tcph->th_sport = htons(3491); tcph->th_dport = htons(port); tcph->th_seq = random(); tcph->th_ack = 0x0; tcph->th_x2 = 0x0; tcph->th_off = sizeof(struct tcphdr) + 1; tcph->th_flags = TH_SYN; tcph->th_win = htonl(TCP_MAXWIN); tcph->th_sum = 0x0; tcph->th_urp = 0x0; //in_cksum() compiled in /usr/lib/libBSDPClient.A.dylib on Mac OS X iph->ip_sum = in_cksum ((unsigned short *) iph, sizeof(struct ip)); //special treatment for tcp header checksum memcpy(&cksum_tcpheader, &(iph->ip_src.s_addr), 4); memcpy(&cksum_tcpheader[4], &(iph->ip_dst.s_addr), 4); cksum_tcpheader[8]=0; cksum_tcpheader[9]=(u_int16_t)iph->ip_p; cksum_tcpheader[10]=(u_int16_t) (sizeof(struct tcphdr) & 0xff00) >> 8; cksum_tcpheader[11]=(u_int16_t) (sizeof(struct tcphdr) & 0x00ff); memcpy(&cksum_tcpheader[12], tcph, sizeof(struct tcphdr)); //in_cksum() compiled in /usr/lib/libBSDPClient.A.dylib on Mac OS X tcph->th_sum = in_cksum((unsigned short *) (cksum_tcpheader), sizeof(struct tcphdr)+12); //set socket option to include the header int one = 1; const int *val = &one; setsockopt (raw_sock, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)); //open BSD Packet Filter bpf = open("/dev/bpf3", O_RDWR); //send the poking packet sendto(raw_sock, datagram, iph->ip_len, SO_KEEPALIVE, (struct sockaddr *) &sin, sizeof (const int *)); //sniff the reply newisn=sniff(bpf, ntohl(iph->ip_dst.s_addr), ntohl(iph->ip_src.s_addr), \ ntohs(tcph->th_dport), ntohs(tcph->th_sport)); //if timed out then close out and return 0 if (newisn==0) { close(raw_sock); close(bpf); return(0); } //we must close these to reuse them oldisn=newisn; close(raw_sock); close(bpf); //if the port is open then return the number return(port); } #define MAX_SCAN_PORTS 1255 /* main function */ int main() { //store the results from the sequential port scan in this array int ports[MAX_SCAN_PORTS]; int i; //clear the array for(i=0; i