diff options
author | 2016-03-21 16:03:47 +0200 | |
---|---|---|
committer | 2016-03-21 16:03:47 +0200 | |
commit | b89efa188810bf95a9d245e69e2961b5721c3b0f (patch) | |
tree | 454273ac6c4ae972ebb8a2c86b893296970b4fa9 /scripts/external_libs/scapy-2.3.1/python3/scapy/layers/dns.py | |
parent | f72c6df9d2e9998ae1f3529d729ab7930b35785a (diff) |
scapy python 2/3
Diffstat (limited to 'scripts/external_libs/scapy-2.3.1/python3/scapy/layers/dns.py')
-rw-r--r-- | scripts/external_libs/scapy-2.3.1/python3/scapy/layers/dns.py | 712 |
1 files changed, 712 insertions, 0 deletions
diff --git a/scripts/external_libs/scapy-2.3.1/python3/scapy/layers/dns.py b/scripts/external_libs/scapy-2.3.1/python3/scapy/layers/dns.py new file mode 100644 index 00000000..8a01e273 --- /dev/null +++ b/scripts/external_libs/scapy-2.3.1/python3/scapy/layers/dns.py @@ -0,0 +1,712 @@ +## This file is part of Scapy +## See http://www.secdev.org/projects/scapy for more informations +## Copyright (C) Philippe Biondi <phil@secdev.org> +## This program is published under a GPLv2 license + +""" +DNS: Domain Name System. +""" + +import socket,struct + +from scapy.packet import * +from scapy.fields import * +from scapy.ansmachine import * +from scapy.layers.inet import IP, UDP +from scapy.utils import str2bytes + +class DNSStrField(StrField): + + def h2i(self, pkt, x): + if type(x) == str: + x = x.encode('ascii') + if x == b"": + return b"." + return x + + def i2m(self, pkt, x): + if type(x) == str: + x = x.encode('ascii') + if x == b".": + return b"\x00" + + x = [k[:63] for k in x.split(b".")] # Truncate chunks that cannot be encoded (more than 63 bytes..) + x = map(lambda y: bytes([len(y)]) + y, x) + x = b"".join(x) + if x[-1] != 0: + x += b"\x00" + return x + + def getfield(self, pkt, s): + n = b"" + + #if ord(s[0]) == 0: + if (s[0]) == 0: + return s[1:], b"." + + while 1: + #l = ord(s[0]) + l = (s[0]) + s = s[1:] + if not l: + break + if l & 0xc0: + raise Scapy_Exception("DNS message can't be compressed at this point!") + else: + n += s[:l]+b"." + s = s[l:] + return s, n + + +class DNSRRCountField(ShortField): + holds_packets=1 + def __init__(self, name, default, rr): + ShortField.__init__(self, name, default) + self.rr = rr + def _countRR(self, pkt): + x = getattr(pkt,self.rr) + i = 0 + while isinstance(x, DNSRR) or isinstance(x, DNSQR) or isdnssecRR(x): + x = x.payload + i += 1 + return i + + def i2m(self, pkt, x): + if x is None: + x = self._countRR(pkt) + return x + def i2h(self, pkt, x): + if x is None: + x = self._countRR(pkt) + return x + + +def DNSgetstr(s,p): + name = b"" + q = 0 + jpath = [p] + while 1: + if p >= len(s): + warning("DNS RR prematured end (ofs=%i, len=%i)"%(p,len(s))) + break + #l = ord(s[p]) + l = s[p] + p += 1 + if l & 0xc0: + if not q: + q = p+1 + if p >= len(s): + warning("DNS incomplete jump token at (ofs=%i)" % p) + break + p = ((l & 0x3f) << 8) + s[p] - 12 + if p in jpath: + warning("DNS decompression loop detected") + break + jpath.append(p) + continue + elif l > 0: + name += s[p:p+l]+b"." + p += l + continue + break + if q: + p = q + return name,p + + +class DNSRRField(StrField): + holds_packets=1 + def __init__(self, name, countfld, passon=1): + StrField.__init__(self, name, None) + self.countfld = countfld + self.passon = passon + def i2m(self, pkt, x): + if x is None: + return b"" + return bytes(x) + def decodeRR(self, name, s, p): + ret = s[p:p+10] + type,cls,ttl,rdlen = struct.unpack("!HHIH", ret) + p += 10 + rr = DNSRR(b"\x00"+ret+s[p:p+rdlen]) + if type in [2, 3, 4, 5]: + rr.rdata = DNSgetstr(s,p)[0] + del(rr.rdlen) + elif type in dnsRRdispatcher.keys(): + rr = dnsRRdispatcher[type](b"\x00"+ret+s[p:p+rdlen]) + else: + del(rr.rdlen) + + p += rdlen + + rr.rrname = name + return rr,p + def getfield(self, pkt, s): + if type(s) is tuple : + s,p = s + else: + p = 0 + ret = None + c = getattr(pkt, self.countfld) + if c > len(s): + warning("wrong value: DNS.%s=%i" % (self.countfld,c)) + return s,b"" + while c: + c -= 1 + name,p = DNSgetstr(s,p) + rr,p = self.decodeRR(name, s, p) + if ret is None: + ret = rr + else: + ret.add_payload(rr) + if self.passon: + return (s,p),ret + else: + return s[p:],ret + + +class DNSQRField(DNSRRField): + holds_packets=1 + def decodeRR(self, name, s, p): + ret = s[p:p+4] + p += 4 + rr = DNSQR(b"\x00"+ret) + rr.qname = name + return rr,p + + + +class RDataField(StrLenField): + def m2i(self, pkt, s): + family = None + if pkt.type == 1: # A + family = socket.AF_INET + elif pkt.type == 12: # PTR + s = DNSgetstr(s, 0)[0] + elif pkt.type == 16: # TXT + ret_s = b"" + tmp_s = s + # RDATA contains a list of strings, each are prepended with + # a byte containing the size of the following string. + while tmp_s: + tmp_len = struct.unpack("!B", bytes([tmp_s[0]]))[0] + 1 + if tmp_len > len(tmp_s): + warning("DNS RR TXT prematured end of character-string (size=%i, remaining bytes=%i)" % (tmp_len, len(tmp_s))) + ret_s += tmp_s[1:tmp_len] + tmp_s = tmp_s[tmp_len:] + s = ret_s + elif pkt.type == 28: # AAAA + family = socket.AF_INET6 + if family is not None: + s = inet_ntop(family, s) + return s + def i2m(self, pkt, s): + if pkt.type == 1: # A + if s: + if type(s) is bytes: + s = s.decode('ascii') + s = inet_aton(s) + elif pkt.type in [2,3,4,5]: # NS, MD, MF, CNAME + s = b"".join(map(lambda x: bytes([len(x)]) + x, s.split(b"."))) + #if ord(s[-1]): + if s[-1]: + s += b"\x00" + elif pkt.type == 16: # TXT + if s: + ret_s = b"" + # The initial string must be splitted into a list of strings + # prepended with theirs sizes. + while len(s) >= 255: + ret_s += b"\xff" + s[:255] + s = s[255:] + # The remaining string is less than 255 bytes long + if len(s): + ret_s += struct.pack("!B", len(s)) + s + s = ret_s + elif pkt.type == 28: # AAAA + if s: + s = inet_pton(socket.AF_INET6, s) + return s + +class RDLenField(Field): + def __init__(self, name): + Field.__init__(self, name, None, "H") + def i2m(self, pkt, x): + if x is None: + rdataf = pkt.get_field("rdata") + x = len(rdataf.i2m(pkt, pkt.rdata)) + return x + def i2h(self, pkt, x): + if x is None: + rdataf = pkt.get_field("rdata") + x = len(rdataf.i2m(pkt, pkt.rdata)) + return x + + +class DNS(Packet): + name = "DNS" + fields_desc = [ ShortField("id", 0), + BitField("qr", 0, 1), + BitEnumField("opcode", 0, 4, {0:"QUERY",1:"IQUERY",2:"STATUS"}), + BitField("aa", 0, 1), + BitField("tc", 0, 1), + BitField("rd", 0, 1), + BitField("ra", 0, 1), + BitField("z", 0, 1), + # AD and CD bits are defined in RFC 2535 + BitField("ad", 0, 1), # Authentic Data + BitField("cd", 0, 1), # Checking Disabled + BitEnumField("rcode", 0, 4, {0:"ok", 1:"format-error", 2:"server-failure", 3:"name-error", 4:"not-implemented", 5:"refused"}), + DNSRRCountField("qdcount", None, "qd"), + DNSRRCountField("ancount", None, "an"), + DNSRRCountField("nscount", None, "ns"), + DNSRRCountField("arcount", None, "ar"), + DNSQRField("qd", "qdcount"), + DNSRRField("an", "ancount"), + DNSRRField("ns", "nscount"), + DNSRRField("ar", "arcount",0) ] + def answers(self, other): + return (isinstance(other, DNS) + and self.id == other.id + and self.qr == 1 + and other.qr == 0) + + def mysummary(self): + type = ["Qry","Ans"][self.qr] + name = "" + if self.qr: + type = "Ans" + if self.ancount > 0 and isinstance(self.an, DNSRR): + name = ' "%s"' % self.an.getstrval("rdata") + else: + type = "Qry" + if self.qdcount > 0 and isinstance(self.qd, DNSQR): + name = ' "%s"' % self.qd.getstrval("qname") + return 'DNS %s%s ' % (type, name) + +dnstypes = { 0:"ANY", 255:"ALL", + 1:"A", 2:"NS", 3:"MD", 4:"MF", 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", + 41:"OPT", 43:"DS", 46:"RRSIG", 47:"NSEC", 48:"DNSKEY", + 50: "NSEC3", 51: "NSEC3PARAM", 32769:"DLV" } + +dnsqtypes = {251:"IXFR",252:"AXFR",253:"MAILB",254:"MAILA",255:"ALL"} +dnsqtypes.update(dnstypes) +dnsclasses = {1: 'IN', 2: 'CS', 3: 'CH', 4: 'HS', 255: 'ANY'} + + +class DNSQR(Packet): + name = "DNS Question Record" + show_indent=0 + fields_desc = [ DNSStrField("qname",b""), + ShortEnumField("qtype", 1, dnsqtypes), + ShortEnumField("qclass", 1, dnsclasses) ] + + + +# RFC 2671 - Extension Mechanisms for DNS (EDNS0) + +class EDNS0TLV(Packet): + name = "DNS EDNS0 TLV" + fields_desc = [ ShortEnumField("optcode", 0, { 0: "Reserved", 1: "LLQ", 2: "UL", 3: "NSID", 4: "Reserved", 5: "PING" }), + FieldLenField("optlen", None, "optdata", fmt="H"), + StrLenField("optdata", b"", length_from=lambda pkt: pkt.optlen) ] + + def extract_padding(self, p): + return b"", p + +class DNSRROPT(Packet): + name = "DNS OPT Resource Record" + fields_desc = [ DNSStrField("rrname",b""), + ShortEnumField("type", 41, dnstypes), + ShortField("rclass", 4096), + ByteField("extrcode", 0), + ByteField("version", 0), + # version 0 means EDNS0 + BitEnumField("z", 32768, 16, { 32768: "D0" }), + # D0 means DNSSEC OK from RFC 3225 + FieldLenField("rdlen", None, length_of="rdata", fmt="H"), + PacketListField("rdata", [], EDNS0TLV, length_from=lambda pkt: pkt.rdlen) ] + +# RFC 4034 - Resource Records for the DNS Security Extensions + +# 09/2013 from http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml +dnssecalgotypes = { 0:"Reserved", 1:"RSA/MD5", 2:"Diffie-Hellman", 3:"DSA/SHA-1", + 4:"Reserved", 5:"RSA/SHA-1", 6:"DSA-NSEC3-SHA1", + 7:"RSASHA1-NSEC3-SHA1", 8:"RSA/SHA-256", 9:"Reserved", + 10:"RSA/SHA-512", 11:"Reserved", 12:"GOST R 34.10-2001", + 13:"ECDSA Curve P-256 with SHA-256", 14: "ECDSA Curve P-384 with SHA-384", + 252:"Reserved for Indirect Keys", 253:"Private algorithms - domain name", + 254:"Private algorithms - OID", 255:"Reserved" } + +# 09/2013 from http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml +dnssecdigesttypes = { 0:"Reserved", 1:"SHA-1", 2:"SHA-256", 3:"GOST R 34.11-94", 4:"SHA-384" } + + +class TimeField(IntField): + + def any2i(self, pkt, x): + if type(x) == str: + import time, calendar + t = time.strptime(x, "%Y%m%d%H%M%S") + return int(calendar.timegm(t)) + return x + + def i2repr(self, pkt, x): + import time + x = self.i2h(pkt, x) + t = time.strftime("%Y%m%d%H%M%S", time.gmtime(x)) + return "%s (%d)" % (t ,x) + + +def bitmap2RRlist(bitmap): + """ + Decode the 'Type Bit Maps' field of the NSEC Resource Record into an + integer list. + """ + # RFC 4034, 4.1.2. The Type Bit Maps Field + + RRlist = [] + + while bitmap: + + if len(bitmap) < 2: + warning("bitmap too short (%i)" % len(bitmap)) + return + + #window_block = ord(bitmap[0]) # window number + window_block = (bitmap[0]) # window number + offset = 256*window_block # offset of the Ressource Record + #bitmap_len = ord(bitmap[0]) # length of the bitmap in bytes + bitmap_len = (bitmap[1]) # length of the bitmap in bytes + + if bitmap_len <= 0 or bitmap_len > 32: + warning("bitmap length is no valid (%i)" % bitmap_len) + return + + tmp_bitmap = bitmap[2:2+bitmap_len] + + # Let's compare each bit of tmp_bitmap and compute the real RR value + for b in range(len(tmp_bitmap)): + v = 128 + for i in range(8): + #if ord(tmp_bitmap[b]) & v: + if (tmp_bitmap[b]) & v: + # each of the RR is encoded as a bit + RRlist += [ offset + b*8 + i ] + v = v >> 1 + +# Next block if any + bitmap = bitmap[2+bitmap_len:] + + return RRlist + + +def RRlist2bitmap(lst): + """ + Encode a list of integers representing Resource Records to a bitmap field + used in the NSEC Resource Record. + """ + # RFC 4034, 4.1.2. The Type Bit Maps Field + + import math + + bitmap = b"" + lst = list(set(lst)) + lst.sort() + + #lst = filter(lambda x: x <= 65535, lst) + #lst = map(lambda x: abs(x), lst) + lst = [ abs(x) for x in lst if x<= 65535 ] + + # number of window blocks + max_window_blocks = int(math.ceil(lst[-1] / 256.)) + min_window_blocks = int(math.floor(lst[0] / 256.)) + if min_window_blocks == max_window_blocks: + max_window_blocks += 1 + + for wb in range(min_window_blocks, max_window_blocks+1): + # First, filter out RR not encoded in the current window block + # i.e. keep everything between 256*wb <= 256*(wb+1) + #rrlist = filter(lambda x: 256*wb <= x and x < 256*(wb+1), lst) + rrlist = [ x for x in lst if 256*wb <= x and x < 256*(wb+1) ] + rrlist.sort() + if rrlist == []: + continue + + # Compute the number of bytes used to store the bitmap + if rrlist[-1] == 0: # only one element in the list + bs = 1 + else: + max = rrlist[-1] - 256*wb + #bs = int(math.ceil(max / 8)) + 1 # use at least 1 byte + bs = int(max // 8) + 1 # use at least 1 byte + if bs > 32: # Don't encode more than 256 bits / values + bs = 32 + + bitmap += struct.pack("B", wb) + bitmap += struct.pack("B", bs) + + # Generate the bitmap + for tmp in range(bs): + v = 0 + # Remove out of range Ressource Records + #tmp_rrlist = filter(lambda x: 256*wb+8*tmp <= x and x < 256*wb+8*tmp+8, rrlist) + tmp_rrlist = [ x for x in rrlist if 256*wb+8*tmp <= x and x < 256*wb+8*tmp+8 ] + if not tmp_rrlist == []: + # 1. rescale to fit into 8 bits + tmp_rrlist = map(lambda x: (x-256*wb)-(tmp*8), tmp_rrlist) + # 2. x gives the bit position ; compute the corresponding value + tmp_rrlist = map(lambda x: 2**(7-x) , tmp_rrlist) + # 3. sum everything + #v = reduce(lambda x,y: x+y, tmp_rrlist) + v = sum(tmp_rrlist) + bitmap += struct.pack("B", v) + + return bitmap + + +class RRlistField(StrField): + def h2i(self, pkt, x): + if type(x) == list: + return RRlist2bitmap(x) + return x + + def i2repr(self, pkt, x): + x = self.i2h(pkt, x) + rrlist = bitmap2RRlist(x) + return [ dnstypes.get(rr, rr) for rr in rrlist ] + + +class _DNSRRdummy(Packet): + name = "Dummy class that implements post_build() for Ressource Records" + def post_build(self, pkt, pay): + if not self.rdlen == None: + return pkt + + lrrname = len(self.fields_desc[0].i2m(b"", self.getfieldval("rrname"))) + l = len(pkt) - lrrname - 10 + pkt = pkt[:lrrname+8] + struct.pack("!H", l) + pkt[lrrname+8+2:] + + return pkt + +class DNSRRSOA(_DNSRRdummy): + name = "DNS SOA Resource Record" + fields_desc = [ DNSStrField("rrname",b""), + ShortEnumField("type", 6, dnstypes), + ShortEnumField("rclass", 1, dnsclasses), + IntField("ttl", 0), + ShortField("rdlen", None), + DNSStrField("mname", b""), + DNSStrField("rname", b""), + IntField("serial", 0), + IntField("refresh", 0), + IntField("retry", 0), + IntField("expire", 0), + IntField("minimum", 0) + ] + +class DNSRRRSIG(_DNSRRdummy): + name = "DNS RRSIG Resource Record" + fields_desc = [ DNSStrField("rrname",b""), + ShortEnumField("type", 46, dnstypes), + ShortEnumField("rclass", 1, dnsclasses), + IntField("ttl", 0), + ShortField("rdlen", None), + ShortEnumField("typecovered", 1, dnstypes), + ByteEnumField("algorithm", 5, dnssecalgotypes), + ByteField("labels", 0), + IntField("originalttl", 0), + TimeField("expiration", 0), + TimeField("inception", 0), + ShortField("keytag", 0), + DNSStrField("signersname", b""), + StrField("signature", b"") + ] + + +class DNSRRNSEC(_DNSRRdummy): + name = "DNS NSEC Resource Record" + fields_desc = [ DNSStrField("rrname",b""), + ShortEnumField("type", 47, dnstypes), + ShortEnumField("rclass", 1, dnsclasses), + IntField("ttl", 0), + ShortField("rdlen", None), + DNSStrField("nextname", b""), + RRlistField("typebitmaps", b"") + ] + + +class DNSRRDNSKEY(_DNSRRdummy): + name = "DNS DNSKEY Resource Record" + fields_desc = [ DNSStrField("rrname",b""), + ShortEnumField("type", 48, dnstypes), + ShortEnumField("rclass", 1, dnsclasses), + IntField("ttl", 0), + ShortField("rdlen", None), + FlagsField("flags", 256, 16, "S???????Z???????"), + # S: Secure Entry Point + # Z: Zone Key + ByteField("protocol", 3), + ByteEnumField("algorithm", 5, dnssecalgotypes), + StrField("publickey", b"") + ] + + +class DNSRRDS(_DNSRRdummy): + name = "DNS DS Resource Record" + fields_desc = [ DNSStrField("rrname",b""), + ShortEnumField("type", 43, dnstypes), + ShortEnumField("rclass", 1, dnsclasses), + IntField("ttl", 0), + ShortField("rdlen", None), + ShortField("keytag", 0), + ByteEnumField("algorithm", 5, dnssecalgotypes), + ByteEnumField("digesttype", 5, dnssecdigesttypes), + StrField("digest", b"") + ] + + +# RFC 5074 - DNSSEC Lookaside Validation (DLV) +class DNSRRDLV(DNSRRDS): + name = "DNS DLV Resource Record" + def __init__(self, *args, **kargs): + DNSRRDS.__init__(self, *args, **kargs) + if not kargs.get('type', 0): + self.type = 32769 + +# RFC 5155 - DNS Security (DNSSEC) Hashed Authenticated Denial of Existence +class DNSRRNSEC3(_DNSRRdummy): + name = "DNS NSEC3 Resource Record" + fields_desc = [ DNSStrField("rrname",b""), + ShortEnumField("type", 50, dnstypes), + ShortEnumField("rclass", 1, dnsclasses), + IntField("ttl", 0), + ShortField("rdlen", None), + ByteField("hashalg", 0), + BitEnumField("flags", 0, 8, {1:"Opt-Out"}), + ShortField("iterations", 0), + FieldLenField("saltlength", 0, fmt="!B", length_of="salt"), + StrLenField("salt", b"", length_from=lambda x: x.saltlength), + FieldLenField("hashlength", 0, fmt="!B", length_of="nexthashedownername"), + StrLenField("nexthashedownername", b"", length_from=lambda x: x.hashlength), + RRlistField("typebitmaps", b"") + ] + + +class DNSRRNSEC3PARAM(_DNSRRdummy): + name = "DNS NSEC3PARAM Resource Record" + fields_desc = [ DNSStrField("rrname",b""), + ShortEnumField("type", 51, dnstypes), + ShortEnumField("rclass", 1, dnsclasses), + IntField("ttl", 0), + ShortField("rdlen", None), + ByteField("hashalg", 0), + ByteField("flags", 0), + ShortField("iterations", 0), + FieldLenField("saltlength", 0, fmt="!B", length_of="salt"), + StrLenField("salt", b"", length_from=lambda pkt: pkt.saltlength) + ] + + +dnssecclasses = [ DNSRROPT, DNSRRRSIG, DNSRRDLV, DNSRRDNSKEY, DNSRRNSEC, DNSRRDS, DNSRRNSEC3, DNSRRNSEC3PARAM ] + +def isdnssecRR(obj): + list = [ isinstance (obj, cls) for cls in dnssecclasses ] + ret = False + for i in list: + ret = ret or i + return ret + +dnsRRdispatcher = { #6: DNSRRSOA, + 41: DNSRROPT, # RFC 1671 + 43: DNSRRDS, # RFC 4034 + 46: DNSRRRSIG, # RFC 4034 + 47: DNSRRNSEC, # RFC 4034 + 48: DNSRRDNSKEY, # RFC 4034 + 50: DNSRRNSEC3, # RFC 5155 + 51: DNSRRNSEC3PARAM, # RFC 5155 + 32769: DNSRRDLV # RFC 4431 + } + +class DNSRR(Packet): + name = "DNS Resource Record" + show_indent=0 + fields_desc = [ DNSStrField("rrname",""), + ShortEnumField("type", 1, dnstypes), + ShortEnumField("rclass", 1, dnsclasses), + IntField("ttl", 0), + RDLenField("rdlen"), + RDataField("rdata", "", length_from=lambda pkt:pkt.rdlen) ] + +bind_layers( UDP, DNS, dport=53) +bind_layers( UDP, DNS, sport=53) + + +@conf.commands.register +def dyndns_add(nameserver, name, rdata, type="A", ttl=10): + """Send a DNS add message to a nameserver for "name" to have a new "rdata" +dyndns_add(nameserver, name, rdata, type="A", ttl=10) -> result code (0=ok) + +example: dyndns_add("ns1.toto.com", "dyn.toto.com", "127.0.0.1") +RFC2136 +""" + zone = name[name.find(".")+1:] + r=sr1(IP(dst=nameserver)/UDP()/DNS(opcode=5, + qd=[DNSQR(qname=zone, qtype="SOA")], + ns=[DNSRR(rrname=name, type="A", + ttl=ttl, rdata=rdata)]), + verbose=0, timeout=5) + if r and r.haslayer(DNS): + return r.getlayer(DNS).rcode + else: + return -1 + + + + +@conf.commands.register +def dyndns_del(nameserver, name, type="ALL", ttl=10): + """Send a DNS delete message to a nameserver for "name" +dyndns_del(nameserver, name, type="ANY", ttl=10) -> result code (0=ok) + +example: dyndns_del("ns1.toto.com", "dyn.toto.com") +RFC2136 +""" + zone = name[name.find(".")+1:] + r=sr1(IP(dst=nameserver)/UDP()/DNS(opcode=5, + qd=[DNSQR(qname=zone, qtype="SOA")], + ns=[DNSRR(rrname=name, type=type, + rclass="ANY", ttl=0, rdata=b"")]), + verbose=0, timeout=5) + if r and r.haslayer(DNS): + return r.getlayer(DNS).rcode + else: + return -1 + + +class DNS_am(AnsweringMachine): + function_name="dns_spoof" + filter = "udp port 53" + + def parse_options(self, joker="192.168.1.1", match=None): + if match is None: + self.match = {} + else: + self.match = match + self.joker=joker + + def is_request(self, req): + return req.haslayer(DNS) and req.getlayer(DNS).qr == 0 + + def make_reply(self, req): + ip = req.getlayer(IP) + dns = req.getlayer(DNS) + resp = IP(dst=ip.src, src=ip.dst)/UDP(dport=ip.sport,sport=ip.dport) + rdata = self.match.get(dns.qd.qname, self.joker) + resp /= DNS(id=dns.id, qr=1, qd=dns.qd, + an=DNSRR(rrname=dns.qd.qname, ttl=10, rdata=rdata)) + return resp + + |