aboutsummaryrefslogtreecommitdiffstats
path: root/repos/dnsmap
diff options
context:
space:
mode:
Diffstat (limited to 'repos/dnsmap')
-rw-r--r--repos/dnsmap/CREDITS.txt10
-rw-r--r--repos/dnsmap/Changelog.txt25
-rw-r--r--repos/dnsmap/Makefile12
-rw-r--r--repos/dnsmap/README.txt177
-rw-r--r--repos/dnsmap/TODO.txt13
-rwxr-xr-xrepos/dnsmap/dnsmap-bulk.sh19
-rw-r--r--repos/dnsmap/dnsmap.c795
-rw-r--r--repos/dnsmap/dnsmap.h1047
-rw-r--r--repos/dnsmap/gpl-2.0.txt339
-rw-r--r--repos/dnsmap/use_cases.txt10
-rw-r--r--repos/dnsmap/wordlist_TLAs.txt17576
11 files changed, 20023 insertions, 0 deletions
diff --git a/repos/dnsmap/CREDITS.txt b/repos/dnsmap/CREDITS.txt
new file mode 100644
index 0000000..5f19715
--- /dev/null
+++ b/repos/dnsmap/CREDITS.txt
@@ -0,0 +1,10 @@
+Main author:
+pagvac (gnucitizen.org)
+
+Patches, bug hunting and general feedback:
+Borys Lacki (www.bothunters.pl)
+Philipp Winter (7c0.org)
+meathive (kinqpinz.info)
+David Kierznowski (withdk.com)
+GNa (gnanet.net)
+srl (security.research.labs@gmail.com)
diff --git a/repos/dnsmap/Changelog.txt b/repos/dnsmap/Changelog.txt
new file mode 100644
index 0000000..ba1b097
--- /dev/null
+++ b/repos/dnsmap/Changelog.txt
@@ -0,0 +1,25 @@
+20/02/2010: dnsmap 0.30 released at www.gnucitizen.org
+* IPv6 support
+* Makefile included
+* delay option (-d) added. This is useful in cases where dnsmap is killing your bandwidth
+* ignore IPs option (-i) added. This allows ignoring user-supplied IPs from the results. Useful for domains which cause dnsmap to produce false positives
+* changes made to make dnsmap compatible with OpenDNS
+* disclosure of internal IP addresses (RFC 1918) are reported
+* updated built-in wordlist
+* included a standalone three-letter acronym (TLA) subdomains wordlist
+* domains susceptible to "same site" scripting (http://snipurl.com/etbcv) are reported
+* completion time is now displayed to the user
+* mechanism to attempt to bruteforce wildcard-enabled domains
+* unique filename containing timestamp is now created when no specific output filename is supplied by user
+* various minor bugs fixed
+
+22/02/2009: dnsmap 0.22 released at www.gnucitizen.org
+* saving the results in human-readable and CSV format for easy processing
+* fixed bug that disallowed reading wordlists with DOS CRLF format
+* improved built-in subdomains wordlist
+* new bash script (dnsmap-bulk.sh) included which allows running dnsmap against a list of domains from a user-supplied file. i.e.: bruteforcing several domains in a bulk fashion
+* bypassing of signature-based dnsmap detection by generating a proper pseudo-random subdomain when checking for wildcards
+
+17/08/2006: dnsmap 0.1 (first public version) released at foro.elhacker.net
+* bruteforcing based on builtin list and user-supplied wordlist
+* obtain all available A records for each bruteforced (sub)domain (rather than only one)
diff --git a/repos/dnsmap/Makefile b/repos/dnsmap/Makefile
new file mode 100644
index 0000000..2393d37
--- /dev/null
+++ b/repos/dnsmap/Makefile
@@ -0,0 +1,12 @@
+CC=gcc
+CFLAGS=-I.
+BINDIR=/usr/local/bin
+
+dnsmap: dnsmap.c dnsmap.h
+ $(CC) $(CFLAGS) -o dnsmap dnsmap.c
+
+install: dnsmap
+ mkdir -p $(DESTDIR)$(BINDIR)
+ install -m 0755 dnsmap $(DESTDIR)$(BINDIR)
+ install -m 0755 dnsmap-bulk.sh $(DESTDIR)$(BINDIR)/dnsmap-bulk
+
diff --git a/repos/dnsmap/README.txt b/repos/dnsmap/README.txt
new file mode 100644
index 0000000..beab0f2
--- /dev/null
+++ b/repos/dnsmap/README.txt
@@ -0,0 +1,177 @@
+INTRODUCTION
+
+dnsmap was originally released back in 2006 and was inspired by the
+fictional story "The Thief No One Saw" by Paul Craig, which can be found
+in the book "Stealing the Network - How to 0wn the Box"
+
+dnsmap is mainly meant to be used by pentesters during the information
+gathering/enumeration phase of infrastructure security assessments. During the
+enumeration stage, the security consultant would typically discover the target
+company's IP netblocks, domain names, phone numbers, etc ...
+
+Subdomain brute-forcing is another technique that should be used in the
+enumeration stage, as it's especially useful when other domain enumeration
+techniques such as zone transfers don't work (I rarely see zone transfers
+being *publicly* allowed these days by the way).
+
+If you are interested in researching stealth computer intrusion techniques,
+I suggest reading this excellent (and fun) chapter which you can find for
+*free* on the web:
+
+http://www.ethicalhacker.net/content/view/45/2/
+
+I'm happy to say that dnsmap was included in Backtrack 2, 3 and 4 and has
+been reviewed by the community:
+
+http://backtrack.offensive-security.com/index.php?title=Tools
+http://www.networkworld.com/community/node/57543
+http://www.linuxhaxor.net/2007/07/14/backtrack-2-information-gathering-all-dnsmap/
+http://www.darknet.org.uk/2009/03/dnsmap-022-released-subdomain-bruteforcing-tool/
+http://www.gnucitizen.org/blog/new-version-of-dnsmap-out/
+
+
+COMPILING
+
+Compiling should be straightforward:
+
+$ make
+
+Or:
+
+$ gcc -Wall dnsmap.c -o dnsmap
+
+
+INSTALLATION
+
+Example of manual installation:
+
+# cp ./dnsmap /usr/local/bin/dnsmap
+
+If you wish to bruteforce several target domains in bulk fashion, you can use the
+included dnsmap-bulk.sh script. Just copy the script to /usr/local/bin/ so you can
+call it from any location. e.g.:
+
+# cp ./dnsmap-bulk.sh /usr/local/bin/
+
+And set execute permissions. e.g.:
+
+# chmod ugo+x /usr/local/bin/dnsmap-bulk.sh
+
+
+LIMITATIONS
+
+Lack of multi-threading. This speed issue will hopefully be resolved in future versions.
+
+
+FUN THINGS THAT CAN HAPPEN
+
+1. Finding interesting remote access servers (e.g.: https://extranet.targetdomain.com)
+
+2. Finding badly configured and/or unpatched servers (e.g.: test.targetdomain.com)
+
+3. Finding new domain names which will allow you to map non-obvious/hard-to-find netblocks
+ of your target organization (registry lookups - aka whois is your friend)
+
+4. Sometimes you find that some bruteforced subdomains resolve to internal IP addresses
+ (RFC 1918). This is great as sometimes they are real up-to-date "A" records which means
+ that it *is* possible to enumerate internal servers of a target organization from the
+ Internet by only using standard DNS resolving (as oppossed to zone transfers for instance).
+
+5. Discover embedded devices configured using Dynamic DNS services (e.g.: linksys-cam.com).
+ This method is an alternative to finding devices via Google hacking techniques
+
+USAGE
+
+Bruteforcing can be done either with dnsmap's built-in wordlist or a user-supplied wordlist.
+Results can be saved in CSV and human-readable format for further processing. dnsmap does
+NOT require root privileges to be run, and should NOT be run with such privileges for
+security reasons.
+
+The usage syntax can be obtained by simply running dnsmap without any parameters:
+
+$ ./dnsmap
+
+dnsmap 0.30 - DNS Network Mapper by pagvac (gnucitizen.org)
+
+usage: dnsmap <target-domain> [options]
+options:
+-w <wordlist-file>
+-r <regular-results-file>
+-c <csv-results-file>
+-d <delay-millisecs>
+-i <ips-to-ignore> (useful if you're obtaining false positives)
+
+Note: delay value is a maximum random value. e.g.: if you enter 1000, each DNS request
+will be delayed a *maximum* of 1 second. By default, dnsmap uses a value of 10 milliseconds
+of maximum delay between DNS lookups
+
+
+EXAMPLES
+Subdomain bruteforcing using dnsmap's built-in word-list:
+
+$ ./dnsmap targetdomain.foo
+
+Subdomain bruteforcing using a user-supplied wordlist:
+
+$ ./dnsmap targetdomain.foo -w wordlist.txt
+
+Subdomain bruteforcing using the built-in wordlist and saving the results to /tmp/ :
+
+$ ./dnsmap targetdomain.foo -r /tmp/
+
+Since no filename was provided in the previous example, but rather only a path, dnsmap would
+create an unique filename which includes the current timestamp. e.g.:
+/tmp/dnsmap_targetdomain_foo_2009_12_15_234953.txt
+
+Example of subdomain bruteforcing using the built-in wordlist, saving the results to /tmp/,
+and waiting a random maximum of 3 milliseconds between each request:
+
+$ ./dnsmap targetdomain.foo -r /tmp/ -d 300
+
+It is recommended to use the -d (delay in milliseconds) option in cases where dnsmap is
+interfering with your online experience. i.e.: killing your bandwidth
+
+Subdomain bruteforcing with 0.8 seconds delay, saving results in regular and CSV format,
+filtering 2 user-provided IP and using a user-supplied wordlist:
+
+$ ./dnsmap targetdomain.foo -d 800 -r /tmp/ -c /tmp/ -i 10.55.206.154,10.55.24.100 -w ./wordlist_TLAs.txt
+
+For bruteforcing a list of target domains in a bulk fashion use the bash script provided. e.g.:
+
+$ ./dnsmap-bulk.sh domains.txt /tmp/results/
+
+
+WORDLISTS
+
+http://packetstormsecurity.org/Crackers/wordlists/dictionaries/
+http://www.cotse.com/tools/wordlists1.htm
+http://wordlist.sourceforge.net/
+
+
+OTHER SIMILAR TOOLS - choice is freedom!
+
+WS-DNS-BFX
+http://ws.hackaholic.org/tools/WS-DNS-BFX.tgz
+
+DNSDigger
+http://www.ernw.de/download/dnsdigger.zip
+
+Fierce Domain Scan
+http://ha.ckers.org/fierce/
+
+Desperate
+http://www.sensepost.com/research_misc.html
+
+DNSenum
+http://dnsenum.googlecode.com/files/dnsenum1.2.tar.gz
+
+ReverseRaider
+http://complemento.sourceforge.net/
+
+Knock
+http://knock.gianniamato.it/
+
+
+--
+pagvac | GNUCITIZEN.org
+Feb 2010
diff --git a/repos/dnsmap/TODO.txt b/repos/dnsmap/TODO.txt
new file mode 100644
index 0000000..0df1368
--- /dev/null
+++ b/repos/dnsmap/TODO.txt
@@ -0,0 +1,13 @@
+* multi-threading - use pthread.h?
+* can't handle wildcarded domains that return more than one IP address on non-existing subdomains
+ test domain: proboards.com
+* allow using a customized list of DNS server to share network load
+* allow using DNS server supplied on the command line
+* for openDNS users: document how to permanently change DNS server settings so they are not overwritten by DHCP settings
+* convert hostent structs to addrinfo ?
+* replace inet_ntoa(*((struct in_addr *)host->h_addr_list[j])) with ipstr
+* obtain aliases for each domain (CNAME records)?
+* clever numerical domain bruteforce for clusters. i.e.: www2, www3
+* pickup new subdomains via reverse lookups (PTR records)
+* better input validation
+ * improve function that validates target domain
diff --git a/repos/dnsmap/dnsmap-bulk.sh b/repos/dnsmap/dnsmap-bulk.sh
new file mode 100755
index 0000000..574aba2
--- /dev/null
+++ b/repos/dnsmap/dnsmap-bulk.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+if [[ $# -ne 1 && $# -ne 2 ]]
+then
+ echo "usage: `basename $0` <domains-file> [results-path]";
+ echo "e.g.:";
+ echo "`basename $0` domains.txt";
+ echo "`basename $0` domains.txt /tmp/";
+ exit
+fi
+for i in `cat $1`
+do
+ if [[ $# -eq 1 ]]
+ then
+ dnsmap $i
+ elif [[ $# -eq 2 ]]
+ then
+ dnsmap $i -r $2
+ fi
+done
diff --git a/repos/dnsmap/dnsmap.c b/repos/dnsmap/dnsmap.c
new file mode 100644
index 0000000..5276e30
--- /dev/null
+++ b/repos/dnsmap/dnsmap.c
@@ -0,0 +1,795 @@
+/*
+ * ** dnsmap - DNS Network Mapper by pagvac
+ * ** Copyright (C) 2010 gnucitizen.org
+ * **
+ * ** This program is free software; you can redistribute it and/or modify
+ * ** it under the terms of the GNU General Public License as published by
+ * ** the Free Software Foundation; either version 2 of the License, or
+ * ** (at your option) any later version.
+ * **
+ * ** This program is distributed in the hope that it will be useful,
+ * ** but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * ** GNU General Public License for more details.
+ * **
+ * ** You should have received a copy of the GNU General Public License
+ * ** along with this program; if not, write to the Free Software
+ * ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <netdb.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "dnsmap.h" // built-in subdomains list and define macros
+
+
+// function prototypes
+unsigned short int wildcarDetect(char *, char *);
+unsigned short int dodelay(unsigned short int);
+unsigned short int isPrivateIP(char *);
+unsigned short int isValidDomain(char *);
+unsigned short int usesOpenDNS(char *);
+unsigned short int isIPblacklisted(char *);
+
+int main(int argc, char *argv[]) {
+
+ unsigned short int i=0, j=0, k=0, l=0, found=0, ipCount=0, filtIPcount=0, milliseconds=10, intIPcount=0,
+ wordlist=FALSE, txtResults=FALSE, csvResults=FALSE,
+ delay=TRUE, filter=FALSE;
+ unsigned long int start=0, end=0;
+ char dom[MAXSTRSIZE]={'\0'}, csvResultsFilename[MAXSTRSIZE]={'\0'},
+ txtResultsFilename[MAXSTRSIZE]={'\0'}, wordlistFilename[MAXSTRSIZE]={'\0'},
+ ipstr[INET_ADDRSTRLEN]={'\0'}, wildcardIpStr[INET_ADDRSTRLEN]={'\0'},
+ filterIPs[5][INET_ADDRSTRLEN]={{'\0'}},
+ invalidTldIpstr[INET_ADDRSTRLEN]={'\0'};
+ void *addr;
+ char *ipver, *strP;
+
+ struct hostent *h;
+ // start of IPv6 stuff
+ struct addrinfo hints, *res, *p;
+ int status;
+ char ipv6str[INET6_ADDRSTRLEN];
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_INET6; // AF_INET or AF_INET6 to force version
+ hints.ai_socktype = SOCK_STREAM;
+ // end of IPv6 stuff
+
+ FILE *fpWords,*fpCsvLogs,*fpTxtLogs;
+
+ time_t now;
+ struct tm *ts;
+ char timestampBuf[18];
+
+ printf("%s", BANNER);
+
+ // get the current time
+ now = time(NULL);
+
+ // timestamp format: yyyy_mm_dd_hhmmss
+ ts = localtime(&now);
+ strftime(timestampBuf, sizeof(timestampBuf), "%Y_%m_%d_%H%M%S", ts);
+
+
+ // start of *primitive* input validation
+ // ideally more work should be spent on this!
+ if(argc==1) {
+ printf("%s%s", USAGE, EXAMPLES);
+ exit(1);
+ }
+ else if(argc%2==1 && argc>2) {
+ printf("%s%s", USAGE, EXAMPLES);
+ exit(1);
+ }
+ for(i=0;argv[1][i];++i) // convert domain to lower case
+ argv[1][i]=(tolower(argv[1][i]));
+ #if DEBUG
+ printf("domain: %s\n", argv[1]);
+ #endif
+ if(!isValidDomain(argv[1])) {
+ printf("%s", DOMAINERR);
+ exit(1);
+ }
+
+ for(i=0;i<argc;++i) {
+ if((strlen(argv[i]))>MAXSTRSIZE) {
+ printf("%s",INPUTERR);
+ exit(1);
+ }
+ }
+ // end of simple input validation
+
+ /*
+ else if ((h=gethostbyname(argv[1])) == NULL) { // get the host info
+ herror("gethostbyname");
+ exit(1);
+ }
+ */
+
+ start=(int)time(NULL);
+
+ #if DEBUG
+ printf("start time: %d\n", (int)start);
+ #endif
+
+ // parse options
+ for(i=0;i<argc;++i) {
+ // save results in file using regular format
+ if(!strcmp(argv[i],"-r")) {
+ // contruct path where txt results file will be created
+ txtResults=TRUE;
+ //strncpy(csvResultsFilename, argv[(i+1)], MAXSTRSIZE);
+ strncpy(txtResultsFilename, argv[(i+1)], MAXSTRSIZE-strlen(txtResultsFilename)-1);
+ fpTxtLogs=fopen(txtResultsFilename, "a");
+ if(!fpTxtLogs) {
+ strncat(txtResultsFilename, "dnsmap_", MAXSTRSIZE-strlen(txtResultsFilename)-1);
+ strncat(txtResultsFilename, argv[1], MAXSTRSIZE-strlen(txtResultsFilename)-1);
+ strncat(txtResultsFilename, "_", MAXSTRSIZE-strlen(txtResultsFilename)-1);
+ strncat(txtResultsFilename, timestampBuf, MAXSTRSIZE-strlen(txtResultsFilename)-1);
+ // replace dots '.' with underscores '_' in filename
+ for(l=0;l<strlen(txtResultsFilename);++l)
+ if(txtResultsFilename[l]=='.')
+ txtResultsFilename[l]='_';
+ strncat(txtResultsFilename, ".txt", MAXSTRSIZE-strlen(txtResultsFilename)-1);
+ fpTxtLogs=fopen(txtResultsFilename, "a");
+ if(!fpTxtLogs) {
+ printf(CREATEFILEERR);
+ exit(1);
+ }
+ }
+ }
+
+ // save results in file using CSV format
+ if(!strcmp(argv[i],"-c")) {
+ // contruct path where CSV results file will be created
+ csvResults=TRUE;
+ strncpy(csvResultsFilename, argv[(i+1)], MAXSTRSIZE-strlen(csvResultsFilename)-1);
+ fpCsvLogs=fopen(csvResultsFilename, "a");
+ if(!fpCsvLogs) {
+ strncat(csvResultsFilename, "dnsmap_", MAXSTRSIZE-strlen(csvResultsFilename)-1);
+ strncat(csvResultsFilename, argv[1], MAXSTRSIZE-strlen(csvResultsFilename)-1);
+ strncat(csvResultsFilename, "_", MAXSTRSIZE-strlen(csvResultsFilename)-1);
+ strncat(csvResultsFilename, timestampBuf, MAXSTRSIZE-strlen(csvResultsFilename)-1);
+ // replace dots '.' with underscores '_' in filename
+ for(l=0;l<strlen(csvResultsFilename);++l)
+ if(csvResultsFilename[l]=='.')
+ csvResultsFilename[l]='_';
+ strncat(csvResultsFilename, ".csv", MAXSTRSIZE-strlen(csvResultsFilename)-1);
+ fpCsvLogs=fopen(csvResultsFilename, "a");
+ if(!fpCsvLogs) {
+ printf(CREATEFILEERR);
+ exit(1);
+ }
+ }
+ }
+
+ // use provided wordlist as opposed to built-in one
+ if(!strcmp(argv[i],"-w")) {
+ wordlist=TRUE;
+ strncpy(wordlistFilename, argv[(i+1)],MAXSTRSIZE);
+ }
+
+ // delay between subdomain resolution requests
+ if(!strcmp(argv[i],"-d")) {
+ if(atoi(argv[(i+1)])<1 || atoi(argv[(i+1)])>300000) { // delay must be between 1 ms and 5 minutes
+ printf("%s", DELAYINPUTERR);
+ exit(1);
+ }
+ delay=TRUE;
+ milliseconds=atoi(argv[(i+1)]);
+ }
+ // filter out user-provided IP(s)
+ if(!strcmp(argv[i],"-i")) {
+ for(filtIPcount=1,j=0;argv[i+1][j]!='\0';++j)
+ if(argv[i+1][j]==',')
+ ++filtIPcount;
+ #if DEBUG
+ printf("%d IP(s) to filter found\nParsing ...\n", filtIPcount);
+ #endif
+ if(filtIPcount<=5) {
+ printf(FILTERMSG);
+ strP=strtok(argv[i+1],",");
+ for(j=0;strP;) {
+ if(strlen(strP)<INET_ADDRSTRLEN) {
+ strncpy(filterIPs[j],strP,INET_ADDRSTRLEN);
+ #if DEBUG
+ printf("%s\n",filterIPs[j]);
+ #endif
+ ++j;
+ }
+ strP=strtok(NULL," ,");
+ }
+ }
+ else {
+ printf(FILTIPINPUTERR);
+ exit(1);
+ }
+ }
+ }
+
+ // read subdomains from built-in list
+ if(!wordlist) {
+ // openDNS detection
+ if(usesOpenDNS(invalidTldIpstr))
+ printf("%s",OPENDNSMSG);
+
+ // wildcard detection
+ wildcarDetect(argv[1],wildcardIpStr);
+
+ if(strcmp(invalidTldIpstr,wildcardIpStr))
+ printf(WILDCARDWARN);
+ printf(BUILTINMSG);
+ if(milliseconds>=1)
+ printf(DELAYMSG);
+
+ printf("%s", "\n");
+ for(i=0;i<(sizeof(sub)/MAXSUBSIZE);++i) {
+ //skipResolve=FALSE;
+ strncpy(dom,sub[i],MAXSTRSIZE-strlen(dom)-1);
+ strncat(dom,".",MAXSTRSIZE-strlen(dom)-1);//TEST
+ strncat(dom,argv[1],MAXSTRSIZE-strlen(dom)-1);
+ #if DEBUG
+ printf("brute-forced domain: %s\n",dom);
+ #endif
+
+ // ipv6 code modded from www.kame.net
+ status = getaddrinfo(dom, NULL, &hints, &res);
+ if ((status=getaddrinfo(dom, NULL, &hints, &res))==0) {
+ printf("%s\n", dom);
+ ++found;
+ if(txtResults)
+ fprintf(fpTxtLogs, "%s\n", dom);
+ if(csvResults)
+ fprintf(fpCsvLogs, "%s", dom);
+ for(p=res,k=0;p;p=p->ai_next,++k) {
+ if (p->ai_family==AF_INET6) { // IPv6
+ struct sockaddr_in6 *ipv6=(struct sockaddr_in6 *)p->ai_addr;
+ addr = &(ipv6->sin6_addr);
+ ipver = "IPv6";
+ }
+ // convert the IP to a string and print it:
+ inet_ntop(p->ai_family, addr, ipv6str, sizeof ipv6str);
+ printf("%s address #%d: %s\n",ipver,k+1,ipv6str);
+ ++ipCount;
+ if(txtResults)
+ fprintf(fpTxtLogs,"%s address #%d: %s\n",ipver,k+1,ipv6str);
+ if(csvResults)
+ fprintf(fpCsvLogs,",%s", ipv6str);
+ }
+ printf("%s", "\n");
+ if(txtResults)
+ fprintf(fpTxtLogs,"\n");
+ if(csvResults)
+ fprintf(fpCsvLogs,"\n");
+ freeaddrinfo(res); // free the linked list
+ } // end of if conditional
+ h=gethostbyname(dom);
+ //sprintf(ipstr,inet_ntoa(*((struct in_addr *)h->h_addr_list[0])),"%s");
+ //for(j=0;h->h_addr_list[j];++j) {
+ // sprintf(ipstr,inet_ntoa(*((struct in_addr *)h->h_addr_list[j])),"%s");
+ // if(isIPblacklisted(ipstr)) {
+ // skipResolve=TRUE;
+ // break;
+ // }
+ //}
+ //if(h && !skipResolve) {
+ //if(h && !isIPblacklisted(ipstr)) {
+ if(h && !isIPblacklisted(inet_ntoa(*((struct in_addr *)h->h_addr_list[0])))) {
+ for(j=0;h->h_addr_list[j];++j) {
+ sprintf(ipstr,inet_ntoa(*((struct in_addr *)h->h_addr_list[j])),"%s");
+ for(k=0;k<filtIPcount;++k) {
+ if(strcmp(filterIPs[k],ipstr)==0) { // filtered IP found
+ // 1st IP of array - weird output formatting bug
+ if(j!=0 && strcmp(wildcardIpStr,filterIPs[k])) {
+ printf("\n");
+ if(txtResults)
+ fprintf(fpTxtLogs, "%s", "\n");
+ if(csvResults)
+ fprintf(fpCsvLogs, "%s", "\n");
+ }
+ #if DEBUG
+ printf("%s found and ignored\n",filterIPs[k]);
+ #endif
+ filter=TRUE;
+ if(h->h_addr_list[j+1])
+ ++j;
+ else
+ break;
+ }
+ }
+ // END OF TEST
+ //if(strcmp(wildcardIpStr,ipstr) && strcmp(filterIpStr,ipstr)) {
+ if(strcmp(wildcardIpStr,ipstr) && filter==FALSE) {
+ if(j==0) {
+ ++found;
+ printf("%s\n", dom);
+
+ if(txtResults)
+ fprintf(fpTxtLogs, "%s\n", dom);
+ if(csvResults)
+ fprintf(fpCsvLogs, "%s", dom);
+ }
+ printf("[%d] %s : %s\n", j+1,dom,ipstr);
+ ++ipCount;
+
+ if(isPrivateIP(ipstr)) {
+ //if(isPrivateIP(inet_ntoa(*((struct in_addr *)h->h_addr_list[j])))) {
+ printf("%s",INTIPWARN);
+ ++intIPcount;
+ }
+ if(!strcmp(ipstr,"127.0.0.1") && strcmp(wildcardIpStr,ipstr)) {
+ //if(!strcmp(inet_ntoa(*((struct in_addr *)h->h_addr_list[j])),
+ //"127.0.0.1"))
+ printf("%s",SAMESITEXSSWARN);
+ }
+ if(txtResults) {
+ //fprintf(fpCsvLogs,",%s",
+ // inet_ntoa(*((struct in_addr *)h->h_addr_list[j])));
+ fprintf(fpTxtLogs,"IP address #%d: %s\n", j+1, ipstr);
+ if(isPrivateIP(ipstr) && strcmp(wildcardIpStr,ipstr))
+ fprintf(fpTxtLogs,"%s",INTIPWARN);
+ if(!strcmp(ipstr,"127.0.0.1") && strcmp(wildcardIpStr,ipstr))
+ fprintf(fpTxtLogs,"%s",SAMESITEXSSWARN);
+ }
+ if(csvResults && strcmp(wildcardIpStr,ipstr))
+ fprintf(fpCsvLogs,",%s",ipstr);
+ }
+ }
+ //if(strcmp(wildcardIpStr,ipstr) && strcmp(filterIpStr,ipstr)) {
+ if(strcmp(wildcardIpStr,ipstr) && filter==FALSE) {
+ printf("%s", "\n");
+ if(txtResults)
+ fprintf(fpTxtLogs,"%s","\n");
+ if(csvResults)
+ fprintf(fpCsvLogs,"%s","\n");
+ }
+ filter=FALSE;
+ }
+ // user wants delay between DNS requests?
+ if(delay)
+ dodelay(milliseconds);
+ }
+ if(txtResults)
+ fclose(fpTxtLogs);
+ if(csvResults)
+ fclose(fpCsvLogs);
+ }
+
+ // read subdomains from wordlist file
+ else if(wordlist) {
+ // openDNS detection
+ if(usesOpenDNS(invalidTldIpstr))
+ printf("%s",OPENDNSMSG);
+
+ // wildcard detection
+ wildcarDetect(argv[1],wildcardIpStr);
+ if(strcmp(invalidTldIpstr,wildcardIpStr))
+ printf(WILDCARDWARN);
+
+ fpWords=fopen(wordlistFilename, "r");
+ if(fpWords) {
+ printf(EXTERNALMSG);
+ if(milliseconds>=1)
+ printf(DELAYMSG);
+ printf("%s","\n");
+
+ while(!feof(fpWords)) {
+ //strncpy(dom,"",MAXSTRSIZE-strlen(dom)-1);
+ for(i=0;i<strlen(dom);++i)
+ dom[i]='\0';
+ fscanf(fpWords,"%100s",dom); // wordlist subdomain not allowed to be more than 100 chars
+ #if DEBUG
+ printf("lengh of dom: %d\n",strlen(dom));
+ #endif
+ strncat(dom,".",MAXSTRSIZE-strlen(dom)-1);
+ strncat(dom,argv[1],MAXSTRSIZE-strlen(dom)-1);
+
+ #if DEBUG
+ printf("brute-forced domain: %s\n",dom);
+ #endif
+ // ipv6 code modded from www.kame.net
+ status = getaddrinfo(dom, NULL, &hints, &res);
+ if ((status=getaddrinfo(dom, NULL, &hints, &res))==0) {
+ printf("%s\n", dom);
+ ++found;
+ if(txtResults)
+ fprintf(fpTxtLogs, "%s\n", dom);
+ if(csvResults)
+ fprintf(fpCsvLogs, "%s", dom);
+ for(p=res,k=0;p;p=p->ai_next,++k) {
+ void *addr;
+ char *ipver;
+ if (p->ai_family==AF_INET6) { // IPv6
+ struct sockaddr_in6 *ipv6=(struct sockaddr_in6 *)p->ai_addr;
+ addr = &(ipv6->sin6_addr);
+ ipver = "IPv6";
+ }
+ // convert the IP to a string and print it:
+ inet_ntop(p->ai_family, addr, ipv6str, sizeof ipv6str);
+ printf("%s address #%d: %s\n",ipver,k+1,ipv6str);
+ ++ipCount;
+ if(txtResults)
+ fprintf(fpTxtLogs,"%s address #%d: %s\n",ipver,k+1,ipv6str);
+ if(csvResults)
+ fprintf(fpCsvLogs,",%s", ipv6str);
+ }
+ printf("%s", "\n");
+ if(txtResults)
+ fprintf(fpTxtLogs,"\n");
+ if(csvResults)
+ fprintf(fpCsvLogs,"\n");
+
+ freeaddrinfo(res); // free the linked list
+ // ipv6 code modded from www.kame.net
+ } // end of if conditional
+
+ h=gethostbyname(dom);
+
+ if(h && !isIPblacklisted(inet_ntoa(*((struct in_addr *)h->h_addr_list[0])))) {
+ for(j=0;h->h_addr_list[j];++j) {
+ sprintf(ipstr,inet_ntoa(*((struct in_addr *)h->h_addr_list[j])),"%s");
+ //TEST
+ for(k=0;k<filtIPcount;++k) {
+ if(strcmp(filterIPs[k],ipstr)==0) { // filtered IP found
+ // 1st IP of array - weird output formatting bug
+ if(j!=0 && strcmp(wildcardIpStr,filterIPs[k])) {
+ printf("\n");
+ if(txtResults)
+ fprintf(fpTxtLogs, "%s", "\n");
+ if(csvResults)
+ fprintf(fpCsvLogs, "%s", "\n");
+ }
+ #if DEBUG
+ printf("%s found and ignored\n",filterIPs[k]);
+ #endif
+ filter=TRUE;
+ if(h->h_addr_list[j+1])
+ ++j;
+ else
+ break;
+ }
+ }
+ // END OF TEST
+
+ //if(strcmp(wildcardIpStr,ipstr) && strcmp(filterIpStr,ipstr)) {
+ if(strcmp(wildcardIpStr,ipstr) && filter==FALSE) {
+ if(j==0) {
+ ++found;
+ printf("%s\n",dom);
+
+ if(txtResults) {
+ //fprintf(fpCsvLogs,"%s",dom);
+ fprintf(fpTxtLogs,"%s\n",dom);
+ }
+ if(csvResults) {
+ //fprintf(fpCsvLogs,"%s",dom);
+ fprintf(fpCsvLogs,"%s",dom);
+ }
+ }
+ printf("IP address #%d: %s\n",j+1,ipstr);
+ ++ipCount;
+
+ if(isPrivateIP(ipstr) && strcmp(wildcardIpStr,ipstr)) {
+ printf("%s",INTIPWARN);
+ ++intIPcount;
+ }
+ if(!strcmp(ipstr,"127.0.0.1") && strcmp(wildcardIpStr,ipstr))
+ printf("%s",SAMESITEXSSWARN);
+ if(txtResults && strcmp(wildcardIpStr,ipstr)) {
+ fprintf(fpTxtLogs,"IP address #%d: %s\n",j+1,ipstr);
+ if(isPrivateIP(ipstr))
+ fprintf(fpTxtLogs,"%s",INTIPWARN);
+ if(!strcmp(ipstr,"127.0.0.1"))
+ fprintf(fpTxtLogs,"%s",SAMESITEXSSWARN);
+ }
+ if(csvResults && strcmp(wildcardIpStr,ipstr))
+ fprintf(fpCsvLogs,",%s",ipstr);
+ }
+ }
+ //if(strcmp(wildcardIpStr,ipstr) && strcmp(filterIpStr,ipstr)) {
+ if(strcmp(wildcardIpStr,ipstr) && filter==FALSE) {
+ printf("%s", "\n");
+ if(txtResults)
+ fprintf(fpTxtLogs,"%s","\n");
+ if(csvResults)
+ fprintf(fpCsvLogs,"%s","\n");
+ }
+ filter=FALSE;
+ }
+ // user wants delay between DNS requests?
+ if(delay)
+ dodelay(milliseconds);
+ } // end while() loop
+ fclose(fpWords);
+ }
+ else {
+ printf(OPENFILEERR);
+ exit(1);
+ }
+ if(txtResults)
+ fclose(fpTxtLogs);
+ if(csvResults)
+ fclose(fpCsvLogs);
+ }
+
+ printf(RESULTSMSG4);
+ if(intIPcount>=1)
+ printf(RESULTSMSG1);
+
+ if(txtResults)
+ printf(RESULTSMSG2);
+ if(csvResults)
+ printf(RESULTSMSG5);
+
+ end=(int)time(NULL);
+ printf(RESULTSMSG3);
+
+ return 0;
+}
+
+// return true if domain wildcards are enabled
+unsigned short int wildcarDetect(char *dom, char *ipstr) {
+ char strTmp[30]={'\0'},s[MAXSTRSIZE]={'\0'};
+ unsigned short int i=0,n=0,max=0;
+ struct hostent *h;
+
+ srand(time(NULL));
+ max=rand()%20;
+ // max should be between 10 and 20
+ if(max<10)
+ max=max+(10-max);
+
+ // generate up to random 20 digits-long subdomain
+ // e.g. 06312580442146732554
+
+ for(i=0;i<max;++i) {
+ n=rand()%10;
+ sprintf(strTmp, "%d", n);
+ if(i==0)
+ strncpy(s,strTmp,MAXSTRSIZE-strlen(s)-1);
+ else
+ strncat(s,strTmp,MAXSTRSIZE-strlen(s)-1);
+ }
+ strncat(s,".",MAXSTRSIZE-strlen(s)-1);
+ strncat(s, dom,MAXSTRSIZE-strlen(s)-1);
+ #if DEBUG
+ printf("random subdomain for wildcard testing: %s\n",s);
+ #endif
+
+ // random subdomain resolves, thus wildcards are enabled
+ h=gethostbyname(s); // replace with getaddrinfo() ?
+ if(h) { /*
+ for(i=0;h->h_addr_list[i];++i) {
+ */
+ //sprintf(ipstr,inet_ntoa(*((struct in_addr *)h->h_addr_list[i])),"%s");
+ sprintf(ipstr,inet_ntoa(*((struct in_addr *)h->h_addr_list[0])),"%s");
+ #if DEBUG
+ printf("wildcard domain\'s IP address: %s\n",ipstr);
+ #endif
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+// return number of milliseconds delayed
+unsigned short int dodelay(unsigned short int maxmillisecs) {
+ unsigned short int n=0;
+
+ srand(time(NULL));
+ n=rand()%maxmillisecs;
+ ++n;
+ maxmillisecs=n;
+ #if DEBUG
+ printf("sleeping %d milliseconds ...\n",maxmillisecs);
+ #endif
+ usleep(maxmillisecs*1000);
+
+ return maxmillisecs;
+}
+
+// return true if IP addr is internal (RFC1918)
+unsigned short int isPrivateIP(char *ip) {
+
+ char classB[][8]={"172.16.","172.17.","172.18.","172.19.",
+ "172.20.","172.21.","172.22.","172.23.","172.24.",
+ "172.25.","172.26.","172.27.","172.28.","172.29.",
+ "172.30.","172.31."};
+
+ unsigned short int i=0,j=0;
+ size_t len = strlen(ip);
+
+ // shortest: 0.0.0.0 - 8 chars inc \0
+ // longest: 255.255.255.255 - 16 chars inc \0
+ if(len<8 || len>16)
+ return 0;
+ // ip addr must have three period signs
+ for(i=0,j=0;i<len;++i) {
+ if(ip[i]=='.')
+ ++j;
+ }
+ if(j!=3 || ip[0]=='.' || ip[len-1]=='.')
+ return 0;
+
+ // 10.0.0.0 - 10.255.255.255 (10/8 prefix)
+ if(strncmp(ip,"10.",3)==0)
+ return 1;
+
+ // 192.168.0.0 - 192.168.255.255 (192.168/16 prefix)
+ else if(strncmp(ip,"192.168.",8)==0)
+ return 1;
+
+
+ else {
+ // 172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
+ for(i=0;i<sizeof(classB)/8;++i) {
+ if(strncmp(ip,classB[i],7)==0)
+ return 1;
+ }
+ return 0;
+ }
+}
+
+// return true if domain is valid, false otherwise
+unsigned short int isValidDomain(char *d) {
+
+ unsigned int i=0, j=0;
+ char *tld;
+ size_t len;
+ char strTmp[30]={'\0'},s[MAXSTRSIZE]={'\0'};
+ unsigned short int n=0,max=0;
+
+ struct hostent *h;
+
+ if(strlen(d)<4) // smallest possible domain provided. e.g. a.pl
+ return 0;
+ if(!strstr(d,".")) // target domain must have at least one dot. e.g. target.va, branch.target.va
+ return 0;
+ tld=strstr(d,".");
+ tld=tld+1;
+ while(strstr(tld,".")){
+ tld=strstr(tld,".");
+ tld=tld+1;
+ }
+ #if DEBUG
+ printf("tld\'s length: %d\n",strlen(tld));
+ printf("dom: %s tld: %s\n",d,tld);
+ #endif
+ if((strlen(tld)<2) || (strlen(tld)>6)) // tld must be between 2-6 char. e.g. .museum, .uk
+ return FALSE;
+
+ // valid domain can only contain digits, letters, dot (.) and dash symbol (-)
+ len = strlen(d);
+ for(i=0;i<len;++i) {
+ if (!(d[i] >= '0' && d[i] <= '9') &&
+ !(d[i] >= 'a' && d[i] <= 'z') &&
+ !(d[i] >= 'A' && d[i] <= 'Z') &&
+ !(d[i] >= '-' && d[i] <= '.'))
+ return 0;
+ }
+
+ srand(time(NULL));
+ max=rand()%20;
+ // max should be between 10 and 20
+ if(max<10)
+ max=max+(10-max);
+
+ // generate up to random 20 digits-long subdomain
+ // e.g. 06312580442146732554
+
+ for(i=0;i<max;++i) {
+ n=rand()%10;
+ sprintf(strTmp, "%d", n);
+ if(i==0)
+ strncpy(s,strTmp,MAXSTRSIZE-strlen(s)-1);
+ else
+ strncat(s,strTmp,MAXSTRSIZE-strlen(s)-1);
+ }
+ strncat(s,".",MAXSTRSIZE-strlen(s)-1);
+ strncat(s, d,MAXSTRSIZE-strlen(s)-1);
+ #if DEBUG
+ printf("random subdomain for wildcard testing: %s\n",s);
+ #endif
+
+ // some domains like proboards.com return more than 1 IP address
+ // when resolving random subdomains (wildcards are enabled)
+ h=gethostbyname(s);
+ if(h) {
+ for(j=0;h->h_addr_list[j];++j)
+ inet_ntoa(*((struct in_addr *)h->h_addr_list[j]));
+ if(j>1) {
+ #if DEBUG
+
+