opexxx

dripper.c

Sep 25th, 2013
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 15.26 KB | None | 0 0
  1. /*
  2. * Stateless DNS Scanner -- dripper.c
  3. * (C) 2013 jtripper
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 1, or (at your option)
  8. * any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <arpa/inet.h>
  20. #include <errno.h>
  21. #include <netinet/ip.h>
  22. #include <netinet/udp.h>
  23. #include <regex.h>
  24. #include <stdarg.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <sys/socket.h>
  29. #include <unistd.h>
  30.  
  31. in_addr_t *dns_servers;
  32. int   NUM_DNS    = 0;
  33. char *RESOLVCONF = "resolv.conf";
  34. char *SUBDOMAINS = "subs.txt";
  35.  
  36. // structs for the DNS protocol
  37. struct dnsflags {
  38.   unsigned short rd:1;
  39.   unsigned short tc:1;
  40.   unsigned short aa:1;
  41.   unsigned short opcode:4;
  42.   unsigned short qr:1;
  43.  
  44.   unsigned short rcode:4;
  45.   unsigned short z:3;
  46.   unsigned short ra:1;
  47. };
  48.  
  49. struct dnshdr {
  50.   unsigned short txid;
  51.   struct dnsflags dns_flags;
  52.   unsigned short questions;
  53.   unsigned short answer_rrs;
  54.   unsigned short authority_rrs;
  55.   unsigned short additional_rrs;
  56. };
  57.  
  58. struct dnstype {
  59.   unsigned short type;
  60.   unsigned short class;
  61. };
  62.  
  63. struct dnsanswer {
  64.   unsigned short name;
  65.   struct dnstype qtype;
  66.   unsigned short pad;
  67.   unsigned short ttl;
  68.   unsigned short len;
  69. };
  70.  
  71. // ipv4_network struct
  72. struct ipv4_network {
  73.   unsigned long mask;
  74.   unsigned long cidr;
  75.   unsigned long max;
  76.   unsigned long addr;
  77.   struct in_addr sin_addr;
  78. };
  79.  
  80. void convert_to_dns(char *dns);
  81. void convert_to_str(char *pkt, int len, char *max);
  82. void error(char *format, ...);
  83. void forward_brute(char *target);
  84. int  ip_range_init(char *range, struct ipv4_network *network);
  85. int  ip_range_next(struct ipv4_network *network);
  86. void parse_dns_reply(unsigned char *pkt, int len_pkt, char *domain);
  87. void parse_resolv_conf();
  88. void print_hex(unsigned char *pkt, int len);
  89. void reverse_search(char *range);
  90. void rstrip(char *str);
  91. int  send_dns(char *target, int type);
  92. void sniff_dns_replies(char *domain);
  93. void usage();
  94.  
  95. // convert dotted format to domain name format
  96. // arguments:
  97. //   dns -> domain name
  98. void convert_to_dns(char *dns) {
  99.   char *mark = NULL;
  100.   int i, j;
  101.  
  102.   for(i=0; i<=strlen(dns); i++) {
  103.     if(dns[i] == '.' && !mark)
  104.       mark = (dns + i);
  105.     else if(dns[i] == '.' || (dns[i] == '\0' && mark)) {
  106.       mark[0] = (char)((dns + i) - mark - 1);
  107.       mark = (dns + i);
  108.     }
  109.   }
  110. }
  111.  
  112. // convert domain name format to regular dotted format
  113. // arguments:
  114. //   pkt -> packet
  115. //   len -> length of domain name (set to 0 if null terminated)
  116. //   max -> highest offset to go to
  117. void convert_to_str(char *pkt, int len, char *max) {
  118.   int i, j;
  119.  
  120.   if((len == 0 && pkt + strlen(pkt) > max) || (len > 0 && pkt + len > max))
  121.     return;
  122.  
  123.   for(i=0; i< (len > 0 ? len : strlen(pkt)); i++) {
  124.     j = pkt[i];
  125.     pkt[i] = '.';
  126.     i += j;
  127.   }
  128.  
  129.   if(len > 0)
  130.     pkt[len] = '\0';
  131. }
  132.  
  133. // print an error
  134. // arguments:
  135. //   format -> format string
  136. //   format string arguments
  137. void error(char *format, ...) {
  138.   char error_buffer[1024];
  139.   va_list args;
  140.  
  141.   va_start(args, format);
  142.   vsnprintf(error_buffer, sizeof(error_buffer), format, args);
  143.   perror(error_buffer);
  144.   va_end(args);
  145.   exit(1);
  146. }
  147.  
  148. // bruteforce forward DNS
  149. // arguments:
  150. //   target -> domain name to bruteforce
  151. void forward_brute(char *target) {
  152.   int i=0;
  153.   char record[80], line[80];
  154.   FILE *f;
  155.  
  156.   if(!(f = fopen(SUBDOMAINS, "r")))
  157.     error("[!] Error opening: %s", SUBDOMAINS);
  158.  
  159.   // loop over file and send requests
  160.   while (fgets(line, 80, f) != NULL) {
  161.     memset(record, 0, 80);
  162.     rstrip(line);
  163.     snprintf(record, 80, ".%s.%s", line, target);
  164.     send_dns(record, 1);
  165.     i++;
  166.     if(i == 1000) {
  167.       sleep(1);
  168.       i = 0;
  169.     }
  170.   }
  171.  
  172.   fprintf(stderr, "All domains scanned.\n");
  173.   fclose(f);
  174. }
  175.  
  176. // initialize an ipv4_network structure
  177. // Arguments:
  178. //   * range   -> string in CIDR network format (e.g. 192.168.0.1/24)
  179. //   * network -> pointer to ipv4_network structure
  180. int ip_range_init(char *range, struct ipv4_network *network) {
  181.   char *slash, tmp_range[20];
  182.   unsigned long num_addrs;
  183.  
  184.   // copy the range into our own variable
  185.   strncpy(tmp_range, range, 19);
  186.  
  187.   // retreive a pointer to the CIDR value
  188.   // thanks for pointing this out http://reddit.com/u/abadidea
  189.   if(!(slash = strchr(tmp_range, '/'))) {
  190.     fprintf(stderr, "[!] Error, invalid CIDR format.\n");
  191.     exit(1);
  192.   }
  193.  
  194.   // verify that the CIDR converts to an unsigned int < 33
  195.   if((network->cidr = atoi(slash + 1)) > 32) {
  196.     fprintf(stderr, "[!] Error, invalid CIDR value.\n");
  197.     exit(1);
  198.   }
  199.  
  200.   // convert the slash into a \0
  201.   slash[0] = '\0';
  202.  
  203.   // convert the IP address into network format
  204.   if(!inet_aton(tmp_range, &network->sin_addr)) {
  205.     fprintf(stderr, "[!] Error, invalid address.\n");
  206.     exit(1);
  207.   }
  208.  
  209.   // reverse the order of the address
  210.   network->addr = ntohl(network->sin_addr.s_addr);
  211.   // retrieve the number of addresses
  212.   num_addrs     = (unsigned long)0xffffffff >> network->cidr;
  213.   // get the network mask
  214.   network->mask = ~num_addrs;
  215.   // get the first address
  216.   network->addr = network->addr & network->mask;
  217.   // get the last address
  218.   network->max  = network->addr + num_addrs;
  219.  
  220.   return 0;
  221. }
  222.  
  223. // Get the next address in an ipv4_network, returns 0 if there are no more addresses
  224. // returns 1 if there are still more address.
  225. // Arguments:
  226. //   * network -> pointer to an initiaziled ipv4_network struct
  227. int ip_range_next(struct ipv4_network *network) {
  228.   if(network->max <= network->addr - 1) {
  229.     return 0;
  230.   } else {
  231.     network->sin_addr.s_addr = htonl(network->addr);
  232.     network->addr++;
  233.     return 1;
  234.   }
  235. }
  236.  
  237. // parse incoming packets
  238. // arguments:
  239. //   pkt     -> packet
  240. //   len_pkt -> packet length
  241. //   domain  -> only print if domain matches (for PTR records only)
  242. void parse_dns_reply(unsigned char *pkt, int len_pkt, char *domain) {
  243.   int length = 0, i, to_dns = 0;
  244.   char *name;
  245.   struct iphdr  *ip_header;
  246.   struct udphdr *udp_header;
  247.   struct dnshdr *dns_header;
  248.   struct dnsanswer *answer;
  249.   struct in_addr *inaddr;
  250.  
  251.   ip_header  = (struct iphdr*)pkt;
  252.   length    += sizeof(struct iphdr);
  253.   udp_header = (struct udphdr*)(pkt + length);
  254.   length    += sizeof(struct udphdr);
  255.   dns_header = (struct dnshdr*)(pkt + length);
  256.   to_dns     = length;
  257.   length    += sizeof(struct dnshdr);
  258.  
  259.   // make sure source port is 53
  260.   if(udp_header->source != htons(53))
  261.     return;
  262.  
  263.   // return if there's no answers
  264.   if(ntohs(dns_header->answer_rrs) < 1)
  265.     return;
  266.  
  267.   // loop over the questions and convert names to strings
  268.   for(i=0; i<ntohs(dns_header->questions); i++) {
  269.     convert_to_str(pkt + length, 0, pkt + len_pkt);
  270.     length += strlen(pkt + length) + 1 + sizeof(struct dnstype);
  271.     if(length > len_pkt)
  272.       return;
  273.   }
  274.  
  275.   // loop over answers
  276.   for(i=0; i<ntohs(dns_header->answer_rrs); i++) {
  277.     answer  = (struct dnsanswer*)(pkt + length);
  278.     length += sizeof(struct dnsanswer);
  279.     if(length > len_pkt)
  280.       return;
  281.  
  282.     // get the offset of the domain name for the answer
  283.     name = (pkt + to_dns + (ntohs(answer->name) & 0xff) + 1);
  284.  
  285.     if(length + ntohs(answer->len) > len_pkt)
  286.       return;
  287.  
  288.     // A
  289.     if(ntohs(answer->qtype.type) == 1) {
  290.       if(ntohs(answer->len) != 4)
  291.         return;
  292.       inaddr = (struct in_addr*)(pkt + length);
  293.       printf("%s -> %s (A)\n", name, inet_ntoa(*inaddr));
  294.     }
  295.     // CNAME
  296.     else if(ntohs(answer->qtype.type) == 5) {
  297.       convert_to_str(pkt + length, ntohs(answer->len) - 1, pkt + len_pkt);
  298.       printf("%s -> %s (CNAME)\n", name, pkt + length + 1);
  299.     }
  300.     // PTR
  301.     else if(ntohs(answer->qtype.type) == 12) {
  302.       convert_to_str(pkt + length, ntohs(answer->len) - 1, pkt + len_pkt);
  303.       if(strstr(pkt + length + 1, domain))
  304.         printf("%s -> %s (PTR)\n", name, pkt + length + 1);
  305.     }
  306.  
  307.     length += ntohs(answer->len);
  308.   }
  309. }
  310.  
  311. // parse a newline delimited resolv.conf file
  312. // arguments:
  313. //   none
  314. void parse_resolv_conf() {
  315.   FILE *f;
  316.   char ns[80];
  317.   int i = 0;
  318.   regex_t preg;
  319.   regmatch_t pmatch[1];
  320.  
  321.   // IP regex
  322.   regcomp(&preg, "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\n$", REG_EXTENDED);
  323.  
  324.   if(!(f = fopen(RESOLVCONF, "r")))
  325.     error("[!] Error opening: %s", RESOLVCONF);
  326.  
  327.   // count lines in file
  328.   while (fgets(ns, 80, f) != NULL) {
  329.     if (!regexec(&preg, ns, 1, pmatch, 0))
  330.       NUM_DNS++;
  331.   }
  332.  
  333.   // go back to the beginning
  334.   rewind(f);
  335.  
  336.   // allocate the DNS servers array
  337.   dns_servers = (in_addr_t*)malloc(sizeof(in_addr_t) * NUM_DNS);
  338.  
  339.   // populate array
  340.   while(fgets(ns, 80, f) != NULL) {
  341.     if (regexec(&preg, ns, 1, pmatch, 0) != 0)
  342.       continue;
  343.     dns_servers[i] = inet_addr(ns);
  344.     i++;
  345.   }
  346.  
  347.   fclose(f);
  348. }
  349.  
  350. // hexdump a char array (for debugging mainly)
  351. // arguments:
  352. //   pkt -> char array to dump
  353. //   len -> number of bytes to print
  354. void print_hex(unsigned char *pkt, int len) {
  355.   int i, j;
  356.  
  357.   for(i=0, j=0; i<len; i++, j++) {
  358.     if(j == 16) j = 0;
  359.  
  360.     printf("%02x ", pkt[i]);
  361.     switch (j) {
  362.       case 7:
  363.         printf(" ");
  364.         break;
  365.       case 15:
  366.         printf("\n");
  367.         break;
  368.     }
  369.   }
  370.  
  371.   printf("\n\n");
  372. }
  373.  
  374. // do a reverse dns search
  375. // arguments:
  376. //   range -> IP range in format 192.168.0.0/24
  377. void reverse_search(char *range) {
  378.   char lookup[29];
  379.   struct ipv4_network network;
  380.  
  381.   ip_range_init(range, &network);
  382.   while(ip_range_next(&network)) {
  383.     network.sin_addr.s_addr = network.addr;
  384.     sprintf(lookup, ".%s.in-addr.arpa", inet_ntoa(network.sin_addr));
  385.     send_dns(lookup, 12);
  386.   }
  387. }
  388.  
  389. // remove trailing new lines
  390. // arguments:
  391. //   str -> string to remove
  392. void rstrip(char *str) {
  393.   int i;
  394.  
  395.   // loop over the string, if any newlines are found change to \0
  396.   for(i=0; i<strlen(str); i++) {
  397.     if(str[i] == '\n' || str[i] == '\r')
  398.       str[i] = '\0';
  399.   }
  400. }
  401.  
  402. // send a DNS request
  403. // arguments:
  404. //   target -> domain to lookup
  405. //   type   -> DNS query type (1 for A, 12 for PTR)
  406. int send_dns(char *target, int type) {
  407.   char  *pkt = (char*)calloc(4096, 1);
  408.   int sock, value = 1, length = 0;
  409.   struct iphdr  *ip_header;
  410.   struct udphdr *udp_header;
  411.   struct dnshdr *dns_header;
  412.   struct dnstype *dns_type;
  413.   struct sockaddr_in daddr;
  414.  
  415.   // pick a random DNS server from the list
  416.   daddr.sin_family      = AF_INET;
  417.   daddr.sin_port        = htons(53);
  418.   daddr.sin_addr.s_addr = dns_servers[rand() % NUM_DNS];
  419.  
  420.   // fill IP header
  421.   ip_header = (struct iphdr*)pkt;
  422.   ip_header->ihl      = 5;
  423.   ip_header->version  = 4;
  424.   ip_header->tos      = 0;
  425.   ip_header->id       = htonl(rand() % 65534 + 1);
  426.   ip_header->frag_off = 0;
  427.   ip_header->ttl      = 255;
  428.   ip_header->protocol = IPPROTO_UDP;
  429.   ip_header->check    = 0;
  430.   ip_header->daddr    = daddr.sin_addr.s_addr;
  431.  
  432.   length += sizeof(struct iphdr);
  433.  
  434.   // fill out UDP header
  435.   udp_header = (struct udphdr*)(pkt + length);
  436.   udp_header->source = htons(rand() % 65534 + 1);
  437.   udp_header->dest   = htons(53);
  438.   udp_header->check  = 0;
  439.  
  440.   length += sizeof(struct udphdr);
  441.  
  442.   // fill out DNS header
  443.   dns_header = (struct dnshdr*)(pkt + length);
  444.   dns_header->txid         = htons(rand() % 65534 + 1);
  445.   // recursion desired = 1
  446.   dns_header->dns_flags.rd = 1;
  447.   dns_header->questions    = htons(1);
  448.  
  449.   length += sizeof(struct dnshdr);
  450.  
  451.   // convert domain to DNS format and copy into the packet
  452.   convert_to_dns(target);
  453.   memcpy(pkt + length, target, strlen(target) + 1);
  454.  
  455.   length += strlen(target) + 1;
  456.  
  457.   // set the type and class
  458.   dns_type = (struct dnstype*)(pkt + length);
  459.   dns_type->type  = htons(type);
  460.   dns_type->class = htons(1);
  461.  
  462.   length += sizeof(struct dnstype);
  463.  
  464.   ip_header->tot_len = length;
  465.   udp_header->len    = htons(length - sizeof(struct iphdr));
  466.  
  467.   // spawn the raw socket
  468.   if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) < 0)
  469.     error("[!] Error socket:");
  470.  
  471.   // tell the kernel we will handle our own headers
  472.   setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &value, sizeof(int));
  473.  
  474.   // send the packet
  475.   if((sendto(sock, pkt, ip_header->tot_len, 0, (struct sockaddr*)&daddr, sizeof(struct sockaddr))) < 0)
  476.     error("[!] Error sendto:");
  477.  
  478.   free(pkt);
  479.   close(sock);
  480. }
  481.  
  482. // start UDP sniffer
  483. // arguments:
  484. //   domain -> only print matching PTR records
  485. void sniff_dns_replies(char *domain) {
  486.   int sniffer, sockaddr_size = sizeof(struct sockaddr), len_pkt;
  487.   unsigned char *buffer = (unsigned char *)calloc(65560, 1);
  488.   struct sockaddr saddr;
  489.  
  490.   // start a raw socket
  491.   if((sniffer = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) < 0)
  492.     error("[!] Error socket:");
  493.  
  494.   for(;;) {
  495.     // receive from port 0 (or sniff all incoming UDP packets)
  496.     if((len_pkt = recvfrom(sniffer, buffer, 65536, 0, &saddr, &sockaddr_size)) < 1)
  497.       continue;
  498.     // parse UDP packets
  499.     parse_dns_reply(buffer, len_pkt, domain);
  500.   }
  501. }
  502.  
  503. // print usage and exit
  504. // arguments:
  505. //   void
  506. void usage() {
  507.   fprintf(stderr, "dripper usage:\n");
  508.   fprintf(stderr, " * -h                     -- display this message.\n");
  509.   fprintf(stderr, " * -r <resolv conf>       -- resolv.conf (list of nameservers).\n");
  510.   fprintf(stderr, " * -s <subdomain list>    -- subdomain list (list of subdomains).\n");
  511.   fprintf(stderr, " * -d <domain to brute>   -- target domain (e.g. google.com).\n");
  512.   fprintf(stderr, " * -i <ip range to brute> -- IP range to bruteforce for a target domain.\n");
  513.   exit(1);
  514. }
  515.  
  516. int main(int argc, char *argv[]) {
  517.   char *range=NULL, *domain=NULL, opt;
  518.   srand(time(NULL));
  519.  
  520.   fprintf(stderr, "---------------------------------\n");
  521.   fprintf(stderr, "dripper Stateless DNS Scanner 1.0\n");
  522.   fprintf(stderr, "  (c) jtripper 2013\n");
  523.   fprintf(stderr, "  http://blackhatlibrary.net/\n");
  524.   fprintf(stderr, "---------------------------------\n\n");
  525.  
  526.   if(argc == 1)
  527.     usage();
  528.  
  529.   // get options
  530.   while((opt = getopt(argc, argv, "hr:s:d:i:")) != -1) {
  531.     switch(opt) {
  532.       // override default resolvconf
  533.       case 'r':
  534.         RESOLVCONF = optarg;
  535.         break;
  536.       // override default subdomain file
  537.       case 's':
  538.         SUBDOMAINS = optarg;
  539.         break;
  540.       // set the domain
  541.       case 'd':
  542.         domain = optarg;
  543.         break;
  544.       // set the IP range (if doing reverse scan)
  545.       case 'i':
  546.         range = optarg;
  547.         break;
  548.       default:
  549.         usage();
  550.     }
  551.   }
  552.  
  553.   // make sure a domain is set
  554.   if(!domain) usage();
  555.  
  556.   // retreive name servers
  557.   parse_resolv_conf();
  558.   // make sure subdomains file exists
  559.   if(!fopen(SUBDOMAINS, "r")) error("[!] Error opening: %s", SUBDOMAINS);
  560.  
  561.   if(!fork()) {
  562.     // do a reverse search or a forward search
  563.     if(range) {
  564.       reverse_search(range);
  565.     } else {
  566.       forward_brute(domain);
  567.     }
  568.   } else {
  569.     // spawn the sniffer
  570.     sniff_dns_replies(domain);
  571.   }
Add Comment
Please, Sign In to add comment