/* * Forging Ping Packets by /bin/laden * PGP Key Fingerprint = 8F 46 A8 46 D5 A9 9F ED 84 50 A3 3C A8 C4 5C A8 * * Everyone always hears how easy it is to forge Ethernet packets. But * just how easy is it? It's this easy. This program will send a forged * ICMP echo request (ping) packet to any destination address making it * appear as if it came from a specifed source address. The destination * machine will respond with an ICMP echo reply to the forged source address. * A decimal/hex/ascii dump of the transmitted packet is printed to stdout. * * This program uses the Berkeley Packet Filter and has been tested on * FreeBSD, NetBSD, and OpenBSD. You will need to have the Ethernet * address of your router in the Ethernet address database (man 5 ethers). * If you are on the same segment as the target machine then specify the * target machine as your router to avoid ICMP redirects. * * Use this program to: * - Test firewalls. * - Play jokes on your friends. ("Why is fbi.gov pinging me?") * - Learn how to use the Berkeley Packet Filter. * * You may encounter problems if your router blocks packets with source * addresses that are not from your network. * * ICMP: What happens when you get caught hacking into military networks. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PKTSIZE 56 #define BUFSIZE sizeof(struct ether_header) + sizeof(struct ip) + 8 + PKTSIZE u_char data[BUFSIZE]; int resolve(const char *, u_long *); int in_cksum(u_short *, int); void dump(const u_char *, int); void usage(const char *); int main(int argc, char *argv[]) { extern char *optarg; extern int optind; struct ether_header *ehdr; struct icmp *icp; struct ifreq ifr; struct ip *iphdr; u_char *p = data; char *device = "ed0"; char *pname; char bpfdev[32]; int fd = -1; int nbytes = BUFSIZE; int n = 0; int ch; pname = argv[0]; while ((ch = getopt(argc, argv, "i:")) != EOF) { switch (ch) { case 'i': device = optarg; break; default: return (1); } } argc -= optind; argv += optind; if (argc != 3) { usage(pname); return (1); } srand(getpid()); do { sprintf(bpfdev, "/dev/bpf%d", n++); fd = open(bpfdev, O_RDWR); } while (fd < 0 && (errno == EBUSY || errno EPERM)); if (fd < 0) { perror(bpfdev); return (1); } strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, BIOCSETIF, &ifr) < 0) { perror("BIOCSETIF"); return (1); } if (ioctl(fd, BIOCGDLT, &n) < 0) { perror("BIOCGDLT"); return (1); } if (n != DLT_EN10MB) { fprintf(stderr, "%s: Unsupported data-link type\n", bpfdev); return (1); } ehdr = (struct ether_header *) p; if (ether_hostton(argv[2], ehdr->ether_dhost)) { fprintf(stderr, "%s: No hardware address\n", argv[2]); return (1); } bzero(ehdr->ether_shost, ETHER_ADDR_LEN); ehdr->ether_type = htons(ETHERTYPE_IP); p += sizeof(struct ether_header); iphdr = (struct ip *) p; iphdr->ip_v = IPVERSION; iphdr->ip_hl = sizeof(struct ip) >> 2; iphdr->ip_tos = 0; iphdr->ip_len = htons(BUFSIZE - sizeof(struct ether_header)); iphdr->ip_id = htons(rand() % 0x10000); iphdr->ip_off = 0; iphdr->ip_ttl = MAXTTL; iphdr->ip_p = IPPROTO_ICMP; iphdr->ip_sum = 0; if (resolve(argv[1], &iphdr->ip_src.s_addr)) { fprintf(stderr, "%s: Unknown host\n", argv[1]); return (1); } if (resolve(argv[0], &iphdr->ip_dst.s_addr)) { fprintf(stderr, "%s: Unknown host\n", argv[0]); return (1); } iphdr->ip_sum = in_cksum((u_short *) iphdr, sizeof(struct ip)); p += sizeof(struct ip); icp = (struct icmp *) p; icp->icmp_type = ICMP_ECHO; icp->icmp_code = 0; icp->icmp_cksum = 0; icp->icmp_id = htons(rand() % 0x10000); icp->icmp_seq = 0; p += 8; for (n = 0; n < PKTSIZE; ++n) p[n] = n; gettimeofday((struct timeval *) p, (struct timezone *) NULL); icp->icmp_cksum = in_cksum((u_short *) icp, 8 + PKTSIZE); if ((nbytes = write(fd, data, sizeof(data))) < 0) { perror("write"); return (1); } dump(data, nbytes); close(fd); return (0); } int resolve(const char *hostname, u_long * addr) { struct hostent *hp; if ((hp = gethostbyname(hostname)) == NULL) *addr = inet_addr(hostname); else bcopy(hp->h_addr, addr, sizeof(*addr)); if (*addr == INADDR_NONE) return (1); return (0); } int in_cksum(u_short * addr, int len) { register int nleft = len; register u_short *w = addr; register int sum = 0; u_short answer = 0; while (nleft > 1) { sum += *w++; nleft -= 2; } if (nleft == 1) { *(u_char *) (&answer) = *(u_char *) w; sum += answer; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); answer = ~sum; return (answer); } void dump(const u_char * p, int n) { char dec[33]; char hex[25]; char asc[9]; int i = 0; while (-n >= 0) { sprintf(hex + i * 3, "%02X ", *p); sprintf(dec + i * 4, "%3d ", *p); sprintf(asc + i, "%c", isprint(*p) ? *p : '.'); if ((++i == 8) || (n == 0)) { printf("%-32s| %-24s| %-8s\n", dec, hex, asc); i = 0; } p++; } } void usage(const char *argv0) { char *p; i f((p = strrchr(argv0, '/')) != NULL) argv0 = p + 1; fprintf(stderr, "usage: %s [-i interface] dst src router\n", argv0); }