lost and found ( for me ? )

Python scapy: generate DNS queries from a pcap file collected with tcpdump

Here is sample scapy script how to generate UDP DNS queries from a pcap file collected with tcpdump.

Prepare a pcap file ( capture only resolvers -> DNS servers packet )
Please note that this script can not read a pcap file collected with wireshark.
# file tcpdump_dns_queries.pcap
tcpdump_dns_queries.pcap: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 500)

# tcpdump -r tcpdump_dns_queries.pcap  -n | head -10
reading from file tcpdump_dns_queries.pcap, link-type EN10MB (Ethernet)
18:27:31.733097 IP 192.168.27.17.40930 > 192.168.122.127.53: 16978 SOA? 1zznbxb487.wue.bar.com. (40)
18:27:31.763683 IP 192.168.27.18.13962 > 192.168.122.127.53: 30924 NS? gx42ilp0sc.iqu.bar.com. (40)
18:27:31.778066 IP 192.168.27.19.15052 > 192.168.122.127.53: 60958 SOA? 2wnwtq8eo7.mx2.bar.com. (40)
18:27:31.786013 IP 192.168.27.20.50300 > 192.168.122.127.53: 28299 SOA? n3prpfvea7.pqj.bar.com. (40)

Here is sample script
scapy can not generate some qury types, e.g. ANY.
If there are query types in the pcap file which scapy can not generate, scapy will use qury type A.
# cat generate_DNS_from_cap.py –n
    1  #!/usr/bin/env python
    2
    3  ###
    4  # Usage: python generate_DNS_from_cap.py pcap_file targetIP device_name
    5  ###
    6
    7  from scapy.all import *
    8  import sys
    9
   10  # check number of arguments
   11  argvs = sys.argv
   12  argc = len(argvs)
   13  if (argc != 4):
   14          print 'Usage # python %s pcap_file dstip device_name' % argvs[0]
   15          quit()
   16
   17  # load a cap file
   18  pkts = rdpcap(argvs[1])
   19
   20  dstip = argvs[2]
   21  nic = argvs[3]
   22
   23  # define query type
   24  type_lists = { 0:"ANY", 255:"ALL",1:"A", 2:"NS", 3:"MD", 4:"MD", 5:"CNAME", 6:"SOA", 7: "MB",8:"MG",9:"MR",10:"NULL",11:"WKS",12:"PTR",13:"HINFO",14:"MINFO",15:"MX",16:"TXT",17:"RP",18:"AFSDB",28:"AAAA", 33:"SRV",38:"A6",39:"DNAME"}
   25
   26  # define class
   27  class_lists = {1: 'IN', 2: 'CS', 3: 'CH', 4: 'HS', 255: 'ANY'}
   28
   29  # build DNS packets from the pcap file and generate DNS queries
   30  for i in range(0,len(pkts)):
   31          # IP protocol or not
   32          if 2048 == pkts[i][Ether].type:
   33
   34                  # UDP packet or not
   35                  if 17 == pkts[i][IP].proto:
   36
   37                          # Dst port 53 or not
   38                          if 53 == pkts[i][UDP].dport:
   39
   40                                  # chek qtype is in the qtype_lists
   41                                  if pkts[i][UDP][DNS][DNSQR].qtype in [0,255,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,28,33,38,39]:
   42                                          srcip = pkts[i][IP].src
   43                                          #dstip = pkts[i][IP].dst
   44                                          txid=pkts[i][IP][DNS].id
   45                                          query_name=pkts[i][DNS][DNSQR].qname
   46                                          query_type=type_lists[pkts[i][DNS][DNSQR].qtype]
   47                                          query_class=class_lists[pkts[i][DNS][DNSQR].qclass]
   48
   49                                          sr1(IP(src="%s" % srcip,dst="%s" % dstip)/UDP(sport=RandShort(), dport=53)/DNS(rd=1,qd=DNSQR(qname="%s" % query_name,qtype="%s" % query_type,qclass="IN")),iface="%s" % nic,retry=False,timeout=0.1,verbose=False)
   50
   51                                  # if qtypes is not in the list, send A DNS queries
   52                                  else:
   53                                          srcip = pkts[i][IP].src
   54                                          #dstip = pkts[i][IP].dst
   55                                          txid=pkts[i][IP][DNS].id
   56                                          query_name=pkts[i][DNS][DNSQR].qname
   57                                          query_type=1
   58                                          query_class=class_lists[pkts[i][DNS][DNSQR].qclass]
   59                                          sr1(IP(src="%s" % srcip,dst="%s" % dstip)/UDP(sport=RandShort(), dport=53)/DNS(rd=1,qd=DNSQR(qname="%s" % query_name,qtype="%s" % query_type,qclass="IN")),iface="%s" % nic,retry=False,timeout=0.1,verbose=False)
   60
   61          # not DNS packet
   62          else:
   63                  pass

Let’s run the script.

Usage: python generate_DNS_from_cap.py pcap_file targetIP device_name

DNS queries are sent from pcap file’s source IPs, which means that this script generate DNS with spoofed IPs.

You can specify a pcap file name, target IP and which device you want to use.

run the script
# ./generate_DNS_from_cap.py tcpdump_dns_queries.pcap 192.168.10.11 eth0

on the target server
# tshark -i eth0 port 53
Running as user "root" and group "root". This could be dangerous.
Capturing on eth0
 0.000000 192.168.30.67 -> 192.168.10.11 DNS Standard query A 22uuwtmm6u.o7y.bar.com
 0.156157 192.168.30.68 -> 192.168.10.11 DNS Standard query NS ox1pvj1rl7.mfc.bar.com
 0.289077 192.168.30.69 -> 192.168.10.11 DNS Standard query SOA zmtxb7lenf.ixk.bar.com
 0.426993 192.168.30.70 -> 192.168.10.11 DNS Standard query SOA 3j1efgk8sd.7dj.bar.com
 0.587145 192.168.30.71 -> 192.168.10.11 DNS Standard query A hxdbbj9a52.qeu.bar.com
 0.724314 192.168.30.72 -> 192.168.10.11 DNS Standard query AAAA 5bbt7hd1a8.ghr.bar.com
 0.872228 192.168.30.73 -> 192.168.10.11 DNS Standard query AAAA d18nxdpj2t.mdy.bar.com
 1.004146 192.168.30.74 -> 192.168.10.11 DNS Standard query SOA 141jo097n9.gxp.bar.com
 1.136820 192.168.30.75 -> 192.168.10.11 DNS Standard query MX 16y1tmxbgj.9zr.bar.com

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.