diff -ruN dsniff-2.3/dnsspoof.c dsniff-2.3-cmg/dnsspoof.c --- dsniff-2.3/dnsspoof.c 2000-11-19 13:39:40.000000000 -0600 +++ dsniff-2.3-cmg/dnsspoof.c 2009-08-11 09:30:51.000000000 -0500 @@ -4,6 +4,7 @@ Forge replies to arbitrary DNS A / PTR queries on the LAN. Copyright (c) 2000 Dug Song + Modifications by Colin Grady $Id: dnsspoof.c,v 1.8 2000/11/19 19:39:40 dugsong Exp $ */ @@ -26,9 +27,18 @@ #include "pcaputil.h" #include "version.h" +#include + +#define SYSLOG_PREFIX "%DNSSPOOF" + +#define HOST_TYPE_IGNORE 0 +#define HOST_TYPE_ALERT 1 +#define HOST_TYPE_SPOOF 2 + struct dnsent { char *name; in_addr_t ip; + int type; SLIST_ENTRY(dnsent) next; }; @@ -39,14 +49,58 @@ int lnet_sock = -1; u_long lnet_ip = -1; +int log_syslog = 0; +int be_daemon = 0; +int be_quiet = 0; + void usage(void) { - fprintf(stderr, "Version: " VERSION "\n" - "Usage: dnsspoof [-i interface] [-f hostsfile] [expression]\n"); + fprintf(stderr, "Version: " VERSION "-cmg\n" + "Usage: dnsspoof [-Dqlh] [-i interface] [-o interface] [-f hostsfile] [expression]\n" + " -D\tRun as a daemon\n" + " -q\tDon't print to the screen\n" + " -l\tLog matches/actions to syslog\n" + " -h\tShow this syntax help\n" + " -i\tInterface to listen on (in)\n" + " -o\tInterface to send spoofs on (out)\n" + " -f\tHosts file\n"); exit(1); } +void +go_daemon(void) +{ + + pid_t fs; + + if (getppid() != 1) { + + fs = fork(); + + if (fs > 0) + exit(0); + + if(fs < 0) + errx(1, "ERROR: couldn't fork into daemon mode"); + + setsid(); + + } + + close(0); + close(1); + close(2); + + open("/dev/null", O_RDWR); + + dup(0); + dup(0); + + return; + +} + /* Pattern matching code from OpenSSH. */ int match_pattern(const char *s, const char *pattern) @@ -90,7 +144,7 @@ FILE *f; struct libnet_link_int *llif; struct dnsent *de; - char *ip, *name, buf[1024]; + char *ip, *name, *type, buf[1024]; if ((llif = libnet_open_link_interface(dev, buf)) == NULL) errx(1, "%s", buf); @@ -112,15 +166,19 @@ if (buf[0] == '#' || buf[0] == '\n') continue; - if ((ip = strtok(buf, "\t ")) == NULL || - (name = strtok(NULL, "\n\t ")) == NULL) + if ((name = strtok(buf, "\t ")) == NULL) + continue; + + if ((ip = strtok(buf, "\t ")) == NULL) + continue; + + if ((type = strtok(buf, "\t\n ")) == NULL) continue; if ((de = malloc(sizeof(*de))) == NULL) err(1, "malloc"); - - if ((de->ip = inet_addr(ip)) == INADDR_ANY || - (de->name = strdup(name)) == NULL) + + if ((de->ip = inet_addr(ip)) == INADDR_ANY || (de->type = atoi(type)) == 0 || (de->name = strdup(name)) == NULL) errx(1, "invalid entry"); SLIST_INSERT_HEAD (&dns_entries, de, next); @@ -132,12 +190,55 @@ err(1, "malloc"); de->ip = htonl(lnet_ip); + de->type = HOST_TYPE_ALERT; de->name = "*"; SLIST_INSERT_HEAD (&dns_entries, de, next); } } +static int +type_lookup_a(const char *name) +{ + struct dnsent *de; + + SLIST_FOREACH(de, &dns_entries, next) { + if (match_pattern(name, de->name)) + return(de->type); + } + + return(HOST_TYPE_IGNORE); +} + +static int +type_lookup_ptr(const char *name) +{ + struct dnsent *de; + int a0, a1, a2, a3; + in_addr_t dst; + char *a; + + if (strchr(name, '%') != NULL) + return(HOST_TYPE_IGNORE); + + if (sscanf(name, "%d.%d.%d.%d.", &a3, &a2, &a1, &a0) != 4) + return(HOST_TYPE_IGNORE); + + a = (char *)&dst; + + a[0] = a0 & 0xff; + a[1] = a1 & 0xff; + a[2] = a2 & 0xff; + a[3] = a3 & 0xff; + + SLIST_FOREACH(de, &dns_entries, next) { + if (de->ip == dst && strchr(de->name, '*') == NULL) + return(de->type); + } + + return(HOST_TYPE_IGNORE); +} + in_addr_t dns_lookup_a(const char *name) { @@ -186,6 +287,7 @@ int i, anslen, dnslen; in_addr_t dst; u_short type, class; + int hosttype = HOST_TYPE_IGNORE; ip = (struct libnet_ip_hdr *)(pkt + pcap_off); udp = (struct libnet_udp_hdr *)(pkt + pcap_off + (ip->ip_hl * 4)); @@ -215,6 +317,7 @@ if (type == T_A) { if ((dst = dns_lookup_a(name)) == -1) return; + hosttype = type_lookup_a(name); /* XXX - cheat on alignment. */ memcpy(p, "\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x3c\x00\x04", 12); @@ -224,6 +327,7 @@ else if (type == T_PTR) { if ((q = dns_lookup_ptr(name)) == NULL) return; + hosttype = type_lookup_ptr(name); /* XXX - cheat on alignment. */ memcpy(p, "\xc0\x0c\x00\x0c\x00\x01\x00\x00\x00\x3c", 10); anslen = dn_comp(q, p + 12, 256, NULL, NULL); @@ -251,13 +355,31 @@ libnet_do_checksum(buf, IPPROTO_UDP, UDP_H + dnslen); - if (libnet_write_ip(lnet_sock, buf, IP_H + UDP_H + dnslen) < 0) - warn("write"); + if (hosttype == HOST_TYPE_SPOOF) { + if (libnet_write_ip(lnet_sock, buf, IP_H + UDP_H + dnslen) < 0) + warn("write"); + } + + if (!be_quiet) { + if (hosttype == HOST_TYPE_SPOOF || hosttype == HOST_TYPE_ALERT) { + + fprintf(stdout, "%s: %s:%d > %s:%d (id %d, type %s) %s\n", + hosttype == HOST_TYPE_SPOOF ? "SPOOF" : "ALERT", + libnet_host_lookup(ip->ip_src.s_addr, 0), ntohs(udp->uh_sport), + libnet_host_lookup(ip->ip_dst.s_addr, 0), ntohs(udp->uh_dport), + ntohs(dns->id), type == T_A ? "A" : "PTR", name); + + } + } + + if (log_syslog) + syslog(LOG_ALERT, "%s-%s-%d: %s action for %s:%d query against %s:%d (id %d, type %s) for %s", + SYSLOG_PREFIX, hosttype == HOST_TYPE_SPOOF ? "4" : "1", hosttype, + hosttype == HOST_TYPE_SPOOF ? "Spoof" : "Alert", + libnet_host_lookup(ip->ip_src.s_addr, 0), ntohs(udp->uh_sport), + libnet_host_lookup(ip->ip_dst.s_addr, 0), ntohs(udp->uh_dport), + ntohs(dns->id), type == T_A ? "A" : "PTR", name); - fprintf(stderr, "%s.%d > %s.%d: %d+ %s? %s\n", - libnet_host_lookup(ip->ip_src.s_addr, 0), ntohs(udp->uh_sport), - libnet_host_lookup(ip->ip_dst.s_addr, 0), ntohs(udp->uh_dport), - ntohs(dns->id), type == T_A ? "A" : "PTR", name); } void @@ -271,15 +393,36 @@ int main(int argc, char *argv[]) { - char *p, *dev, *hosts, buf[1024]; + char *p, *indev, *outdev, *hosts, buf[1024]; + char errbuf[128]; + struct bpf_program fp; + bpf_u_int32 netp; + bpf_u_int32 maskp; int i; - dev = hosts = NULL; + outdev = indev = hosts = NULL; - while ((i = getopt(argc, argv, "i:f:h?")) != -1) { + while ((i = getopt(argc, argv, "Dqlh?i:o:f:")) != -1) { switch (i) { + case 'D': + be_daemon = 1; + be_quiet = 1; + break; + case 'q': + be_quiet = 1; + break; + case 'h': + case '?': + usage(); + break; + case 'l': + log_syslog = 1; + break; case 'i': - dev = optarg; + indev = optarg; + break; + case 'o': + outdev = optarg; break; case 'f': hosts = optarg; @@ -292,10 +435,16 @@ argc -= optind; argv += optind; - if (dev == NULL && (dev = pcap_lookupdev(buf)) == NULL) + if (be_daemon) + go_daemon(); + + if (indev == NULL && (indev = pcap_lookupdev(buf)) == NULL) errx(1, "%s", buf); - dns_init(dev, hosts); + if (outdev == NULL && (outdev = pcap_lookupdev(buf)) == NULL) + errx(1, "%s", buf); + + dns_init(outdev, hosts); if (argc > 0) { p = copy_argv(argv); @@ -304,8 +453,15 @@ else snprintf(buf, sizeof(buf), "udp dst port 53 and not src %s", libnet_host_lookup(lnet_ip, 0)); - if ((pcap_pd = pcap_init(dev, buf, 128)) == NULL) - errx(1, "couldn't initialize sniffing"); + pcap_pd = pcap_open_live(indev, 128, 1, 0, errbuf); + if (pcap_pd == NULL) + errx(1, "couldn't initialize sniffing: %s", errbuf); + + if (pcap_compile(pcap_pd, &fp, buf, 0, netp) == -1) + errx(1, "couldn't compile pcap"); + + if (pcap_setfilter(pcap_pd, &fp) == -1) + errx(1, "can't set the filter"); if ((pcap_off = pcap_dloff(pcap_pd)) < 0) errx(1, "couldn't determine link layer offset"); @@ -319,7 +475,7 @@ signal(SIGINT, cleanup); signal(SIGTERM, cleanup); - warnx("listening on %s [%s]", dev, buf); + warnx("listening on %s [%s]", indev, buf); pcap_loop(pcap_pd, -1, dns_spoof, NULL); diff -ruN dsniff-2.3/dnsspoof.hosts dsniff-2.3-cmg/dnsspoof.hosts --- dsniff-2.3/dnsspoof.hosts 2000-11-19 15:37:34.000000000 -0600 +++ dsniff-2.3-cmg/dnsspoof.hosts 2009-08-11 09:15:56.000000000 -0500 @@ -2,47 +2,57 @@ # # Sample hosts file for dnsspoof - kill web banner ads for Niels. :-) # -127.0.0.1 ad.* -127.0.0.1 ads*.* -127.0.0.1 adbot*.* -127.0.0.1 adcount*.* -127.0.0.1 adfinity*.* -127.0.0.1 adforce*.* -127.0.0.1 adimage*.* -127.0.0.1 adlink*.* -127.0.0.1 adserv*.* -127.0.0.1 adremote*.* -127.0.0.1 adv.* -127.0.0.1 advert*.* -127.0.0.1 banner*.* -127.0.0.1 count*.* -127.0.0.1 promo*.* -127.0.0.1 werbung*.* -127.0.0.1 *ads*.*.com -127.0.0.1 *.adbot.com -127.0.0.1 *.adone.com -127.0.0.1 *.adforce.com -127.0.0.1 *.ad-up.com -127.0.0.1 *.advert*.* -127.0.0.1 *.banner*.* -127.0.0.1 *.bfast.com -127.0.0.1 *.burstnet.com -127.0.0.1 *.doubleclick.net -127.0.0.1 *.focalink.com -127.0.0.1 *.flycast.com -127.0.0.1 *.freestats.com -127.0.0.1 *.hitbox.com -127.0.0.1 *.globaltrack.com -127.0.0.1 *.globaltrak.net -127.0.0.1 *.imagine-inc.com -127.0.0.1 *.imgis.com -127.0.0.1 *.link*.com -127.0.0.1 *.memory.net -127.0.0.1 *.preferences.com -127.0.0.1 *.smartclicks.com -127.0.0.1 *.sponsorpool.net -127.0.0.1 *.stats.net -127.0.0.1 *.stattrax.com -127.0.0.1 *.*tracker.com -127.0.0.1 *.valueclick.com -127.0.0.1 *.wisewire.com +# Three fields (single tab or space separated): +# - ipaddress +# - hostname/mask +# - action +# +# Supported Actions: +# - 0 = ignore +# - 1 = alert +# - 2 = spoof +# +127.0.0.1 ad.* 2 +127.0.0.1 ads*.* 2 +127.0.0.1 adbot*.* 2 +127.0.0.1 adcount*.* 2 +127.0.0.1 adfinity*.* 2 +127.0.0.1 adforce*.* 2 +127.0.0.1 adimage*.* 2 +127.0.0.1 adlink*.* 2 +127.0.0.1 adserv*.* 2 +127.0.0.1 adremote*.* 2 +127.0.0.1 adv.* 2 +127.0.0.1 advert*.* 2 +127.0.0.1 banner*.* 2 +127.0.0.1 count*.* 2 +127.0.0.1 promo*.* 2 +127.0.0.1 werbung*.* 2 +127.0.0.1 *ads*.*.com 2 +127.0.0.1 *.adbot.com 2 +127.0.0.1 *.adone.com 2 +127.0.0.1 *.adforce.com 2 +127.0.0.1 *.ad-up.com 2 +127.0.0.1 *.advert*.* 2 +127.0.0.1 *.banner*.* 2 +127.0.0.1 *.bfast.com 2 +127.0.0.1 *.burstnet.com 2 +127.0.0.1 *.doubleclick.net 2 +127.0.0.1 *.focalink.com 2 +127.0.0.1 *.flycast.com 2 +127.0.0.1 *.freestats.com 2 +127.0.0.1 *.hitbox.com 2 +127.0.0.1 *.globaltrack.com 2 +127.0.0.1 *.globaltrak.net 2 +127.0.0.1 *.imagine-inc.com 2 +127.0.0.1 *.imgis.com 2 +127.0.0.1 *.link*.com 2 +127.0.0.1 *.memory.net 2 +127.0.0.1 *.preferences.com 2 +127.0.0.1 *.smartclicks.com 2 +127.0.0.1 *.sponsorpool.net 2 +127.0.0.1 *.stats.net 2 +127.0.0.1 *.stattrax.com 2 +127.0.0.1 *.*tracker.com 2 +127.0.0.1 *.valueclick.com 2 +127.0.0.1 *.wisewire.com 2