[ipv6hackers] Finding v6 hosts by efficiently mapping ip6.arpa
Marc Heuse
mh at mh-sec.de
Sat Mar 31 20:37:28 CEST 2012
Hi folks,
I am done with the version for thc--ipv6 toolkit. as it will still take
some time until the 2.0 release, and the topic is current, attached is
the code.
highlights:
* detects wildcard DNS servers
* adapts to lossy/slow DNS server
* fast but non-flooding
* alternatively specifying the reverse domain as 2001:db8::/56
or 0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa
copy the C file into the thc-ipv6-1.x folder where the tools were
already compiled, then:
gcc -O2 -o dnsrevenum6 dnsrevenum6.c thc-ipv6-lib.o -lcrypto -lssl -lpcap
/prg/thc-ipv6 # time ./dnsrevenum6 81.169.163.39 2a01:238:42a8:e700::/48
Starting DNS reverse enumeration of 2a01:238:42a8:e700:: on server
81.169.163.39
Found: h2006391.stratoserver.net. is 2a01:238:42a8:7900:8960:d3b3:29ce:f73b
Found: spontanplan.com. is 2a01:238:42a8:a500:ea3b:e256:264d:b539
Found: mh-sec.de. is 2a01:238:42a8:e700:454:cae7:ad64:4621
Found: tumelum.de. is 2a01:238:42a8:f000:60da:a625:9507:84da
Found 4 entries.
real 0m8.493s
user 0m0.000s
sys 0m0.172s
Greets,
Marc
--
Marc Heuse
www.mh-sec.de
PGP: FEDD 5B50 C087 F8DF 5CB9 876F 7FDD E533 BF4F 891A
-------------- next part --------------
/*
* Simple and fast Reverse DNS Enumerator for IPv6
* - detects wildcard DNS servers
* - adapts to lossy/slow DNS server
* - fast but non-flooding
* - specify the reverse domain as 2001:db8::/56
* or 0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa
*
* (c) 2012 by Marc "van Hauser" Heuse <vh(at)thc.org> or <mh(at)mh-sec.de>
* The GPL 3 license applies to this code.
*
* Compile: gcc -O2 -o dnsrevenum6 dnsrevenum6.c thc-ipv6-lib.o -lcrypto -lssl -lpcap
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include "thc-ipv6.h"
// do not set below 2
#define WAITTIME_START 2
extern int debug;
int sock, len, buf_len, waittime = WAITTIME_START, wait, found = 0;
unsigned char range[33], buf_start[12], buf_end[14], buf[512], buf2[1024], name[512], dst6[16], *prg, *dst, cnt = 0;
int dnssocket(char *server) {
struct addrinfo *ai;
struct addrinfo hints;
int s;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
if (getaddrinfo(server, "53", &hints, &ai) != 0) {
fprintf(stderr, "Error: unable to resolve dns server %s!\n", server);
exit(-1);
}
if ((s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) {
fprintf(stderr, "Error: unable to resolve dns server %s!\n", server);
exit(-1);
}
if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0) {
fprintf(stderr, "Error: unable to connect to dns server %s!\n", server);
exit(-1);
}
freeaddrinfo(ai);
return s;
}
unsigned char tohex(unsigned char c) {
if (c < 10)
return (c + '0');
else
return (c + 'a' - 10);
}
unsigned char tochar(unsigned char c) {
if (c >= '0' && c <= '9')
return (c - '0');
else
return (tolower(c) - 'a' + 10);
}
void ignore(int signal) {
wait = 0;
return;
}
int send_range() {
int i;
for (i = 0; i < 32; i++) {
buf[sizeof(buf_start) + i * 2] = 1;
buf[sizeof(buf_start) + i * 2 + 1] = range[31 - i];
}
memcpy(buf + sizeof(buf_start) + 64, buf_end, sizeof(buf_end));
buf_len = sizeof(buf_start) + 64 + sizeof(buf_end);
buf[0] = 254;
buf[1] = cnt++;
if (send(sock, buf, buf_len, 0) < 0) {
fprintf(stderr, "Error: Can not send to network!\n");
exit(-1);
} else
usleep(5);
alarm(waittime + 1);
if ((len = recv(sock, buf2, sizeof(buf2), 0)) > 20) {
alarm(0);
if ((buf2[3] & 3) == 0 && buf2[7] == 1)
return 0;
else
return 1;
}
alarm(0);
return -1;
}
int deeper(int depth) {
unsigned char r[16], *ptr2;
int i, j, ok = 0, rs = 0, len, clen, nlen;
if (depth > 31)
return -1;
memset(r, 0, sizeof(r));
// generate base packet
cnt++;
buf[1] = cnt;
for (i = 0; i < depth; i++) {
buf[sizeof(buf_start) + 2 + i * 2] = 1;
buf[sizeof(buf_start) + 2 + i * 2 + 1] = range[depth - i - 1];
}
memcpy(buf + sizeof(buf_start) + 2 + depth * 2, buf_end, sizeof(buf_end));
buf_len = sizeof(buf_start) + 2 + depth * 2 + sizeof(buf_end);
// loop to finish generation and send
for (i = 0; i < 16; i ++) {
buf[0] = i;
buf[13] = tohex(i);
if (send(sock, buf, buf_len, 0) < 0) {
fprintf(stderr, "Error: can not send to network!\n");
exit(-1);
} else
usleep(5);
}
//recveive and process replies
wait = 1;
alarm(waittime);
while(ok == 0 && wait == 1) {
if ((len = recv(sock, buf2, sizeof(buf2), 0)) > 70 && buf2[1] == cnt) {
i = (buf2[0] & 15);
if ((buf2[3] & 3) == 0) {
if (depth == 31) {
r[i] = 3;
if (buf2[7] == 1) {
found++;
ptr2 = buf2 + 102;
strcpy(name, "Found: ");
while (*ptr2 != 0 && ptr2 + *ptr2 + 1 <= buf2 + len) {
clen = *ptr2;
nlen = *(ptr2 + clen + 1);
*(ptr2 + clen + 1) = 0;
strcat(name, ptr2 + 1);
strcat(name, ".");
*(ptr2 + *ptr2 + 1) = nlen;
ptr2 += clen + 1;
}
strcat(name, " is ");
ptr2 = buf2 + 12;
i = 0;
while (i < 32 && *ptr2 == 1) {
if (i % 2 == 0)
j = tochar(ptr2[1]);
else
dst6[15 - i/2] = (tochar(ptr2[1]) * 16) + j;
ptr2 += 2;
i++;
}
strcat(name, thc_ipv62notation(dst6));
if (debug) {
strcat(name, " is ");
ptr2 = buf2 + 12;
while (*ptr2 != 0 && ptr2 + *ptr2 + 1 <= buf2 + len) {
clen = *ptr2;
nlen = *(ptr2 + clen + 1);
*(ptr2 + clen + 1) = 0;
strcat(name, ptr2 + 1);
strcat(name, ".");
*(ptr2 + *ptr2 + 1) = nlen;
ptr2 += clen + 1;
}
}
printf("%s\n", name);
}
} else
r[i] = 2;
} else
r[i] = 1;
rs++;
}
if (rs == 16)
ok = 1;
}
alarm(0);
if (ok == 1) { // all packets received
for (i = 0; i < 16; i++)
if (r[i] == 2) {
range[depth] = tohex(i);
deeper(depth + 1);
}
} else { // packet loss / timeout
if (rs < 15)
waittime++;
if (rs < 11)
waittime++;
if (rs < 6)
waittime++;
if (rs < 2)
waittime++;
if ((rs == 0 && (waittime - 2 >= WAITTIME_START)) || waittime > 15) {
fprintf(stderr, "Error: DNS Server %s is not answering or not reliable enough anymore!\n", dst);
exit(-1);
}
fprintf(stderr, "Warning: packet loss, increasing response timeout to %d seconds\n", waittime);
rs = deeper(depth);
}
return rs;
}
int main(int argc, char *argv[]) {
unsigned char *ptr, *ptr2, *dest, range_start = 0;;
int i, j, k, ok;
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
prg = argv[0];
if (argc < 3) {
printf("%s %s (c) 2012 by %s %s\n\n", prg, VERSION, AUTHOR, RESOURCE);
printf("Syntax: %s dns-server ipv6address\n\n", argv[0]);
printf("Performs a fast reverse DNS enumeration and is able to cope with slow servers.\n");
printf("Examples:\n");
printf(" %s dns.test.com 2001:db8:42a8::/48\n", argv[0]);
printf(" %s dns.test.com 8.a.2.4.8.b.d.0.1.0.0.2.ip6.arpa\n", argv[0]);
exit(0);
}
if (strcmp(argv[1], "-d") == 0) {
debug = 1;
argv++;
argc--;
}
dst = argv[1];
ptr = argv[2];
srand(time(NULL) + getpid());
memset(range, 0, sizeof(range));
memset(buf, 0, sizeof(buf));
memset(buf_start, 0, sizeof(buf_start));
memset(buf_end, 0, sizeof(buf_end));
ok = 1;
if ((*ptr != '.') && (index(ptr, '.') != NULL) && ((ptr2 = (char*)strcasestr(ptr, ".ip6.arpa")) != NULL)) {
*ptr2 = 0;
for (i = strlen(ptr) - 1; i >= 0 && ok == 1; i--) {
if ((ptr[i] >= 'A' && ptr[i] <= 'F') || (ptr[i] >= 'a' && ptr[i] <= 'f') || (ptr[i] >= '0' && ptr[i] <= '9')) {
range[range_start++] = (char) tolower(ptr[i]);
if (i >= 2) {
if (ptr[i - 1] != '.')
ok = 0;
else
i--;
}
} else
ok = 0;
}
} else if (index(ptr, ':') != NULL && (ptr2 = index(ptr, '/')) != NULL) {
*ptr2++ = 0;
len = atoi(ptr2);
if (len % 4 > 0 || len < 4 || len > 124) {
fprintf(stderr, "Error: invalid prefix length, must be a multiple of 4!\n");
exit(-1);
}
if (len % 8 > 0)
j = (len / 8) + 1;
else
j = len / 8;
dest = thc_resolve6(ptr);
for (i = 0; i < j; i++) {
range[i * 2] = tohex(dest[i] / 16);
range[i * 2 + 1] = tohex(dest[i] % 16);
}
range_start = len / 4;
} else
ok = 0;
if (ok == 0) {
fprintf(stderr, "Error: invalid ipv6 address specified: %s\n", argv[2]);
exit(-1);
}
memset(buf_start, 0, sizeof(buf_start));
memset(buf_end, 0, sizeof(buf_end));
buf_start[2] = 1;
buf_start[5] = 1;
memcpy(buf, buf_start, sizeof(buf_start));
buf[12] = 1;
buf_end[0] = 3;
strcpy(buf_end + 1, "ip6");
buf_end[4] = 4;
strcpy(buf_end + 5, "arpa");
buf_end[11] = 0x0c;
buf_end[13] = 1;
signal(SIGALRM, ignore);
printf("Starting DNS reverse enumeration of %s on server %s\n", ptr, dst);
// first: wildcard check
ok = 0;
k = 0;
sock = dnssocket(dst);
for (j = 0; j < 5; j++) {
for (i = range_start; i < 32; i++)
range[i] = tohex(rand() % 16);
switch(send_range()) {
case 0:
ok++;
break;
case -1:
k++;
break;
default:
i = 0; // ignored
}
}
if (ok > 2) {
fprintf(stderr, "Error: Wildcard configured in DNS server, not possible to enumerate!\n");
return -1;
}
if (k == 5) {
fprintf(stderr, "Error: DNS server %s sent no replies!\n", dst);
return -1;
} else if (k > 0)
waittime += 2;
// starting the search
i = deeper(range_start);
printf("Found %d entr%s.\n", found, found == 1 ? "y" : "ies");
if (found == 0)
return 1;
else
return 0;
}
More information about the Ipv6hackers
mailing list