1 from scapy.fields import * 2 from scapy.packet import * 3 from scapy.layers.inet import UDP 4 from scapy.layers.dns import DNSQRField, DNSRRField, DNSRRCountField 5 6 """ 7 LLMNR (Link Local Multicast Node Resolution). 8 9 [RFC 4795] 10 """ 11 12 ############################################################################# 13 ### LLMNR (RFC4795) ### 14 ############################################################################# 15 # LLMNR is based on the DNS packet format (RFC1035 Section 4) 16 # RFC also envisions LLMNR over TCP. Like vista, we don't support it -- arno 17 18 _LLMNR_IPv6_mcast_Addr = "FF02:0:0:0:0:0:1:3" 19 _LLMNR_IPv4_mcast_addr = "224.0.0.252" 20 21 class LLMNRQuery(Packet): 22 name = "Link Local Multicast Node Resolution - Query" 23 fields_desc = [ ShortField("id", 0), 24 BitField("qr", 0, 1), 25 BitEnumField("opcode", 0, 4, { 0:"QUERY" }), 26 BitField("c", 0, 1), 27 BitField("tc", 0, 2), 28 BitField("z", 0, 4), 29 BitEnumField("rcode", 0, 4, { 0:"ok" }), 30 DNSRRCountField("qdcount", None, "qd"), 31 DNSRRCountField("ancount", None, "an"), 32 DNSRRCountField("nscount", None, "ns"), 33 DNSRRCountField("arcount", None, "ar"), 34 DNSQRField("qd", "qdcount"), 35 DNSRRField("an", "ancount"), 36 DNSRRField("ns", "nscount"), 37 DNSRRField("ar", "arcount",0)] 38 overload_fields = {UDP: {"sport": 5355, "dport": 5355 }} 39 def hashret(self): 40 return struct.pack("!H", self.id) 41 42 class LLMNRResponse(LLMNRQuery): 43 name = "Link Local Multicast Node Resolution - Response" 44 qr = 1 45 def answers(self, other): 46 return (isinstance(other, LLMNRQuery) and 47 self.id == other.id and 48 self.qr == 1 and 49 other.qr == 0) 50 51 def _llmnr_dispatcher(x, *args, **kargs): 52 cls = conf.raw_layer 53 if len(x) >= 2: 54 if (orb(x[2]) & 0x80): # Response 55 cls = LLMNRResponse 56 else: # Query 57 cls = LLMNRQuery 58 return cls(x, *args, **kargs) 59 60 bind_bottom_up(UDP, _llmnr_dispatcher, { "dport": 5355 }) 61 bind_bottom_up(UDP, _llmnr_dispatcher, { "sport": 5355 }) 62 63 # LLMNRQuery(id=RandShort(), qd=DNSQR(qname="vista."))) 64 65 66