C   27
dnstcp buggy
Guest on 16th March 2023 01:23:18 PM


  1. /*
  2.  * Example of client using TCP protocol, adapted from
  3.  *   "Unix Network Programming", 1st ed.
  4.  */
  5.  
  6. #include  <stdio.h>
  7. #include  <sys/types.h>
  8. #include  <sys/socket.h>
  9. #include  <netinet/in.h>
  10. #include  <arpa/inet.h>
  11.  
  12. #include  <stdio.h>
  13. #include  <strings.h> // bzero
  14. #include  <string.h>  // strncpy
  15. #include  <stdlib.h>  // exit
  16. #include  <unistd.h>  // close
  17.  
  18. #include <stdint.h>   // uint8_t
  19.  
  20. int print_dns_name(char *, char *);
  21.  
  22. #define SERV_TCP_PORT   53
  23. #define SERV_HOST_ADDR  "129.170.170.2"
  24.  
  25. // Pasted from Wireshark's "Analyze > Follow > TCP stream",
  26. //  generated by "dig +tcp a cs60.cs.dartmouth.edu"
  27. // Note: unlike a UDP payload, this one has a two-byte
  28. //  length field up front, 0x00 0x27 = 39 bytes after
  29. //  the length field, 41 bytes all told.
  30. char req[] = {
  31.      0x00, 0x27, 0x1d, 0x62, 0x01, 0x00, 0x00, 0x01,
  32.      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x63,
  33.      0x73, 0x36, 0x30, 0x02, 0x63, 0x73, 0x09, 0x64,
  34.      0x61, 0x72, 0x74, 0x6d, 0x6f, 0x75, 0x74, 0x68,
  35.      0x03, 0x65, 0x64, 0x75, 0x00, 0x00, 0x01, 0x00,
  36.      0x01 };
  37.  
  38. #define MAX_MSG 1500
  39.  
  40. typedef struct tcp_dns_resp_hdr {
  41.      uint16_t len;    // not there in UDP payloads!
  42.      uint16_t tx_id;
  43.      uint8_t  flags[2];
  44.      uint16_t n_q;
  45.      uint16_t n_a;
  46.      uint16_t n_auth;
  47.      uint16_t n_add;
  48. } tcp_dns_resp_hdr_t;
  49.  
  50. int main(argc, argv)
  51. int     argc;
  52. char    *argv[];
  53. {
  54.      int sockfd;
  55.      struct sockaddr_in serv_addr;
  56.  
  57.      char buff[1500];
  58.      int n, i;
  59.  
  60.      uint16_t type, class, data_len;
  61.      uint32_t ttl;
  62.  
  63.      tcp_dns_resp_hdr_t *r;
  64.  
  65.      char *p;
  66.  
  67.      /*
  68.       * Fill in the structure "serv_addr" with the address of the
  69.       * server that we want to connect with.
  70.       */
  71.      
  72.      bzero((char *) &serv_addr, sizeof(serv_addr));
  73.      serv_addr.sin_family      = AF_INET;
  74.      serv_addr.sin_addr.s_addr = inet_addr(SERV_HOST_ADDR);
  75.      serv_addr.sin_port        = htons(SERV_TCP_PORT);
  76.      
  77.      /*
  78.       * Open a TCP socket (an Internet stream socket).
  79.       */
  80.      
  81.      if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
  82.           perror("tcp client: can't open stream socket");
  83.           exit(1);
  84.      }
  85.  
  86.      /*
  87.       * Connect to the server.
  88.       */
  89.      
  90.      if (connect(sockfd, (struct sockaddr *) &serv_addr,
  91.                  sizeof(serv_addr)) < 0){
  92.           perror("tcp client: can't connect to server");
  93.           exit(1);
  94.      }
  95.      
  96.      //send(sockfd, (void*) msg, MSG_LEN, 0);
  97.      write(sockfd, (void*) req, sizeof(req));
  98.      
  99.      n = recv(sockfd, (void*) buff, MAX_MSG, 0);
  100.      if( n < 0 ){
  101.           perror("Truncated response received.");
  102.           goto out;
  103.      }
  104.  
  105.      r = (tcp_dns_resp_hdr_t *) buff;
  106.      printf( "Response length: %d\n", ntohs(r->len) );
  107.  
  108.      // Print the packet bytes as received
  109.      for (i = 0; i < n; i++) {
  110.           printf("%02X%s", (uint8_t)buff[i], (i + 1)%16 ? " " : "\n");
  111.      }
  112.      printf("\n");
  113.  
  114.      // Print the common DNS header
  115.      printf("tx_id 0x%x, flags %02X %02X, questions %d, answers %d, authorities %d, additional %d\n",
  116.             ntohs(r->tx_id), r->flags[0], r->flags[1], ntohs(r->n_q), ntohs(r->n_a), ntohs(r->n_auth), ntohs(r->n_add) );
  117.      
  118.      p = buff + sizeof(tcp_dns_resp_hdr_t);
  119.  
  120.      for( i = 0 ; i < ntohs(r->n_q); i++ ){
  121.           // parse RR starting from name
  122.           printf( "Query RR name: " );    
  123.           p += print_dns_name( p, buff+2 );
  124.          
  125.           // then print type and class
  126.           type = ntohs( *(uint16_t *)p );
  127.           p += 2;
  128.           class = ntohs (*(uint16_t *)p );
  129.           p += 2;
  130.           printf( "  type %d, class %d\n", type, class );
  131.      }  
  132.      // Print answers
  133.      for( i = 0 ; i < ntohs(r->n_a); i++ ){
  134.           // parse RR starting from name
  135.           printf( "Answer RR name: " );    
  136.           p += print_dns_name(p, buff+2);
  137.  
  138.           type = ntohs( *(uint16_t *)p );
  139.           p += 2;
  140.           class = ntohs (*(uint16_t *)p );
  141.           p += 2;
  142.           printf( "  type %d, class %d\n", type, class );
  143.  
  144.           ttl = ntohs( *(uint32_t *)p );
  145.           p += 4;
  146.  
  147.           data_len = ntohs( *(uint16_t *)p );
  148.           p += 2;
  149.           printf( "  ttl %d, data_len %d ", ttl, data_len );
  150.  
  151.           // Data interpretation varies by type
  152.           if( type == 1 && data_len == 4){
  153.                printf( " %s\n", inet_ntoa( *(struct in_addr*) p ));
  154.                p += 4;
  155.           }
  156.           else if( type == 2 ){
  157.                print_dns_name( p, buff );
  158.           }
  159.           else{
  160.                printf( "WARN: don't know how to parse RR data for type %d length %d\n", type, data_len);
  161.           }
  162.          
  163.           p += data_len;
  164.  
  165.      } // done printing answers
  166.      for( i = 0 ; i < ntohs(r->n_auth); i++ ){
  167.           printf( "Skipping authority RR: not implemented\n");
  168.      }
  169.      for( i = 0 ; i < ntohs(r->n_add); i++ ){
  170.           printf( "Skipping additional RR: not implemented\n");
  171.      }
  172.  
  173. out:
  174.      close(sockfd);
  175.      return 0;
  176. }
  177.  
  178. /*
  179.  * Args: pointer to a DNS-encoded name (or backreference), pointer to
  180.  *   the start of the DNS payload (to resolve backreferences).
  181.  * Returns: the number of bytes occupied by the name, to skip over.
  182.  */
  183. int print_dns_name(char *p, char *buff)
  184. {
  185.      char *p0 = p;
  186.      int8_t len  = *(uint8_t*)p;
  187.      p++;
  188.  
  189.      // write out parts of the name from this record
  190.      while( len > 0 ){
  191.           fwrite( p, len, 1, stdout );
  192.           printf(".");
  193.           p += len;
  194.           len = *(uint8_t*)p;
  195.           p++;
  196.      }
  197.      // at this point we either hit len==0 (the end of name)
  198.      //  or a negative back-pointer
  199.  
  200.      if( len < 0 ){ // back-pointer, starts with 0xc0
  201.           uint16_t offset;
  202.           offset = ntohs(*(uint16_t *)(p-1)) & ~0xc000;  // scan back one byte
  203.           printf( "<backref offset %d>", offset );
  204.           print_dns_name( buff+offset, buff ); // ignore return value
  205.           printf("\n");
  206.           p += 1; // skip offset
  207.      }
  208.  
  209.      return p-p0;
  210. }

Raw Paste

Login or Register to edit or fork this paste. It's free.