diff options
Diffstat (limited to 'repos')
| -rw-r--r-- | repos/dnsmap/CREDITS.txt | 10 | ||||
| -rw-r--r-- | repos/dnsmap/Changelog.txt | 25 | ||||
| -rw-r--r-- | repos/dnsmap/Makefile | 12 | ||||
| -rw-r--r-- | repos/dnsmap/README.txt | 177 | ||||
| -rw-r--r-- | repos/dnsmap/TODO.txt | 13 | ||||
| -rwxr-xr-x | repos/dnsmap/dnsmap-bulk.sh | 19 | ||||
| -rw-r--r-- | repos/dnsmap/dnsmap.c | 795 | ||||
| -rw-r--r-- | repos/dnsmap/dnsmap.h | 1047 | ||||
| -rw-r--r-- | repos/dnsmap/gpl-2.0.txt | 339 | ||||
| -rw-r--r-- | repos/dnsmap/use_cases.txt | 10 | ||||
| -rw-r--r-- | repos/dnsmap/wordlist_TLAs.txt | 17576 | 
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 +     +                                printf("wildcard domain\'s number of IP address(es): %d" +                                        " (this causes dnsmap to produce false positives)\n",j); +                        #endif +                        return FALSE; +                } +        } + +	return TRUE; + +} + +// return true if IP is blacklisted, false otherwise +unsigned short int isIPblacklisted(char *ip) { +	int i; +	// add you own blacklisted IP addresses here if dnsmap is producing false positives. +	// this could be caused by your ISP returning a captive portal search page when +	// when requesting invalid domains on your browser +	char ips[][INET_ADDRSTRLEN]={ +					"81.200.64.50", +					"67.215.66.132", +					"1.2.3.4", +					"0.0.0.0"	// add your fa | 
